From b4cd12c1c36f89328747a500f5ebbccbcc3b2a50 Mon Sep 17 00:00:00 2001 From: Daniel Rose Date: Sat, 26 Nov 2016 18:11:26 +0100 Subject: [PATCH 1/7] Fix handling of excluded branches. Pass on data, check that each branch is added only once. --- src/GitVersionCore/BranchConfigurationCalculator.cs | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/GitVersionCore/BranchConfigurationCalculator.cs b/src/GitVersionCore/BranchConfigurationCalculator.cs index 14f314cf94..10489ce7fa 100644 --- a/src/GitVersionCore/BranchConfigurationCalculator.cs +++ b/src/GitVersionCore/BranchConfigurationCalculator.cs @@ -83,7 +83,11 @@ static BranchConfig InheritBranchConfiguration(bool onlyEvaluateTrackedBranches, return (branchConfig.Length != 1) || (branchConfig.Length == 1 && branchConfig[0].Increment == IncrementStrategy.Inherit); }).ToList(); } - excludedBranches.ToList().ForEach(excludedInheritBranches.Add); + // Add new excluded branches. + foreach (var excludedBranch in excludedBranches.ExcludingBranches(excludedInheritBranches)) + { + excludedInheritBranches.Add(excludedBranch); + } var branchesToEvaluate = repository.Branches.Except(excludedInheritBranches).ToList(); var branchPoint = currentBranch.FindCommitBranchWasBranchedFrom(repository, excludedInheritBranches.ToArray()); @@ -144,7 +148,7 @@ static BranchConfig InheritBranchConfiguration(bool onlyEvaluateTrackedBranches, var branchName = chosenBranch.FriendlyName; Logger.WriteWarning(errorMessage + Environment.NewLine + Environment.NewLine + "Falling back to " + branchName + " branch config"); - var inheritingBranchConfig = GetBranchConfiguration(currentCommit, repository, onlyEvaluateTrackedBranches, config, chosenBranch); + var inheritingBranchConfig = GetBranchConfiguration(currentCommit, repository, onlyEvaluateTrackedBranches, config, chosenBranch, excludedInheritBranches); return new BranchConfig(branchConfiguration) { Increment = inheritingBranchConfig.Increment, From 59311f2988836ddc72435e791585d9ca6108f0c1 Mon Sep 17 00:00:00 2001 From: Daniel Rose Date: Sat, 26 Nov 2016 18:11:47 +0100 Subject: [PATCH 2/7] Break out of infinite loops when inheriting. --- src/GitVersionCore/BranchConfigurationCalculator.cs | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/GitVersionCore/BranchConfigurationCalculator.cs b/src/GitVersionCore/BranchConfigurationCalculator.cs index 10489ce7fa..629d60da63 100644 --- a/src/GitVersionCore/BranchConfigurationCalculator.cs +++ b/src/GitVersionCore/BranchConfigurationCalculator.cs @@ -148,6 +148,16 @@ static BranchConfig InheritBranchConfiguration(bool onlyEvaluateTrackedBranches, var branchName = chosenBranch.FriendlyName; Logger.WriteWarning(errorMessage + Environment.NewLine + Environment.NewLine + "Falling back to " + branchName + " branch config"); + // To prevent infinite loops, make sure that a new branch was chosen. + if (LibGitExtensions.IsSameBranch(currentBranch, chosenBranch)) + { + Logger.WriteWarning("Fallback branch wants to inherit Increment branch configuration from itself. Using patch increment instead."); + return new BranchConfig(branchConfiguration) + { + Increment = IncrementStrategy.Patch + }; + } + var inheritingBranchConfig = GetBranchConfiguration(currentCommit, repository, onlyEvaluateTrackedBranches, config, chosenBranch, excludedInheritBranches); return new BranchConfig(branchConfiguration) { From 9176303a7775481b1558716c5366840c15b5b0dd Mon Sep 17 00:00:00 2001 From: Daniel Rose Date: Fri, 25 Nov 2016 16:36:33 +0100 Subject: [PATCH 3/7] Cache the result of FindMergeBase(). --- src/GitVersionCore/LibGitExtensions.cs | 30 ++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/src/GitVersionCore/LibGitExtensions.cs b/src/GitVersionCore/LibGitExtensions.cs index 130cc91c76..8689965384 100644 --- a/src/GitVersionCore/LibGitExtensions.cs +++ b/src/GitVersionCore/LibGitExtensions.cs @@ -72,6 +72,8 @@ public static BranchCommit FindCommitBranchWasBranchedFrom([NotNull] this Branch } } + private static List cachedMergeBase = new List(); + /// /// Find the merge base of the two branches, i.e. the best common ancestor of the two branches' tips. /// @@ -79,6 +81,13 @@ public static Commit FindMergeBase(this Branch branch, Branch otherBranch, IRepo { using (Logger.IndentLog(string.Format("Finding merge base between '{0}' and '{1}'.", branch.FriendlyName, otherBranch.FriendlyName))) { + // Check the cache. + var cachedData = cachedMergeBase.FirstOrDefault(data => IsSameBranch(branch, data.Branch) && IsSameBranch(otherBranch, data.OtherBranch) && repository == data.Repository); + if (cachedData != null) + { + return cachedData.MergeBase; + } + // Otherbranch tip is a forward merge var commitToFindCommonBase = otherBranch.Tip; var commit = branch.Tip; @@ -113,6 +122,10 @@ public static Commit FindMergeBase(this Branch branch, Branch otherBranch, IRepo } } while (mergeBaseWasForwardMerge); } + + // Store in cache. + cachedMergeBase.Add(new MergeBaseData(branch, otherBranch, repository, findMergeBase)); + return findMergeBase; } } @@ -275,5 +288,22 @@ public static void CheckoutFilesIfExist(this IRepository repository, params stri } } } + + private class MergeBaseData + { + public Branch Branch { get; private set; } + public Branch OtherBranch { get; private set; } + public IRepository Repository { get; private set; } + + public Commit MergeBase { get; private set; } + + public MergeBaseData(Branch branch, Branch otherBranch, IRepository repository, Commit mergeBase) + { + Branch = branch; + OtherBranch = otherBranch; + Repository = repository; + MergeBase = mergeBase; + } + } } } From 1aa99a1c9b15e720dc4ef5d7a81f02715b11f9c6 Mon Sep 17 00:00:00 2001 From: Daniel Rose Date: Fri, 25 Nov 2016 16:51:51 +0100 Subject: [PATCH 4/7] Cache the data in FindCommitBranchWasBranchedFrom(). Clear the caches for each new run of GitVersion. --- src/GitVersionCore/GitVersionContext.cs | 3 ++ src/GitVersionCore/LibGitExtensions.cs | 46 +++++++++++++++++-------- 2 files changed, 35 insertions(+), 14 deletions(-) diff --git a/src/GitVersionCore/GitVersionContext.cs b/src/GitVersionCore/GitVersionContext.cs index 1e8c869866..6e04374225 100644 --- a/src/GitVersionCore/GitVersionContext.cs +++ b/src/GitVersionCore/GitVersionContext.cs @@ -16,6 +16,9 @@ public GitVersionContext(IRepository repository, Config configuration, bool isFo public GitVersionContext(IRepository repository, Branch currentBranch, Config configuration, bool onlyEvaluateTrackedBranches = true, string commitId = null) { + // With a new context, clear any in-memory caches. + LibGitExtensions.ClearInMemoryCache(); + Repository = repository; FullConfiguration = configuration; OnlyEvaluateTrackedBranches = onlyEvaluateTrackedBranches; diff --git a/src/GitVersionCore/LibGitExtensions.cs b/src/GitVersionCore/LibGitExtensions.cs index 8689965384..c6620a5cce 100644 --- a/src/GitVersionCore/LibGitExtensions.cs +++ b/src/GitVersionCore/LibGitExtensions.cs @@ -4,6 +4,7 @@ namespace GitVersion using System.Collections.Generic; using System.IO; using System.Linq; + using System.Runtime.CompilerServices; using JetBrains.Annotations; using LibGit2Sharp; @@ -32,6 +33,8 @@ public static IEnumerable GetVersionTagsOnBranch(this Branch br })); } + private static List cacheMergeBaseCommits; + /// /// Find the commit where the given branch was branched from another branch. /// If there are multiple such commits and branches, returns the newest commit. @@ -53,22 +56,22 @@ public static BranchCommit FindCommitBranchWasBranchedFrom([NotNull] this Branch return BranchCommit.Empty; } - var otherBranches = repository.Branches - .ExcludingBranches(excludedBranches) - .Where(b => !IsSameBranch(branch, b)); - var mergeBases = otherBranches.Select(otherBranch => + if (cacheMergeBaseCommits == null) { - if (otherBranch.Tip == null) + cacheMergeBaseCommits = repository.Branches.Select(otherBranch => { - Logger.WriteWarning(string.Format(missingTipFormat, otherBranch.FriendlyName)); - return BranchCommit.Empty; - } + if (otherBranch.Tip == null) + { + Logger.WriteWarning(string.Format(missingTipFormat, otherBranch.FriendlyName)); + return BranchCommit.Empty; + } - var findMergeBase = FindMergeBase(branch, otherBranch, repository); - return new BranchCommit(findMergeBase,otherBranch); - }).Where(b => b.Commit != null).OrderByDescending(b => b.Commit.Committer.When); + var findMergeBase = FindMergeBase(branch, otherBranch, repository); + return new BranchCommit(findMergeBase, otherBranch); + }).Where(b => b.Commit != null).OrderByDescending(b => b.Commit.Committer.When).ToList(); + } - return mergeBases.FirstOrDefault(); + return cacheMergeBaseCommits.ExcludingBranches(excludedBranches).FirstOrDefault(b => !IsSameBranch(branch, b.Branch)); } } @@ -146,6 +149,14 @@ public static bool IsSameBranch(Branch branch, Branch otherBranch) return otherBranchFriendlyName == branchFriendlyName; } + /// + /// Exclude the given branches (by value equality according to friendly name). + /// + public static IEnumerable ExcludingBranches([NotNull] this IEnumerable branches, [NotNull] IEnumerable branchesToExclude) + { + return branches.Where(b => branchesToExclude.All(bte => !IsSameBranch(b.Branch, bte))); + } + /// /// Exclude the given branches (by value equality according to friendly name). /// @@ -210,7 +221,7 @@ public static IEnumerable GetBranchesContainingCommit([NotNull] this Com public static GitObject PeeledTarget(this Tag tag) { GitObject cachedTarget; - if(_cachedPeeledTarget.TryGetValue(tag.Target.Sha, out cachedTarget)) + if (_cachedPeeledTarget.TryGetValue(tag.Target.Sha, out cachedTarget)) { return cachedTarget; } @@ -274,7 +285,7 @@ public static void CheckoutFilesIfExist(this IRepository repository, params stri } var fullPath = Path.Combine(repository.GetRepositoryDirectory(), fileName); - using (var stream = ((Blob) treeEntry.Target).GetContentStream()) + using (var stream = ((Blob)treeEntry.Target).GetContentStream()) { using (var streamReader = new BinaryReader(stream)) { @@ -289,6 +300,13 @@ public static void CheckoutFilesIfExist(this IRepository repository, params stri } } + internal static void ClearInMemoryCache() + { + cacheMergeBaseCommits = null; + cachedMergeBase.Clear(); + _cachedPeeledTarget.Clear(); + } + private class MergeBaseData { public Branch Branch { get; private set; } From 555f78bc742d27a8741eecd10bfca010a25f0088 Mon Sep 17 00:00:00 2001 From: Jake Ginnivan Date: Sun, 27 Nov 2016 12:45:08 +0800 Subject: [PATCH 5/7] Introduced a new class which builds cachable metadata about a git repository This makes the cache non-static and hopefully easier to maintain in the long wrong --- .../FeatureBranchScenarios.cs | 5 +- .../BranchConfigurationCalculator.cs | 39 +-- src/GitVersionCore/GitRepoMetadataProvider.cs | 222 ++++++++++++++++++ src/GitVersionCore/GitVersionContext.cs | 9 +- src/GitVersionCore/GitVersionCore.csproj | 1 + src/GitVersionCore/LibGitExtensions.cs | 203 +--------------- .../VersionInBranchNameBaseVersionStrategy.cs | 2 +- .../DevelopVersionStrategy.cs | 2 +- .../NextVersionCalculator.cs | 4 +- 9 files changed, 256 insertions(+), 231 deletions(-) create mode 100644 src/GitVersionCore/GitRepoMetadataProvider.cs diff --git a/src/GitVersionCore.Tests/IntegrationTests/FeatureBranchScenarios.cs b/src/GitVersionCore.Tests/IntegrationTests/FeatureBranchScenarios.cs index 5e65ab2c53..1867740b0c 100644 --- a/src/GitVersionCore.Tests/IntegrationTests/FeatureBranchScenarios.cs +++ b/src/GitVersionCore.Tests/IntegrationTests/FeatureBranchScenarios.cs @@ -514,9 +514,8 @@ public void PickUpVersionFromMasterMarkedWithIsTracksReleaseBranches() fixture.AssertFullSemver(config, "0.10.1-pre.1+1"); // create a feature branch from master and verify the version - // TODO this will pass once default becomes inherit - //fixture.BranchTo("MyFeatureD"); - //fixture.AssertFullSemver(config, "0.10.1-MyFeatureD.1+1"); + fixture.BranchTo("MyFeatureD"); + fixture.AssertFullSemver(config, "0.10.1-MyFeatureD.1+1"); } } } diff --git a/src/GitVersionCore/BranchConfigurationCalculator.cs b/src/GitVersionCore/BranchConfigurationCalculator.cs index 629d60da63..acd527e9e7 100644 --- a/src/GitVersionCore/BranchConfigurationCalculator.cs +++ b/src/GitVersionCore/BranchConfigurationCalculator.cs @@ -12,9 +12,9 @@ public class BranchConfigurationCalculator /// /// Gets the for the current commit. /// - public static BranchConfig GetBranchConfiguration(Commit currentCommit, IRepository repository, bool onlyEvaluateTrackedBranches, Config config, Branch currentBranch, IList excludedInheritBranches = null) + public static BranchConfig GetBranchConfiguration(GitVersionContext context, Branch targetBranch, IList excludedInheritBranches = null) { - var matchingBranches = LookupBranchConfiguration(config, currentBranch).ToArray(); + var matchingBranches = LookupBranchConfiguration(context.FullConfiguration, targetBranch).ToArray(); BranchConfig branchConfiguration; if (matchingBranches.Length > 0) @@ -25,7 +25,7 @@ public static BranchConfig GetBranchConfiguration(Commit currentCommit, IReposit { Logger.WriteWarning(string.Format( "Multiple branch configurations match the current branch branchName of '{0}'. Using the first matching configuration, '{1}'. Matching configurations include: '{2}'", - currentBranch.FriendlyName, + targetBranch.FriendlyName, branchConfiguration.Name, string.Join("', '", matchingBranches.Select(b => b.Name)))); } @@ -34,14 +34,14 @@ public static BranchConfig GetBranchConfiguration(Commit currentCommit, IReposit { Logger.WriteInfo(string.Format( "No branch configuration found for branch {0}, falling back to default configuration", - currentBranch.FriendlyName)); + targetBranch.FriendlyName)); branchConfiguration = new BranchConfig { Name = string.Empty }; - ConfigurationProvider.ApplyBranchDefaults(config, branchConfiguration, ""); + ConfigurationProvider.ApplyBranchDefaults(context.FullConfiguration, branchConfiguration, ""); } return branchConfiguration.Increment == IncrementStrategy.Inherit ? - InheritBranchConfiguration(onlyEvaluateTrackedBranches, repository, currentCommit, currentBranch, branchConfiguration, config, excludedInheritBranches) : + InheritBranchConfiguration(context, targetBranch, branchConfiguration, excludedInheritBranches) : branchConfiguration; } @@ -60,16 +60,18 @@ static IEnumerable LookupBranchConfiguration([NotNull] Config conf return config.Branches.Where(b => Regex.IsMatch(currentBranch.FriendlyName, "^" + b.Value.Regex, RegexOptions.IgnoreCase)).Select(kvp => kvp.Value); } - static BranchConfig InheritBranchConfiguration(bool onlyEvaluateTrackedBranches, IRepository repository, Commit currentCommit, Branch currentBranch, BranchConfig branchConfiguration, Config config, IList excludedInheritBranches) + static BranchConfig InheritBranchConfiguration(GitVersionContext context, Branch targetBranch, BranchConfig branchConfiguration, IList excludedInheritBranches) { + var repository = context.Repository; + var config = context.FullConfiguration; using (Logger.IndentLog("Attempting to inherit branch configuration from parent branch")) { - var excludedBranches = new[] { currentBranch }; + var excludedBranches = new[] { targetBranch }; // Check if we are a merge commit. If so likely we are a pull request - var parentCount = currentCommit.Parents.Count(); + var parentCount = context.CurrentCommit.Parents.Count(); if (parentCount == 2) { - excludedBranches = CalculateWhenMultipleParents(repository, currentCommit, ref currentBranch, excludedBranches); + excludedBranches = CalculateWhenMultipleParents(repository, context.CurrentCommit, ref targetBranch, excludedBranches); } if (excludedInheritBranches == null) @@ -90,11 +92,12 @@ static BranchConfig InheritBranchConfiguration(bool onlyEvaluateTrackedBranches, } var branchesToEvaluate = repository.Branches.Except(excludedInheritBranches).ToList(); - var branchPoint = currentBranch.FindCommitBranchWasBranchedFrom(repository, excludedInheritBranches.ToArray()); + var branchPoint = context.RepostioryMetadataProvider + .FindCommitBranchWasBranchedFrom(targetBranch, repository, excludedInheritBranches.ToArray()); List possibleParents; if (branchPoint == BranchCommit.Empty) { - possibleParents = currentCommit.GetBranchesContainingCommit(repository, branchesToEvaluate, true) + possibleParents = context.RepostioryMetadataProvider.GetBranchesContainingCommit(context.CurrentCommit, repository, branchesToEvaluate, true) // It fails to inherit Increment branch configuration if more than 1 parent; // therefore no point to get more than 2 parents .Take(2) @@ -102,10 +105,12 @@ static BranchConfig InheritBranchConfiguration(bool onlyEvaluateTrackedBranches, } else { - var branches = branchPoint.Commit.GetBranchesContainingCommit(repository, branchesToEvaluate, true).ToList(); + var branches = context.RepostioryMetadataProvider + .GetBranchesContainingCommit(branchPoint.Commit, repository, branchesToEvaluate, true).ToList(); if (branches.Count > 1) { - var currentTipBranches = currentCommit.GetBranchesContainingCommit(repository, branchesToEvaluate, true).ToList(); + var currentTipBranches = context.RepostioryMetadataProvider + .GetBranchesContainingCommit(context.CurrentCommit, repository, branchesToEvaluate, true).ToList(); possibleParents = branches.Except(currentTipBranches).ToList(); } else @@ -118,7 +123,7 @@ static BranchConfig InheritBranchConfiguration(bool onlyEvaluateTrackedBranches, if (possibleParents.Count == 1) { - var branchConfig = GetBranchConfiguration(currentCommit, repository, onlyEvaluateTrackedBranches, config, possibleParents[0], excludedInheritBranches); + var branchConfig = GetBranchConfiguration(context, possibleParents[0], excludedInheritBranches); return new BranchConfig(branchConfiguration) { Increment = branchConfig.Increment, @@ -149,7 +154,7 @@ static BranchConfig InheritBranchConfiguration(bool onlyEvaluateTrackedBranches, Logger.WriteWarning(errorMessage + Environment.NewLine + Environment.NewLine + "Falling back to " + branchName + " branch config"); // To prevent infinite loops, make sure that a new branch was chosen. - if (LibGitExtensions.IsSameBranch(currentBranch, chosenBranch)) + if (LibGitExtensions.IsSameBranch(targetBranch, chosenBranch)) { Logger.WriteWarning("Fallback branch wants to inherit Increment branch configuration from itself. Using patch increment instead."); return new BranchConfig(branchConfiguration) @@ -158,7 +163,7 @@ static BranchConfig InheritBranchConfiguration(bool onlyEvaluateTrackedBranches, }; } - var inheritingBranchConfig = GetBranchConfiguration(currentCommit, repository, onlyEvaluateTrackedBranches, config, chosenBranch, excludedInheritBranches); + var inheritingBranchConfig = GetBranchConfiguration(context, chosenBranch, excludedInheritBranches); return new BranchConfig(branchConfiguration) { Increment = inheritingBranchConfig.Increment, diff --git a/src/GitVersionCore/GitRepoMetadataProvider.cs b/src/GitVersionCore/GitRepoMetadataProvider.cs new file mode 100644 index 0000000000..085183a113 --- /dev/null +++ b/src/GitVersionCore/GitRepoMetadataProvider.cs @@ -0,0 +1,222 @@ +using JetBrains.Annotations; +using LibGit2Sharp; +using System; +using System.Collections.Generic; +using System.Linq; + +namespace GitVersion +{ + public class GitRepoMetadataProvider + { + private Dictionary> mergeBaseCommitsCache; + private Dictionary, MergeBaseData> mergeBaseCache; + private Dictionary> semanticVersionTagsOnBranchCache; + private IRepository repository; + const string missingTipFormat = "{0} has no tip. Please see http://example.com/docs for information on how to fix this."; + + + public GitRepoMetadataProvider(IRepository repository) + { + mergeBaseCache = new Dictionary, MergeBaseData>(); + mergeBaseCommitsCache = new Dictionary>(); + semanticVersionTagsOnBranchCache = new Dictionary>(); + this.repository = repository; + } + + public IEnumerable GetVersionTagsOnBranch(Branch branch, IRepository repository, string tagPrefixRegex) + { + if (semanticVersionTagsOnBranchCache.ContainsKey(branch)) + { + return semanticVersionTagsOnBranchCache[branch]; + } + var tags = repository.Tags.Select(t => t).ToList(); + + var versionTags = repository.Commits.QueryBy(new CommitFilter + { + IncludeReachableFrom = branch.Tip + }) + .SelectMany(c => tags.Where(t => c.Sha == t.Target.Sha).SelectMany(t => + { + SemanticVersion semver; + if (SemanticVersion.TryParse(t.FriendlyName, tagPrefixRegex, out semver)) + return new[] { semver }; + return new SemanticVersion[0]; + })).ToList(); + + semanticVersionTagsOnBranchCache.Add(branch, versionTags); + return versionTags; + } + + // TODO Should we cache this? + public IEnumerable GetBranchesContainingCommit([NotNull] Commit commit, IRepository repository, IList branches, bool onlyTrackedBranches) + { + if (commit == null) + { + throw new ArgumentNullException("commit"); + } + + using (Logger.IndentLog(string.Format("Getting branches containing the commit '{0}'.", commit.Id))) + { + var directBranchHasBeenFound = false; + Logger.WriteInfo("Trying to find direct branches."); + // TODO: It looks wasteful looping through the branches twice. Can't these loops be merged somehow? @asbjornu + foreach (var branch in branches) + { + if (branch.Tip != null && branch.Tip.Sha != commit.Sha || (onlyTrackedBranches && !branch.IsTracking)) + { + continue; + } + + directBranchHasBeenFound = true; + Logger.WriteInfo(string.Format("Direct branch found: '{0}'.", branch.FriendlyName)); + yield return branch; + } + + if (directBranchHasBeenFound) + { + yield break; + } + + Logger.WriteInfo(string.Format("No direct branches found, searching through {0} branches.", onlyTrackedBranches ? "tracked" : "all")); + foreach (var branch in branches.Where(b => onlyTrackedBranches && !b.IsTracking)) + { + Logger.WriteInfo(string.Format("Searching for commits reachable from '{0}'.", branch.FriendlyName)); + + var commits = repository.Commits.QueryBy(new CommitFilter + { + IncludeReachableFrom = branch + }).Where(c => c.Sha == commit.Sha); + + if (!commits.Any()) + { + Logger.WriteInfo(string.Format("The branch '{0}' has no matching commits.", branch.FriendlyName)); + continue; + } + + Logger.WriteInfo(string.Format("The branch '{0}' has a matching commit.", branch.FriendlyName)); + yield return branch; + } + } + } + + /// + /// Find the merge base of the two branches, i.e. the best common ancestor of the two branches' tips. + /// + public Commit FindMergeBase(Branch branch, Branch otherBranch, IRepository repository) + { + var key = Tuple.Create(branch, otherBranch); + + if (mergeBaseCache.ContainsKey(key)) + { + return mergeBaseCache[key].MergeBase; + } + + using (Logger.IndentLog(string.Format("Finding merge base between '{0}' and '{1}'.", branch.FriendlyName, otherBranch.FriendlyName))) + { + // Otherbranch tip is a forward merge + var commitToFindCommonBase = otherBranch.Tip; + var commit = branch.Tip; + if (otherBranch.Tip.Parents.Contains(commit)) + { + commitToFindCommonBase = otherBranch.Tip.Parents.First(); + } + + var findMergeBase = repository.ObjectDatabase.FindMergeBase(commit, commitToFindCommonBase); + if (findMergeBase != null) + { + Logger.WriteInfo(string.Format("Found merge base of {0}", findMergeBase.Sha)); + // We do not want to include merge base commits which got forward merged into the other branch + bool mergeBaseWasForwardMerge; + do + { + // Now make sure that the merge base is not a forward merge + mergeBaseWasForwardMerge = otherBranch.Commits + .SkipWhile(c => c != commitToFindCommonBase) + .TakeWhile(c => c != findMergeBase) + .Any(c => c.Parents.Contains(findMergeBase)); + if (mergeBaseWasForwardMerge) + { + var second = commitToFindCommonBase.Parents.First(); + var mergeBase = repository.ObjectDatabase.FindMergeBase(commit, second); + if (mergeBase == findMergeBase) + { + break; + } + findMergeBase = mergeBase; + Logger.WriteInfo(string.Format("Merge base was due to a forward merge, next merge base is {0}", findMergeBase)); + } + } while (mergeBaseWasForwardMerge); + } + + // Store in cache. + mergeBaseCache.Add(key, new MergeBaseData(branch, otherBranch, repository, findMergeBase)); + + return findMergeBase; + } + } + + /// + /// Find the commit where the given branch was branched from another branch. + /// If there are multiple such commits and branches, returns the newest commit. + /// + public BranchCommit FindCommitBranchWasBranchedFrom([NotNull] Branch branch, IRepository repository, params Branch[] excludedBranches) + { + if (branch == null) + { + throw new ArgumentNullException("branch"); + } + + using (Logger.IndentLog(string.Format("Finding branch source of '{0}'", branch.FriendlyName))) + { + if (branch.Tip == null) + { + Logger.WriteWarning(string.Format(missingTipFormat, branch.FriendlyName)); + return BranchCommit.Empty; + } + + return GetMergeCommitsForBranch(branch).ExcludingBranches(excludedBranches).FirstOrDefault(b => !branch.IsSameBranch(b.Branch)); + } + } + + + List GetMergeCommitsForBranch(Branch branch) + { + if (mergeBaseCommitsCache.ContainsKey(branch)) + { + return mergeBaseCommitsCache[branch]; + } + + var branchMergeBases = repository.Branches.Select(otherBranch => + { + if (otherBranch.Tip == null) + { + Logger.WriteWarning(string.Format(missingTipFormat, otherBranch.FriendlyName)); + return BranchCommit.Empty; + } + + var findMergeBase = FindMergeBase(branch, otherBranch, repository); + return new BranchCommit(findMergeBase, otherBranch); + }).Where(b => b.Commit != null).OrderByDescending(b => b.Commit.Committer.When).ToList(); + mergeBaseCommitsCache.Add(branch, branchMergeBases); + + return branchMergeBases; + } + + private class MergeBaseData + { + public Branch Branch { get; private set; } + public Branch OtherBranch { get; private set; } + public IRepository Repository { get; private set; } + + public Commit MergeBase { get; private set; } + + public MergeBaseData(Branch branch, Branch otherBranch, IRepository repository, Commit mergeBase) + { + Branch = branch; + OtherBranch = otherBranch; + Repository = repository; + MergeBase = mergeBase; + } + } + } +} \ No newline at end of file diff --git a/src/GitVersionCore/GitVersionContext.cs b/src/GitVersionCore/GitVersionContext.cs index 6e04374225..c3c9be5db7 100644 --- a/src/GitVersionCore/GitVersionContext.cs +++ b/src/GitVersionCore/GitVersionContext.cs @@ -16,10 +16,8 @@ public GitVersionContext(IRepository repository, Config configuration, bool isFo public GitVersionContext(IRepository repository, Branch currentBranch, Config configuration, bool onlyEvaluateTrackedBranches = true, string commitId = null) { - // With a new context, clear any in-memory caches. - LibGitExtensions.ClearInMemoryCache(); - Repository = repository; + RepostioryMetadataProvider = new GitRepoMetadataProvider(repository); FullConfiguration = configuration; OnlyEvaluateTrackedBranches = onlyEvaluateTrackedBranches; @@ -49,7 +47,7 @@ public GitVersionContext(IRepository repository, Branch currentBranch, Config co if (currentBranch.IsDetachedHead()) { - CurrentBranch = CurrentCommit.GetBranchesContainingCommit(repository, repository.Branches.ToList(), OnlyEvaluateTrackedBranches).OnlyOrDefault() ?? currentBranch; + CurrentBranch = RepostioryMetadataProvider.GetBranchesContainingCommit(CurrentCommit, repository, repository.Branches.ToList(), OnlyEvaluateTrackedBranches).OnlyOrDefault() ?? currentBranch; } else { @@ -81,10 +79,11 @@ public GitVersionContext(IRepository repository, Branch currentBranch, Config co public Branch CurrentBranch { get; private set; } public Commit CurrentCommit { get; private set; } public bool IsCurrentCommitTagged { get; private set; } + public GitRepoMetadataProvider RepostioryMetadataProvider { get; private set; } void CalculateEffectiveConfiguration() { - var currentBranchConfig = BranchConfigurationCalculator.GetBranchConfiguration(CurrentCommit, Repository, OnlyEvaluateTrackedBranches, FullConfiguration, CurrentBranch); + var currentBranchConfig = BranchConfigurationCalculator.GetBranchConfiguration(this, CurrentBranch); if (!currentBranchConfig.VersioningMode.HasValue) throw new Exception(string.Format("Configuration value for 'Versioning mode' for branch {0} has no value. (this should not happen, please report an issue)", currentBranchConfig.Name)); diff --git a/src/GitVersionCore/GitVersionCore.csproj b/src/GitVersionCore/GitVersionCore.csproj index 57d35345e1..ef715fea33 100644 --- a/src/GitVersionCore/GitVersionCore.csproj +++ b/src/GitVersionCore/GitVersionCore.csproj @@ -122,6 +122,7 @@ + diff --git a/src/GitVersionCore/LibGitExtensions.cs b/src/GitVersionCore/LibGitExtensions.cs index c6620a5cce..3f009112f0 100644 --- a/src/GitVersionCore/LibGitExtensions.cs +++ b/src/GitVersionCore/LibGitExtensions.cs @@ -4,7 +4,6 @@ namespace GitVersion using System.Collections.Generic; using System.IO; using System.Linq; - using System.Runtime.CompilerServices; using JetBrains.Annotations; using LibGit2Sharp; @@ -16,127 +15,10 @@ public static DateTimeOffset When(this Commit commit) return commit.Committer.When; } - public static IEnumerable GetVersionTagsOnBranch(this Branch branch, IRepository repository, string tagPrefixRegex) - { - var tags = repository.Tags.Select(t => t).ToList(); - - return repository.Commits.QueryBy(new CommitFilter - { - IncludeReachableFrom = branch.Tip - }) - .SelectMany(c => tags.Where(t => c.Sha == t.Target.Sha).SelectMany(t => - { - SemanticVersion semver; - if (SemanticVersion.TryParse(t.FriendlyName, tagPrefixRegex, out semver)) - return new [] { semver }; - return new SemanticVersion[0]; - })); - } - - private static List cacheMergeBaseCommits; - - /// - /// Find the commit where the given branch was branched from another branch. - /// If there are multiple such commits and branches, returns the newest commit. - /// - public static BranchCommit FindCommitBranchWasBranchedFrom([NotNull] this Branch branch, IRepository repository, params Branch[] excludedBranches) - { - const string missingTipFormat = "{0} has no tip. Please see http://example.com/docs for information on how to fix this."; - - if (branch == null) - { - throw new ArgumentNullException("branch"); - } - - using (Logger.IndentLog(string.Format("Finding branch source of '{0}'", branch.FriendlyName))) - { - if (branch.Tip == null) - { - Logger.WriteWarning(string.Format(missingTipFormat, branch.FriendlyName)); - return BranchCommit.Empty; - } - - if (cacheMergeBaseCommits == null) - { - cacheMergeBaseCommits = repository.Branches.Select(otherBranch => - { - if (otherBranch.Tip == null) - { - Logger.WriteWarning(string.Format(missingTipFormat, otherBranch.FriendlyName)); - return BranchCommit.Empty; - } - - var findMergeBase = FindMergeBase(branch, otherBranch, repository); - return new BranchCommit(findMergeBase, otherBranch); - }).Where(b => b.Commit != null).OrderByDescending(b => b.Commit.Committer.When).ToList(); - } - - return cacheMergeBaseCommits.ExcludingBranches(excludedBranches).FirstOrDefault(b => !IsSameBranch(branch, b.Branch)); - } - } - - private static List cachedMergeBase = new List(); - - /// - /// Find the merge base of the two branches, i.e. the best common ancestor of the two branches' tips. - /// - public static Commit FindMergeBase(this Branch branch, Branch otherBranch, IRepository repository) - { - using (Logger.IndentLog(string.Format("Finding merge base between '{0}' and '{1}'.", branch.FriendlyName, otherBranch.FriendlyName))) - { - // Check the cache. - var cachedData = cachedMergeBase.FirstOrDefault(data => IsSameBranch(branch, data.Branch) && IsSameBranch(otherBranch, data.OtherBranch) && repository == data.Repository); - if (cachedData != null) - { - return cachedData.MergeBase; - } - - // Otherbranch tip is a forward merge - var commitToFindCommonBase = otherBranch.Tip; - var commit = branch.Tip; - if (otherBranch.Tip.Parents.Contains(commit)) - { - commitToFindCommonBase = otherBranch.Tip.Parents.First(); - } - - var findMergeBase = repository.ObjectDatabase.FindMergeBase(commit, commitToFindCommonBase); - if (findMergeBase != null) - { - Logger.WriteInfo(string.Format("Found merge base of {0}", findMergeBase.Sha)); - // We do not want to include merge base commits which got forward merged into the other branch - bool mergeBaseWasForwardMerge; - do - { - // Now make sure that the merge base is not a forward merge - mergeBaseWasForwardMerge = otherBranch.Commits - .SkipWhile(c => c != commitToFindCommonBase) - .TakeWhile(c => c != findMergeBase) - .Any(c => c.Parents.Contains(findMergeBase)); - if (mergeBaseWasForwardMerge) - { - var second = commitToFindCommonBase.Parents.First(); - var mergeBase = repository.ObjectDatabase.FindMergeBase(commit, second); - if (mergeBase == findMergeBase) - { - break; - } - findMergeBase = mergeBase; - Logger.WriteInfo(string.Format("Merge base was due to a forward merge, next merge base is {0}", findMergeBase)); - } - } while (mergeBaseWasForwardMerge); - } - - // Store in cache. - cachedMergeBase.Add(new MergeBaseData(branch, otherBranch, repository, findMergeBase)); - - return findMergeBase; - } - } - /// /// Checks if the two branch objects refer to the same branch (have the same friendly name). /// - public static bool IsSameBranch(Branch branch, Branch otherBranch) + public static bool IsSameBranch(this Branch branch, Branch otherBranch) { // For each branch, fixup the friendly name if the branch is remote. var otherBranchFriendlyName = otherBranch.IsRemote ? @@ -165,73 +47,14 @@ public static IEnumerable ExcludingBranches([NotNull] this IEnumerable branchesToExclude.All(bte => !IsSameBranch(b, bte))); } - public static IEnumerable GetBranchesContainingCommit([NotNull] this Commit commit, IRepository repository, IList branches, bool onlyTrackedBranches) - { - if (commit == null) - { - throw new ArgumentNullException("commit"); - } - - using (Logger.IndentLog(string.Format("Getting branches containing the commit '{0}'.", commit.Id))) - { - var directBranchHasBeenFound = false; - Logger.WriteInfo("Trying to find direct branches."); - // TODO: It looks wasteful looping through the branches twice. Can't these loops be merged somehow? @asbjornu - foreach (var branch in branches) - { - if (branch.Tip != null && branch.Tip.Sha != commit.Sha || (onlyTrackedBranches && !branch.IsTracking)) - { - continue; - } - - directBranchHasBeenFound = true; - Logger.WriteInfo(string.Format("Direct branch found: '{0}'.", branch.FriendlyName)); - yield return branch; - } - - if (directBranchHasBeenFound) - { - yield break; - } - - Logger.WriteInfo(string.Format("No direct branches found, searching through {0} branches.", onlyTrackedBranches ? "tracked" : "all")); - foreach (var branch in branches.Where(b => onlyTrackedBranches && !b.IsTracking)) - { - Logger.WriteInfo(string.Format("Searching for commits reachable from '{0}'.", branch.FriendlyName)); - - var commits = repository.Commits.QueryBy(new CommitFilter - { - IncludeReachableFrom = branch - }).Where(c => c.Sha == commit.Sha); - - if (!commits.Any()) - { - Logger.WriteInfo(string.Format("The branch '{0}' has no matching commits.", branch.FriendlyName)); - continue; - } - - Logger.WriteInfo(string.Format("The branch '{0}' has a matching commit.", branch.FriendlyName)); - yield return branch; - } - } - } - - private static Dictionary _cachedPeeledTarget = new Dictionary(); - public static GitObject PeeledTarget(this Tag tag) { - GitObject cachedTarget; - if (_cachedPeeledTarget.TryGetValue(tag.Target.Sha, out cachedTarget)) - { - return cachedTarget; - } var target = tag.Target; while (target is TagAnnotation) { target = ((TagAnnotation)(target)).Target; } - _cachedPeeledTarget.Add(tag.Target.Sha, target); return target; } @@ -299,29 +122,5 @@ public static void CheckoutFilesIfExist(this IRepository repository, params stri } } } - - internal static void ClearInMemoryCache() - { - cacheMergeBaseCommits = null; - cachedMergeBase.Clear(); - _cachedPeeledTarget.Clear(); - } - - private class MergeBaseData - { - public Branch Branch { get; private set; } - public Branch OtherBranch { get; private set; } - public IRepository Repository { get; private set; } - - public Commit MergeBase { get; private set; } - - public MergeBaseData(Branch branch, Branch otherBranch, IRepository repository, Commit mergeBase) - { - Branch = branch; - OtherBranch = otherBranch; - Repository = repository; - MergeBase = mergeBase; - } - } } } diff --git a/src/GitVersionCore/VersionCalculation/BaseVersionCalculators/VersionInBranchNameBaseVersionStrategy.cs b/src/GitVersionCore/VersionCalculation/BaseVersionCalculators/VersionInBranchNameBaseVersionStrategy.cs index 89a6ff7cf8..979bcaa51b 100644 --- a/src/GitVersionCore/VersionCalculation/BaseVersionCalculators/VersionInBranchNameBaseVersionStrategy.cs +++ b/src/GitVersionCore/VersionCalculation/BaseVersionCalculators/VersionInBranchNameBaseVersionStrategy.cs @@ -25,7 +25,7 @@ public IEnumerable GetVersions(GitVersionContext context, string ta var versionInBranch = GetVersionInBranch(branchName, tagPrefixRegex); if (versionInBranch != null) { - var commitBranchWasBranchedFrom = currentBranch.FindCommitBranchWasBranchedFrom(repository); + var commitBranchWasBranchedFrom = context.RepostioryMetadataProvider.FindCommitBranchWasBranchedFrom(currentBranch, repository); var branchNameOverride = branchName.RegexReplace("[-/]" + versionInBranch.Item1, string.Empty); yield return new BaseVersion(context, "Version in branch name", false, versionInBranch.Item2, commitBranchWasBranchedFrom.Commit, branchNameOverride); } diff --git a/src/GitVersionCore/VersionCalculation/DevelopVersionStrategy.cs b/src/GitVersionCore/VersionCalculation/DevelopVersionStrategy.cs index 71e1591bb5..000c03fd1d 100644 --- a/src/GitVersionCore/VersionCalculation/DevelopVersionStrategy.cs +++ b/src/GitVersionCore/VersionCalculation/DevelopVersionStrategy.cs @@ -84,7 +84,7 @@ IEnumerable GetReleaseVersion(GitVersionContext context, Branch rel var repository = context.Repository; // Find the commit where the child branch was created. - var baseSource = releaseBranch.FindMergeBase(context.CurrentBranch, repository); + var baseSource = context.RepostioryMetadataProvider.FindMergeBase(releaseBranch, context.CurrentBranch, repository); if (baseSource == context.CurrentCommit) { // Ignore the branch if it has no commits. diff --git a/src/GitVersionCore/VersionCalculation/NextVersionCalculator.cs b/src/GitVersionCore/VersionCalculation/NextVersionCalculator.cs index 03ac5325eb..348a57f659 100644 --- a/src/GitVersionCore/VersionCalculation/NextVersionCalculator.cs +++ b/src/GitVersionCore/VersionCalculation/NextVersionCalculator.cs @@ -258,8 +258,8 @@ void UpdatePreReleaseTag(GitVersionContext context, SemanticVersion semanticVers int? number = null; - var lastTag = context.CurrentBranch - .GetVersionTagsOnBranch(context.Repository, context.Configuration.GitTagPrefix) + var lastTag = context.RepostioryMetadataProvider + .GetVersionTagsOnBranch(context.CurrentBranch, context.Repository, context.Configuration.GitTagPrefix) .FirstOrDefault(v => v.PreReleaseTag.Name == tagToUse); if (lastTag != null && From 179c8495c141bc2b72aee79fcc619a470e00c6f3 Mon Sep 17 00:00:00 2001 From: Jake Ginnivan Date: Sun, 27 Nov 2016 21:23:46 +0800 Subject: [PATCH 6/7] Added some debug messages --- src/GitVersionCore/GitRepoMetadataProvider.cs | 41 ++++++++++++------- .../GitVersionCacheKeyFactory.cs | 10 ++++- src/GitVersionCore/GitVersionFinder.cs | 5 ++- .../GitVersionTaskDirectoryTests.cs | 1 + 4 files changed, 40 insertions(+), 17 deletions(-) diff --git a/src/GitVersionCore/GitRepoMetadataProvider.cs b/src/GitVersionCore/GitRepoMetadataProvider.cs index 085183a113..710a8a7fa9 100644 --- a/src/GitVersionCore/GitRepoMetadataProvider.cs +++ b/src/GitVersionCore/GitRepoMetadataProvider.cs @@ -27,24 +27,29 @@ public IEnumerable GetVersionTagsOnBranch(Branch branch, IRepos { if (semanticVersionTagsOnBranchCache.ContainsKey(branch)) { + Logger.WriteDebug(string.Format("Cache hit for version tags on branch '{0}", branch.CanonicalName)); return semanticVersionTagsOnBranchCache[branch]; } - var tags = repository.Tags.Select(t => t).ToList(); - var versionTags = repository.Commits.QueryBy(new CommitFilter + using (Logger.IndentLog(string.Format("Getting version tags from branch '{0}'.", branch.CanonicalName))) { - IncludeReachableFrom = branch.Tip - }) - .SelectMany(c => tags.Where(t => c.Sha == t.Target.Sha).SelectMany(t => - { - SemanticVersion semver; - if (SemanticVersion.TryParse(t.FriendlyName, tagPrefixRegex, out semver)) - return new[] { semver }; - return new SemanticVersion[0]; - })).ToList(); - - semanticVersionTagsOnBranchCache.Add(branch, versionTags); - return versionTags; + var tags = repository.Tags.Select(t => t).ToList(); + + var versionTags = repository.Commits.QueryBy(new CommitFilter + { + IncludeReachableFrom = branch.Tip + }) + .SelectMany(c => tags.Where(t => c.Sha == t.Target.Sha).SelectMany(t => + { + SemanticVersion semver; + if (SemanticVersion.TryParse(t.FriendlyName, tagPrefixRegex, out semver)) + return new[] { semver }; + return new SemanticVersion[0]; + })).ToList(); + + semanticVersionTagsOnBranchCache.Add(branch, versionTags); + return versionTags; + } } // TODO Should we cache this? @@ -54,7 +59,7 @@ public IEnumerable GetBranchesContainingCommit([NotNull] Commit commit, { throw new ArgumentNullException("commit"); } - + Logger.WriteDebug("Heh"); using (Logger.IndentLog(string.Format("Getting branches containing the commit '{0}'.", commit.Id))) { var directBranchHasBeenFound = false; @@ -108,6 +113,9 @@ public Commit FindMergeBase(Branch branch, Branch otherBranch, IRepository repos if (mergeBaseCache.ContainsKey(key)) { + Logger.WriteDebug(string.Format( + "Cache hit for merge base between '{0}' and '{1}'.", + branch.FriendlyName, otherBranch.FriendlyName)); return mergeBaseCache[key].MergeBase; } @@ -183,6 +191,9 @@ List GetMergeCommitsForBranch(Branch branch) { if (mergeBaseCommitsCache.ContainsKey(branch)) { + Logger.WriteDebug(string.Format( + "Cache hit for getting merge commits for branch {0}.", + branch.CanonicalName)); return mergeBaseCommitsCache[branch]; } diff --git a/src/GitVersionCore/GitVersionCacheKeyFactory.cs b/src/GitVersionCore/GitVersionCacheKeyFactory.cs index f81dea37ee..a918d67001 100644 --- a/src/GitVersionCore/GitVersionCacheKeyFactory.cs +++ b/src/GitVersionCore/GitVersionCacheKeyFactory.cs @@ -123,7 +123,15 @@ static List CalculateDirectoryContents(string root) private static string GetRepositorySnapshotHash(GitPreparer gitPreparer) { - var repositorySnapshot = gitPreparer.WithRepository(repo => string.Join(":", repo.Head.CanonicalName, repo.Head.Tip.Sha)); + var repositorySnapshot = gitPreparer.WithRepository(repo => { + var head = repo.Head; + if (head.Tip == null) + { + return head.CanonicalName; + } + var hash = string.Join(":", head.CanonicalName, head.Tip.Sha); + return hash; + }); return GetHash(repositorySnapshot); } diff --git a/src/GitVersionCore/GitVersionFinder.cs b/src/GitVersionCore/GitVersionFinder.cs index 926a421933..4163d23a62 100644 --- a/src/GitVersionCore/GitVersionFinder.cs +++ b/src/GitVersionCore/GitVersionFinder.cs @@ -8,7 +8,10 @@ public class GitVersionFinder { public SemanticVersion FindVersion(GitVersionContext context) { - Logger.WriteInfo(string.Format("Running against branch: {0} ({1})", context.CurrentBranch.FriendlyName, context.CurrentCommit.Sha)); + Logger.WriteInfo(string.Format( + "Running against branch: {0} ({1})", + context.CurrentBranch.FriendlyName, + context.CurrentCommit == null ? "-" : context.CurrentCommit.Sha)); EnsureMainTopologyConstraints(context); var filePath = Path.Combine(context.Repository.GetRepositoryDirectory(), "NextVersion.txt"); diff --git a/src/GitVersionTask.Tests/GitVersionTaskDirectoryTests.cs b/src/GitVersionTask.Tests/GitVersionTaskDirectoryTests.cs index 497b59526d..9ba0c96cfc 100644 --- a/src/GitVersionTask.Tests/GitVersionTaskDirectoryTests.cs +++ b/src/GitVersionTask.Tests/GitVersionTaskDirectoryTests.cs @@ -61,6 +61,7 @@ public void Finds_GitDirectory_In_Parent() } catch (Exception ex) { + // TODO I think this test is wrong.. It throws a different exception // `RepositoryNotFoundException` means that it couldn't find the .git directory, // any other exception means that the .git was found but there was some other issue that this test doesn't care about. Assert.IsNotAssignableFrom(ex); From d8c600acfcbb143a78797f33d32feb7bdda645f7 Mon Sep 17 00:00:00 2001 From: Daniel Rose Date: Mon, 28 Nov 2016 12:01:17 +0100 Subject: [PATCH 7/7] Cleanup. Fix typos, remove unused usings, invoke extension methods properly. --- .../ConfigProviderTests.cs | 4 +-- .../BranchConfigurationCalculator.cs | 16 +++++----- .../Configuration/ConfigurationProvider.cs | 1 - src/GitVersionCore/GitRepoMetadataProvider.cs | 32 +++++++++---------- src/GitVersionCore/GitVersionContext.cs | 6 ++-- .../VersionInBranchNameBaseVersionStrategy.cs | 2 +- .../DevelopVersionStrategy.cs | 4 +-- .../NextVersionCalculator.cs | 4 +-- 8 files changed, 33 insertions(+), 36 deletions(-) diff --git a/src/GitVersionCore.Tests/ConfigProviderTests.cs b/src/GitVersionCore.Tests/ConfigProviderTests.cs index 008862d405..e4dfdd5710 100644 --- a/src/GitVersionCore.Tests/ConfigProviderTests.cs +++ b/src/GitVersionCore.Tests/ConfigProviderTests.cs @@ -322,7 +322,7 @@ public void WarnOnObsoleteIsDevelopBranchConfigurationSetting() LegacyConfigNotifier.Notify(new StringReader(text)); }); - var expecedMessage = string.Format("'is-develop' is deprecated, use 'track-release-branches' instead."); - exception.Message.ShouldContain(expecedMessage); + const string expectedMessage = @"'is-develop' is deprecated, use 'track-release-branches' instead."; + exception.Message.ShouldContain(expectedMessage); } } diff --git a/src/GitVersionCore/BranchConfigurationCalculator.cs b/src/GitVersionCore/BranchConfigurationCalculator.cs index acd527e9e7..e6e05d3489 100644 --- a/src/GitVersionCore/BranchConfigurationCalculator.cs +++ b/src/GitVersionCore/BranchConfigurationCalculator.cs @@ -92,12 +92,12 @@ static BranchConfig InheritBranchConfiguration(GitVersionContext context, Branch } var branchesToEvaluate = repository.Branches.Except(excludedInheritBranches).ToList(); - var branchPoint = context.RepostioryMetadataProvider - .FindCommitBranchWasBranchedFrom(targetBranch, repository, excludedInheritBranches.ToArray()); + var branchPoint = context.RepositoryMetadataProvider + .FindCommitBranchWasBranchedFrom(targetBranch, excludedInheritBranches.ToArray()); List possibleParents; if (branchPoint == BranchCommit.Empty) { - possibleParents = context.RepostioryMetadataProvider.GetBranchesContainingCommit(context.CurrentCommit, repository, branchesToEvaluate, true) + possibleParents = context.RepositoryMetadataProvider.GetBranchesContainingCommit(context.CurrentCommit, branchesToEvaluate, true) // It fails to inherit Increment branch configuration if more than 1 parent; // therefore no point to get more than 2 parents .Take(2) @@ -105,12 +105,12 @@ static BranchConfig InheritBranchConfiguration(GitVersionContext context, Branch } else { - var branches = context.RepostioryMetadataProvider - .GetBranchesContainingCommit(branchPoint.Commit, repository, branchesToEvaluate, true).ToList(); + var branches = context.RepositoryMetadataProvider + .GetBranchesContainingCommit(branchPoint.Commit, branchesToEvaluate, true).ToList(); if (branches.Count > 1) { - var currentTipBranches = context.RepostioryMetadataProvider - .GetBranchesContainingCommit(context.CurrentCommit, repository, branchesToEvaluate, true).ToList(); + var currentTipBranches = context.RepositoryMetadataProvider + .GetBranchesContainingCommit(context.CurrentCommit, branchesToEvaluate, true).ToList(); possibleParents = branches.Except(currentTipBranches).ToList(); } else @@ -154,7 +154,7 @@ static BranchConfig InheritBranchConfiguration(GitVersionContext context, Branch Logger.WriteWarning(errorMessage + Environment.NewLine + Environment.NewLine + "Falling back to " + branchName + " branch config"); // To prevent infinite loops, make sure that a new branch was chosen. - if (LibGitExtensions.IsSameBranch(targetBranch, chosenBranch)) + if (targetBranch.IsSameBranch(chosenBranch)) { Logger.WriteWarning("Fallback branch wants to inherit Increment branch configuration from itself. Using patch increment instead."); return new BranchConfig(branchConfiguration) diff --git a/src/GitVersionCore/Configuration/ConfigurationProvider.cs b/src/GitVersionCore/Configuration/ConfigurationProvider.cs index 4801c7d879..3d803d3fd3 100644 --- a/src/GitVersionCore/Configuration/ConfigurationProvider.cs +++ b/src/GitVersionCore/Configuration/ConfigurationProvider.cs @@ -2,7 +2,6 @@ namespace GitVersion { using Configuration.Init.Wizard; using GitVersion.Helpers; - using System; using System.IO; using System.Linq; using System.Text; diff --git a/src/GitVersionCore/GitRepoMetadataProvider.cs b/src/GitVersionCore/GitRepoMetadataProvider.cs index 710a8a7fa9..4f329e22f9 100644 --- a/src/GitVersionCore/GitRepoMetadataProvider.cs +++ b/src/GitVersionCore/GitRepoMetadataProvider.cs @@ -11,19 +11,18 @@ public class GitRepoMetadataProvider private Dictionary> mergeBaseCommitsCache; private Dictionary, MergeBaseData> mergeBaseCache; private Dictionary> semanticVersionTagsOnBranchCache; - private IRepository repository; + private IRepository Repository { get; set; } const string missingTipFormat = "{0} has no tip. Please see http://example.com/docs for information on how to fix this."; - public GitRepoMetadataProvider(IRepository repository) { mergeBaseCache = new Dictionary, MergeBaseData>(); mergeBaseCommitsCache = new Dictionary>(); semanticVersionTagsOnBranchCache = new Dictionary>(); - this.repository = repository; + this.Repository = repository; } - public IEnumerable GetVersionTagsOnBranch(Branch branch, IRepository repository, string tagPrefixRegex) + public IEnumerable GetVersionTagsOnBranch(Branch branch, string tagPrefixRegex) { if (semanticVersionTagsOnBranchCache.ContainsKey(branch)) { @@ -33,9 +32,9 @@ public IEnumerable GetVersionTagsOnBranch(Branch branch, IRepos using (Logger.IndentLog(string.Format("Getting version tags from branch '{0}'.", branch.CanonicalName))) { - var tags = repository.Tags.Select(t => t).ToList(); + var tags = this.Repository.Tags.Select(t => t).ToList(); - var versionTags = repository.Commits.QueryBy(new CommitFilter + var versionTags = this.Repository.Commits.QueryBy(new CommitFilter { IncludeReachableFrom = branch.Tip }) @@ -53,13 +52,13 @@ public IEnumerable GetVersionTagsOnBranch(Branch branch, IRepos } // TODO Should we cache this? - public IEnumerable GetBranchesContainingCommit([NotNull] Commit commit, IRepository repository, IList branches, bool onlyTrackedBranches) + public IEnumerable GetBranchesContainingCommit([NotNull] Commit commit, IList branches, bool onlyTrackedBranches) { if (commit == null) { throw new ArgumentNullException("commit"); } - Logger.WriteDebug("Heh"); + using (Logger.IndentLog(string.Format("Getting branches containing the commit '{0}'.", commit.Id))) { var directBranchHasBeenFound = false; @@ -87,7 +86,7 @@ public IEnumerable GetBranchesContainingCommit([NotNull] Commit commit, { Logger.WriteInfo(string.Format("Searching for commits reachable from '{0}'.", branch.FriendlyName)); - var commits = repository.Commits.QueryBy(new CommitFilter + var commits = this.Repository.Commits.QueryBy(new CommitFilter { IncludeReachableFrom = branch }).Where(c => c.Sha == commit.Sha); @@ -107,7 +106,7 @@ public IEnumerable GetBranchesContainingCommit([NotNull] Commit commit, /// /// Find the merge base of the two branches, i.e. the best common ancestor of the two branches' tips. /// - public Commit FindMergeBase(Branch branch, Branch otherBranch, IRepository repository) + public Commit FindMergeBase(Branch branch, Branch otherBranch) { var key = Tuple.Create(branch, otherBranch); @@ -129,7 +128,7 @@ public Commit FindMergeBase(Branch branch, Branch otherBranch, IRepository repos commitToFindCommonBase = otherBranch.Tip.Parents.First(); } - var findMergeBase = repository.ObjectDatabase.FindMergeBase(commit, commitToFindCommonBase); + var findMergeBase = this.Repository.ObjectDatabase.FindMergeBase(commit, commitToFindCommonBase); if (findMergeBase != null) { Logger.WriteInfo(string.Format("Found merge base of {0}", findMergeBase.Sha)); @@ -145,7 +144,7 @@ public Commit FindMergeBase(Branch branch, Branch otherBranch, IRepository repos if (mergeBaseWasForwardMerge) { var second = commitToFindCommonBase.Parents.First(); - var mergeBase = repository.ObjectDatabase.FindMergeBase(commit, second); + var mergeBase = this.Repository.ObjectDatabase.FindMergeBase(commit, second); if (mergeBase == findMergeBase) { break; @@ -157,7 +156,7 @@ public Commit FindMergeBase(Branch branch, Branch otherBranch, IRepository repos } // Store in cache. - mergeBaseCache.Add(key, new MergeBaseData(branch, otherBranch, repository, findMergeBase)); + mergeBaseCache.Add(key, new MergeBaseData(branch, otherBranch, this.Repository, findMergeBase)); return findMergeBase; } @@ -167,7 +166,7 @@ public Commit FindMergeBase(Branch branch, Branch otherBranch, IRepository repos /// Find the commit where the given branch was branched from another branch. /// If there are multiple such commits and branches, returns the newest commit. /// - public BranchCommit FindCommitBranchWasBranchedFrom([NotNull] Branch branch, IRepository repository, params Branch[] excludedBranches) + public BranchCommit FindCommitBranchWasBranchedFrom([NotNull] Branch branch, params Branch[] excludedBranches) { if (branch == null) { @@ -186,7 +185,6 @@ public BranchCommit FindCommitBranchWasBranchedFrom([NotNull] Branch branch, IRe } } - List GetMergeCommitsForBranch(Branch branch) { if (mergeBaseCommitsCache.ContainsKey(branch)) @@ -197,7 +195,7 @@ List GetMergeCommitsForBranch(Branch branch) return mergeBaseCommitsCache[branch]; } - var branchMergeBases = repository.Branches.Select(otherBranch => + var branchMergeBases = Repository.Branches.Select(otherBranch => { if (otherBranch.Tip == null) { @@ -205,7 +203,7 @@ List GetMergeCommitsForBranch(Branch branch) return BranchCommit.Empty; } - var findMergeBase = FindMergeBase(branch, otherBranch, repository); + var findMergeBase = FindMergeBase(branch, otherBranch); return new BranchCommit(findMergeBase, otherBranch); }).Where(b => b.Commit != null).OrderByDescending(b => b.Commit.Committer.When).ToList(); mergeBaseCommitsCache.Add(branch, branchMergeBases); diff --git a/src/GitVersionCore/GitVersionContext.cs b/src/GitVersionCore/GitVersionContext.cs index c3c9be5db7..1b5f57e195 100644 --- a/src/GitVersionCore/GitVersionContext.cs +++ b/src/GitVersionCore/GitVersionContext.cs @@ -17,7 +17,7 @@ public GitVersionContext(IRepository repository, Config configuration, bool isFo public GitVersionContext(IRepository repository, Branch currentBranch, Config configuration, bool onlyEvaluateTrackedBranches = true, string commitId = null) { Repository = repository; - RepostioryMetadataProvider = new GitRepoMetadataProvider(repository); + RepositoryMetadataProvider = new GitRepoMetadataProvider(repository); FullConfiguration = configuration; OnlyEvaluateTrackedBranches = onlyEvaluateTrackedBranches; @@ -47,7 +47,7 @@ public GitVersionContext(IRepository repository, Branch currentBranch, Config co if (currentBranch.IsDetachedHead()) { - CurrentBranch = RepostioryMetadataProvider.GetBranchesContainingCommit(CurrentCommit, repository, repository.Branches.ToList(), OnlyEvaluateTrackedBranches).OnlyOrDefault() ?? currentBranch; + CurrentBranch = RepositoryMetadataProvider.GetBranchesContainingCommit(CurrentCommit, repository.Branches.ToList(), OnlyEvaluateTrackedBranches).OnlyOrDefault() ?? currentBranch; } else { @@ -79,7 +79,7 @@ public GitVersionContext(IRepository repository, Branch currentBranch, Config co public Branch CurrentBranch { get; private set; } public Commit CurrentCommit { get; private set; } public bool IsCurrentCommitTagged { get; private set; } - public GitRepoMetadataProvider RepostioryMetadataProvider { get; private set; } + public GitRepoMetadataProvider RepositoryMetadataProvider { get; private set; } void CalculateEffectiveConfiguration() { diff --git a/src/GitVersionCore/VersionCalculation/BaseVersionCalculators/VersionInBranchNameBaseVersionStrategy.cs b/src/GitVersionCore/VersionCalculation/BaseVersionCalculators/VersionInBranchNameBaseVersionStrategy.cs index 979bcaa51b..db2546e06a 100644 --- a/src/GitVersionCore/VersionCalculation/BaseVersionCalculators/VersionInBranchNameBaseVersionStrategy.cs +++ b/src/GitVersionCore/VersionCalculation/BaseVersionCalculators/VersionInBranchNameBaseVersionStrategy.cs @@ -25,7 +25,7 @@ public IEnumerable GetVersions(GitVersionContext context, string ta var versionInBranch = GetVersionInBranch(branchName, tagPrefixRegex); if (versionInBranch != null) { - var commitBranchWasBranchedFrom = context.RepostioryMetadataProvider.FindCommitBranchWasBranchedFrom(currentBranch, repository); + var commitBranchWasBranchedFrom = context.RepositoryMetadataProvider.FindCommitBranchWasBranchedFrom(currentBranch); var branchNameOverride = branchName.RegexReplace("[-/]" + versionInBranch.Item1, string.Empty); yield return new BaseVersion(context, "Version in branch name", false, versionInBranch.Item2, commitBranchWasBranchedFrom.Commit, branchNameOverride); } diff --git a/src/GitVersionCore/VersionCalculation/DevelopVersionStrategy.cs b/src/GitVersionCore/VersionCalculation/DevelopVersionStrategy.cs index 000c03fd1d..99cea3298d 100644 --- a/src/GitVersionCore/VersionCalculation/DevelopVersionStrategy.cs +++ b/src/GitVersionCore/VersionCalculation/DevelopVersionStrategy.cs @@ -66,7 +66,7 @@ private IEnumerable ReleaseBranchBaseVersions(GitVersionContext con // Need to drop branch overrides and give a bit more context about // where this version came from var source1 = "Release branch exists -> " + baseVersion.Source; - return new BaseVersion(context, + return new BaseVersion(context, source1, baseVersion.ShouldIncrement, baseVersion.SemanticVersion, @@ -84,7 +84,7 @@ IEnumerable GetReleaseVersion(GitVersionContext context, Branch rel var repository = context.Repository; // Find the commit where the child branch was created. - var baseSource = context.RepostioryMetadataProvider.FindMergeBase(releaseBranch, context.CurrentBranch, repository); + var baseSource = context.RepositoryMetadataProvider.FindMergeBase(releaseBranch, context.CurrentBranch); if (baseSource == context.CurrentCommit) { // Ignore the branch if it has no commits. diff --git a/src/GitVersionCore/VersionCalculation/NextVersionCalculator.cs b/src/GitVersionCore/VersionCalculation/NextVersionCalculator.cs index 348a57f659..d06bbeb358 100644 --- a/src/GitVersionCore/VersionCalculation/NextVersionCalculator.cs +++ b/src/GitVersionCore/VersionCalculation/NextVersionCalculator.cs @@ -258,8 +258,8 @@ void UpdatePreReleaseTag(GitVersionContext context, SemanticVersion semanticVers int? number = null; - var lastTag = context.RepostioryMetadataProvider - .GetVersionTagsOnBranch(context.CurrentBranch, context.Repository, context.Configuration.GitTagPrefix) + var lastTag = context.RepositoryMetadataProvider + .GetVersionTagsOnBranch(context.CurrentBranch, context.Configuration.GitTagPrefix) .FirstOrDefault(v => v.PreReleaseTag.Name == tagToUse); if (lastTag != null &&