From 818fafc8ddb2efab3bb80b54f648bb8680703318 Mon Sep 17 00:00:00 2001 From: Daniel Rose Date: Tue, 16 Aug 2016 10:43:55 +0200 Subject: [PATCH 01/10] Add various tests for inheriting version numbers in feature branches. --- .../FeatureBranchScenarios.cs | 287 +++++++++++++++++- 1 file changed, 286 insertions(+), 1 deletion(-) diff --git a/src/GitVersionCore.Tests/IntegrationTests/FeatureBranchScenarios.cs b/src/GitVersionCore.Tests/IntegrationTests/FeatureBranchScenarios.cs index 3e05956b49..b2fed69e95 100644 --- a/src/GitVersionCore.Tests/IntegrationTests/FeatureBranchScenarios.cs +++ b/src/GitVersionCore.Tests/IntegrationTests/FeatureBranchScenarios.cs @@ -1,3 +1,4 @@ +using System.Collections.Generic; using GitTools.Testing; using GitVersion; using GitVersionCore.Tests; @@ -223,7 +224,7 @@ public void BranchCreatedAfterFinishReleaseShouldInheritAndIncrementFromLastMast fixture.Checkout("develop"); fixture.Repository.MergeNoFF("release/0.2.0"); fixture.Repository.Branches.Remove("release/2.0.0"); - + fixture.Repository.MakeACommit(); //validate develop branch version after merging release 0.2.0 to master and develop (finish release) @@ -237,4 +238,288 @@ public void BranchCreatedAfterFinishReleaseShouldInheritAndIncrementFromLastMast fixture.AssertFullSemver("0.3.0-TEST-1.1+2"); } } + + [Test] + public void ShouldPickUpVersionFromDevelopAfterReleaseBranchCreated() + { + using (var fixture = new EmptyRepositoryFixture()) + { + // Create develop and release branches + fixture.MakeACommit(); + fixture.BranchTo("develop"); + fixture.MakeACommit(); + fixture.BranchTo("release/1.0"); + fixture.MakeACommit(); + fixture.Checkout("develop"); + fixture.MakeACommit(); + fixture.AssertFullSemver("1.1.0-alpha.1"); + + // create a feature branch from develop and verify the version + fixture.BranchTo("feature/test"); + fixture.AssertFullSemver("1.1.0-test.1+1"); + } + } + + [Test] + public void ShouldPickUpVersionFromDevelopAfterReleaseBranchMergedBack() + { + using (var fixture = new EmptyRepositoryFixture()) + { + // Create develop and release branches + fixture.MakeACommit(); + fixture.BranchTo("develop"); + fixture.MakeACommit(); + fixture.BranchTo("release/1.0"); + fixture.MakeACommit(); + + // merge release into develop + fixture.Checkout("develop"); + fixture.MergeNoFF("release/1.0"); + fixture.AssertFullSemver("1.1.0-alpha.2"); + + // create a feature branch from develop and verify the version + fixture.BranchTo("feature/test"); + fixture.AssertFullSemver("1.1.0-test.1+2"); + } + } + + public class WhenMasterMarkedAsIsDevelop + { + [Test] + public void ShouldPickUpVersionFromMasterAfterReleaseBranchCreated() + { + var config = new Config + { + Branches = new Dictionary + { + { + "master", new BranchConfig() + { + IsDevelop = true, + } + } + } + }; + + using (var fixture = new EmptyRepositoryFixture()) + { + // Create release branch + fixture.MakeACommit(); + fixture.BranchTo("release/1.0"); + fixture.MakeACommit(); + fixture.Checkout("master"); + fixture.MakeACommit(); + fixture.AssertFullSemver(config, "1.0.1+1"); + + // create a feature branch from master and verify the version + fixture.BranchTo("feature/test"); + fixture.AssertFullSemver(config, "1.0.1-test.1+1"); + } + } + + [Test] + public void ShouldPickUpVersionFromMasterAfterReleaseBranchMergedBack() + { + var config = new Config + { + Branches = new Dictionary + { + { + "master", new BranchConfig() + { + IsDevelop = true, + } + } + } + }; + + using (var fixture = new EmptyRepositoryFixture()) + { + // Create release branch + fixture.MakeACommit(); + fixture.BranchTo("release/1.0"); + fixture.MakeACommit(); + + // merge release into master + fixture.Checkout("master"); + fixture.MergeNoFF("release/1.0"); + fixture.AssertFullSemver(config, "1.0.1+2"); + + // create a feature branch from master and verify the version + fixture.BranchTo("feature/test"); + fixture.AssertFullSemver(config, "1.0.1-test.1+2"); + } + } + } + + public class WhenFeatureBranchHasNoConfig + { + [TestCase(IncrementStrategy.Inherit)] + [TestCase(IncrementStrategy.Major)] + [TestCase(IncrementStrategy.Minor)] + [TestCase(IncrementStrategy.None)] + [TestCase(IncrementStrategy.Patch)] + public void ShouldPickUpVersionFromDevelopAfterReleaseBranchCreated(IncrementStrategy strategy) + { + var config = new Config + { + Branches = new Dictionary + { + { + "misnamed", new BranchConfig() + { + Increment = strategy + } + } + } + }; + + using (var fixture = new EmptyRepositoryFixture()) + { + // Create develop and release branches + fixture.MakeACommit(); + fixture.BranchTo("develop"); + fixture.MakeACommit(); + fixture.BranchTo("release/1.0"); + fixture.MakeACommit(); + fixture.Checkout("develop"); + fixture.MakeACommit(); + fixture.AssertFullSemver(config, "1.1.0-alpha.1"); + + // create a misnamed feature branch (should have no config; for testing, only Increment set) from develop and verify the version + fixture.BranchTo("misnamed"); + fixture.AssertFullSemver(config, "1.1.0+1"); + } + } + + [TestCase(IncrementStrategy.Inherit)] + [TestCase(IncrementStrategy.Major)] + [TestCase(IncrementStrategy.Minor)] + [TestCase(IncrementStrategy.None)] + [TestCase(IncrementStrategy.Patch)] + public void ShouldPickUpVersionFromDevelopAfterReleaseBranchMergedBack(IncrementStrategy strategy) + { + var config = new Config + { + Branches = new Dictionary + { + { + "misnamed", new BranchConfig() + { + Increment = strategy + } + } + } + }; + + using (var fixture = new EmptyRepositoryFixture()) + { + // Create develop and release branches + fixture.MakeACommit(); + fixture.BranchTo("develop"); + fixture.MakeACommit(); + fixture.BranchTo("release/1.0"); + fixture.MakeACommit(); + + // merge release into develop + fixture.Checkout("develop"); + fixture.MergeNoFF("release/1.0"); + fixture.AssertFullSemver(config, "1.1.0-alpha.2"); + + // create a misnamed feature branch (should have no config; for testing, only Increment set) from develop and verify the version + fixture.BranchTo("misnamed"); + fixture.AssertFullSemver(config, "1.1.0+0"); + } + } + + // ReSharper disable once MemberHidesStaticFromOuterClass + public class WhenMasterMarkedAsIsDevelop + { + [TestCase(IncrementStrategy.Inherit)] + [TestCase(IncrementStrategy.Major)] + [TestCase(IncrementStrategy.Minor)] + [TestCase(IncrementStrategy.None)] + [TestCase(IncrementStrategy.Patch)] + public void ShouldPickUpVersionFromMasterAfterReleaseBranchCreated(IncrementStrategy strategy) + { + var config = new Config + { + Branches = new Dictionary + { + { + "master", new BranchConfig() + { + IsDevelop = true, + } + }, + { + "misnamed", new BranchConfig() + { + Increment = strategy + } + } + } + }; + + using (var fixture = new EmptyRepositoryFixture()) + { + // Create release branch + fixture.MakeACommit(); + fixture.BranchTo("release/1.0"); + fixture.MakeACommit(); + fixture.Checkout("master"); + fixture.MakeACommit(); + fixture.AssertFullSemver(config, "1.0.1+1"); + + // create a misnamed feature branch (should have no config; for testing, only Increment set) from master and verify the version + fixture.BranchTo("misnamed"); + fixture.AssertFullSemver(config, "1.0.1+1"); + } + } + + [TestCase(IncrementStrategy.Inherit)] + [TestCase(IncrementStrategy.Major)] + [TestCase(IncrementStrategy.Minor)] + [TestCase(IncrementStrategy.None)] + [TestCase(IncrementStrategy.Patch)] + public void ShouldPickUpVersionFromMasterAfterReleaseBranchMergedBack(IncrementStrategy strategy) + { + var config = new Config + { + Branches = new Dictionary + { + { + "master", new BranchConfig() + { + IsDevelop = true, + } + }, + { + "misnamed", new BranchConfig() + { + Increment = strategy + } + } + } + }; + + using (var fixture = new EmptyRepositoryFixture()) + { + // Create release branch + fixture.MakeACommit(); + fixture.BranchTo("release/1.0"); + fixture.MakeACommit(); + + // merge release into master + fixture.Checkout("master"); + fixture.MergeNoFF("release/1.0"); + fixture.AssertFullSemver(config, "1.0.1+2"); + + // create a misnamed feature branch (should have no config; for testing, only Increment set) from master and verify the version + fixture.BranchTo("misnamed"); + fixture.AssertFullSemver(config, "1.0.1+2"); + } + } + } + } } \ No newline at end of file From bf486760a58912012515a74907f0f84f97658fc5 Mon Sep 17 00:00:00 2001 From: Daniel Rose Date: Fri, 23 Sep 2016 14:59:16 +0200 Subject: [PATCH 02/10] Test for picking up version number from parent branch. --- .../FeatureBranchScenarios.cs | 69 +++++++++++++++++++ 1 file changed, 69 insertions(+) diff --git a/src/GitVersionCore.Tests/IntegrationTests/FeatureBranchScenarios.cs b/src/GitVersionCore.Tests/IntegrationTests/FeatureBranchScenarios.cs index b2fed69e95..cfa6a60cc1 100644 --- a/src/GitVersionCore.Tests/IntegrationTests/FeatureBranchScenarios.cs +++ b/src/GitVersionCore.Tests/IntegrationTests/FeatureBranchScenarios.cs @@ -522,4 +522,73 @@ public void ShouldPickUpVersionFromMasterAfterReleaseBranchMergedBack(IncrementS } } } + + [Test] + public void ShouldPickupConfigsFromParentBranches() { + var config = new Config { + Branches = new Dictionary + { + { + "master", new BranchConfig() + { + Increment = IncrementStrategy.Major + } + }, + { + "child_minor", new BranchConfig() + { + Increment = IncrementStrategy.Minor + } + }, + { + "child_patch", new BranchConfig() + { + Increment = IncrementStrategy.Patch + } + }, + { + "child_inherit", new BranchConfig() + { + Increment = IncrementStrategy.Inherit + } + } + } + }; + + using (var fixture = new EmptyRepositoryFixture()) { + fixture.MakeACommit(); + + // tag master => 1.0.0 + fixture.ApplyTag("1.0.0"); + fixture.MakeACommit(); + fixture.AssertFullSemver(config, "2.0.0+1"); + + // branch to child_minor => same version number as master + fixture.BranchTo("child_minor"); + fixture.MakeACommit(); + fixture.AssertFullSemver(config, "2.0.0+3"); + + // tag child_minor as 3.2.0 => 3.3 + fixture.ApplyTag("3.2.0"); + fixture.MakeACommit(); + fixture.AssertFullSemver(config, "3.3.0+1"); + + // branch to child_patch from child_minor => same version number as child_minor + fixture.BranchTo("child_patch"); + fixture.MakeACommit(); + fixture.AssertFullSemver(config, "3.3.0+2"); + + // branch to child_inherit from master => same version number as master + fixture.Checkout("master"); + fixture.MakeACommit(); + fixture.BranchTo("child_inherit"); + fixture.MakeACommit(); + fixture.AssertFullSemver(config, "2.0.0+3"); + + // tag child_inherit as 5.0.0 => 6.0 + fixture.ApplyTag("5.0.0"); + fixture.MakeACommit(); + fixture.AssertFullSemver(config, "6.0.0+1"); + } + } } \ No newline at end of file From fb4bb192f98168bb16c65e2386df534ace4f3b0a Mon Sep 17 00:00:00 2001 From: Daniel Rose Date: Fri, 23 Sep 2016 15:17:38 +0200 Subject: [PATCH 03/10] Add Regex for custom branch configs. --- .../FeatureBranchScenarios.cs | 37 +++++++++++++------ 1 file changed, 26 insertions(+), 11 deletions(-) diff --git a/src/GitVersionCore.Tests/IntegrationTests/FeatureBranchScenarios.cs b/src/GitVersionCore.Tests/IntegrationTests/FeatureBranchScenarios.cs index cfa6a60cc1..0f0609167a 100644 --- a/src/GitVersionCore.Tests/IntegrationTests/FeatureBranchScenarios.cs +++ b/src/GitVersionCore.Tests/IntegrationTests/FeatureBranchScenarios.cs @@ -296,6 +296,7 @@ public void ShouldPickUpVersionFromMasterAfterReleaseBranchCreated() "master", new BranchConfig() { IsDevelop = true, + Regex = "master" } } } @@ -328,6 +329,7 @@ public void ShouldPickUpVersionFromMasterAfterReleaseBranchMergedBack() "master", new BranchConfig() { IsDevelop = true, + Regex = "master" } } } @@ -368,7 +370,8 @@ public void ShouldPickUpVersionFromDevelopAfterReleaseBranchCreated(IncrementStr { "misnamed", new BranchConfig() { - Increment = strategy + Increment = strategy, + Regex = "misnamed" } } } @@ -406,7 +409,8 @@ public void ShouldPickUpVersionFromDevelopAfterReleaseBranchMergedBack(Increment { "misnamed", new BranchConfig() { - Increment = strategy + Increment = strategy, + Regex = "misnamed" } } } @@ -450,12 +454,14 @@ public void ShouldPickUpVersionFromMasterAfterReleaseBranchCreated(IncrementStra "master", new BranchConfig() { IsDevelop = true, + Regex = "master" } }, { "misnamed", new BranchConfig() { - Increment = strategy + Increment = strategy, + Regex = "misnamed" } } } @@ -492,12 +498,14 @@ public void ShouldPickUpVersionFromMasterAfterReleaseBranchMergedBack(IncrementS "master", new BranchConfig() { IsDevelop = true, + Regex = "master" } }, { "misnamed", new BranchConfig() { - Increment = strategy + Increment = strategy, + Regex = "misnamed" } } } @@ -524,38 +532,45 @@ public void ShouldPickUpVersionFromMasterAfterReleaseBranchMergedBack(IncrementS } [Test] - public void ShouldPickupConfigsFromParentBranches() { - var config = new Config { + public void ShouldPickupConfigsFromParentBranches() + { + var config = new Config + { Branches = new Dictionary { { "master", new BranchConfig() { - Increment = IncrementStrategy.Major + Increment = IncrementStrategy.Major, + Regex = "master" } }, { "child_minor", new BranchConfig() { - Increment = IncrementStrategy.Minor + Increment = IncrementStrategy.Minor, + Regex = "child_minor" } }, { "child_patch", new BranchConfig() { - Increment = IncrementStrategy.Patch + Increment = IncrementStrategy.Patch, + Regex = "child_patch" } }, { "child_inherit", new BranchConfig() { - Increment = IncrementStrategy.Inherit + Increment = IncrementStrategy.Inherit, + Regex = "child_inherit" } } } }; - using (var fixture = new EmptyRepositoryFixture()) { + using (var fixture = new EmptyRepositoryFixture()) + { fixture.MakeACommit(); // tag master => 1.0.0 From c1adffe27f6c056835a4cc38486039cd2ea5540d Mon Sep 17 00:00:00 2001 From: Daniel Rose Date: Fri, 30 Sep 2016 15:00:03 +0200 Subject: [PATCH 04/10] Add comments. --- .../Configuration/BranchConfig.cs | 7 +++++-- src/GitVersionCore/LibGitExtensions.cs | 16 +++++++++++----- .../ConfigNextVersionBaseVersionStrategy.cs | 5 +++++ .../MergeMessageBaseVersionStrategy.cs | 5 +++++ .../TaggedCommitVersionStrategy.cs | 5 +++++ .../VersionInBranchBaseVersionStrategy.cs | 5 +++++ .../VersionCalculation/BaseVersionStrategy.cs | 9 +++++++++ .../DevelopVersionStrategy.cs | 19 ++++++++++++++++++- .../FallbackBaseVersionStrategy.cs | 5 +++++ 9 files changed, 68 insertions(+), 8 deletions(-) diff --git a/src/GitVersionCore/Configuration/BranchConfig.cs b/src/GitVersionCore/Configuration/BranchConfig.cs index b3abee74df..8b243f9721 100644 --- a/src/GitVersionCore/Configuration/BranchConfig.cs +++ b/src/GitVersionCore/Configuration/BranchConfig.cs @@ -8,9 +8,11 @@ public BranchConfig() { } + /// + /// Creates a clone of the given . + /// public BranchConfig(BranchConfig branchConfiguration) { - Regex = branchConfiguration.Regex; VersioningMode = branchConfiguration.VersioningMode; Tag = branchConfiguration.Tag; Increment = branchConfiguration.Increment; @@ -18,6 +20,7 @@ public BranchConfig(BranchConfig branchConfiguration) TagNumberPattern = branchConfiguration.TagNumberPattern; TrackMergeTarget = branchConfiguration.TrackMergeTarget; CommitMessageIncrementing = branchConfiguration.CommitMessageIncrementing; + Regex = branchConfiguration.Regex; IsDevelop = branchConfiguration.IsDevelop; IsReleaseBranch = branchConfiguration.IsReleaseBranch; IsMainline = branchConfiguration.IsMainline; @@ -43,7 +46,7 @@ public BranchConfig(BranchConfig branchConfiguration) [YamlMember(Alias = "track-merge-target")] public bool? TrackMergeTarget { get; set; } - + [YamlMember(Alias = "commit-message-incrementing")] public CommitMessageIncrementMode? CommitMessageIncrementing { get; set; } diff --git a/src/GitVersionCore/LibGitExtensions.cs b/src/GitVersionCore/LibGitExtensions.cs index 810d68e31d..9179e7ee0b 100644 --- a/src/GitVersionCore/LibGitExtensions.cs +++ b/src/GitVersionCore/LibGitExtensions.cs @@ -32,7 +32,10 @@ public static IEnumerable GetVersionTagsOnBranch(this Branch br })); } - + /// + /// 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 Commit 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."; @@ -79,6 +82,9 @@ public static Commit FindCommitBranchWasBranchedFrom([NotNull] this Branch branc } } + /// + /// 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))) @@ -96,15 +102,15 @@ public static Commit FindMergeBase(this Branch branch, Branch otherBranch, IRepo { 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 mergeBaseWasFowardMerge; + bool mergeBaseWasForwardMerge; do { // Now make sure that the merge base is not a forward merge - mergeBaseWasFowardMerge = otherBranch.Commits + mergeBaseWasForwardMerge = otherBranch.Commits .SkipWhile(c => c != commitToFindCommonBase) .TakeWhile(c => c != findMergeBase) .Any(c => c.Parents.Contains(findMergeBase)); - if (mergeBaseWasFowardMerge) + if (mergeBaseWasForwardMerge) { var second = commitToFindCommonBase.Parents.First(); var mergeBase = repository.ObjectDatabase.FindMergeBase(commit, second); @@ -115,7 +121,7 @@ public static Commit FindMergeBase(this Branch branch, Branch otherBranch, IRepo findMergeBase = mergeBase; Logger.WriteInfo(string.Format("Merge base was due to a forward merge, next merge base is {0}", findMergeBase)); } - } while (mergeBaseWasFowardMerge); + } while (mergeBaseWasForwardMerge); } return findMergeBase; } diff --git a/src/GitVersionCore/VersionCalculation/BaseVersionCalculators/ConfigNextVersionBaseVersionStrategy.cs b/src/GitVersionCore/VersionCalculation/BaseVersionCalculators/ConfigNextVersionBaseVersionStrategy.cs index 9d70a7bf35..8ab379a5fb 100644 --- a/src/GitVersionCore/VersionCalculation/BaseVersionCalculators/ConfigNextVersionBaseVersionStrategy.cs +++ b/src/GitVersionCore/VersionCalculation/BaseVersionCalculators/ConfigNextVersionBaseVersionStrategy.cs @@ -2,6 +2,11 @@ { using System.Collections.Generic; + /// + /// Version is from NextVersion (the configuration value), unless the current commit is tagged. + /// BaseVersionSource is null. + /// Does not increment. + /// public class ConfigNextVersionBaseVersionStrategy : BaseVersionStrategy { public override IEnumerable GetVersions(GitVersionContext context) diff --git a/src/GitVersionCore/VersionCalculation/BaseVersionCalculators/MergeMessageBaseVersionStrategy.cs b/src/GitVersionCore/VersionCalculation/BaseVersionCalculators/MergeMessageBaseVersionStrategy.cs index c0964e01a3..8703409b12 100644 --- a/src/GitVersionCore/VersionCalculation/BaseVersionCalculators/MergeMessageBaseVersionStrategy.cs +++ b/src/GitVersionCore/VersionCalculation/BaseVersionCalculators/MergeMessageBaseVersionStrategy.cs @@ -6,6 +6,11 @@ using System.Text.RegularExpressions; using LibGit2Sharp; + /// + /// Version is extracted from older commits's merge messages. + /// BaseVersionSource is the commit where the message was found. + /// Increments if PreventIncrementForMergedBranchVersion (from the branch config) is false. + /// public class MergeMessageBaseVersionStrategy : BaseVersionStrategy { public override IEnumerable GetVersions(GitVersionContext context) diff --git a/src/GitVersionCore/VersionCalculation/BaseVersionCalculators/TaggedCommitVersionStrategy.cs b/src/GitVersionCore/VersionCalculation/BaseVersionCalculators/TaggedCommitVersionStrategy.cs index eaea434d53..2f91955cd8 100644 --- a/src/GitVersionCore/VersionCalculation/BaseVersionCalculators/TaggedCommitVersionStrategy.cs +++ b/src/GitVersionCore/VersionCalculation/BaseVersionCalculators/TaggedCommitVersionStrategy.cs @@ -5,6 +5,11 @@ using System.Linq; using LibGit2Sharp; + /// + /// Version is extracted from all tags on the branch which are valid, and not newer than the current commit. + /// BaseVersionSource is the tag's commit. + /// Increments if the tag is not the current commit. + /// public class TaggedCommitVersionStrategy : BaseVersionStrategy { public override IEnumerable GetVersions(GitVersionContext context) diff --git a/src/GitVersionCore/VersionCalculation/BaseVersionCalculators/VersionInBranchBaseVersionStrategy.cs b/src/GitVersionCore/VersionCalculation/BaseVersionCalculators/VersionInBranchBaseVersionStrategy.cs index 8e0bcc7470..c6749d8f55 100644 --- a/src/GitVersionCore/VersionCalculation/BaseVersionCalculators/VersionInBranchBaseVersionStrategy.cs +++ b/src/GitVersionCore/VersionCalculation/BaseVersionCalculators/VersionInBranchBaseVersionStrategy.cs @@ -4,6 +4,11 @@ using System.Collections.Generic; using LibGit2Sharp; + /// + /// Version is extracted from the name of the branch. + /// BaseVersionSource is the commit where the branch was branched from its parent. + /// Does not increment. + /// public class VersionInBranchBaseVersionStrategy : BaseVersionStrategy { public override IEnumerable GetVersions(GitVersionContext context) diff --git a/src/GitVersionCore/VersionCalculation/BaseVersionStrategy.cs b/src/GitVersionCore/VersionCalculation/BaseVersionStrategy.cs index a30ccd8c32..67fe87d552 100644 --- a/src/GitVersionCore/VersionCalculation/BaseVersionStrategy.cs +++ b/src/GitVersionCore/VersionCalculation/BaseVersionStrategy.cs @@ -5,6 +5,15 @@ public abstract class BaseVersionStrategy { + /// + /// Calculates the values for the given . + /// + /// + /// The context for calculating the . + /// + /// + /// An of the base version values found by the strategy. + /// public abstract IEnumerable GetVersions(GitVersionContext context); } } \ No newline at end of file diff --git a/src/GitVersionCore/VersionCalculation/DevelopVersionStrategy.cs b/src/GitVersionCore/VersionCalculation/DevelopVersionStrategy.cs index 355bbfc63f..aac8be529d 100644 --- a/src/GitVersionCore/VersionCalculation/DevelopVersionStrategy.cs +++ b/src/GitVersionCore/VersionCalculation/DevelopVersionStrategy.cs @@ -8,7 +8,20 @@ namespace GitVersion.VersionCalculation using LibGit2Sharp; /// - /// Inherit version from release branch and tags on master + /// Active only when the branch is marked as IsDevelop. + /// Two different algorithms (results are merged): + /// + /// Using : + /// Version is that of any child branches marked with IsReleaseBranch (except if they have no commits of their own). + /// BaseVersionSource is the commit where the child branch was created. + /// Always increments. + /// + /// + /// Using : + /// Version is extracted from all tags on the master branch which are valid. + /// BaseVersionSource is the tag's commit (same as base strategy). + /// Increments if the tag is not the current commit (same as base strategy). + /// /// public class DevelopVersionStrategy : BaseVersionStrategy { @@ -69,9 +82,13 @@ IEnumerable GetReleaseVersion(GitVersionContext context, Branch rel var tagPrefixRegex = context.Configuration.GitTagPrefix; var repository = context.Repository; + // Find the commit where the child branch was created. var baseSource = releaseBranch.FindMergeBase(context.CurrentBranch, repository); if (baseSource == context.CurrentCommit) + { + // Ignore the branch if it has no commits. return new BaseVersion[0]; + } return releaseVersionStrategy .GetVersions(tagPrefixRegex, releaseBranch, repository) diff --git a/src/GitVersionCore/VersionCalculation/FallbackBaseVersionStrategy.cs b/src/GitVersionCore/VersionCalculation/FallbackBaseVersionStrategy.cs index 52666337b4..f548ce7215 100644 --- a/src/GitVersionCore/VersionCalculation/FallbackBaseVersionStrategy.cs +++ b/src/GitVersionCore/VersionCalculation/FallbackBaseVersionStrategy.cs @@ -5,6 +5,11 @@ using BaseVersionCalculators; using LibGit2Sharp; + /// + /// Version is 0.1.0. + /// BaseVersionSource is the "root" commit reachable from the current commit. + /// Does not increment. + /// public class FallbackBaseVersionStrategy : BaseVersionStrategy { public override IEnumerable GetVersions(GitVersionContext context) From 08216665f25dfd901b2ddbbb4746ba4557fddae6 Mon Sep 17 00:00:00 2001 From: Daniel Rose Date: Fri, 30 Sep 2016 16:52:42 +0200 Subject: [PATCH 05/10] When the increment strategy is Inherit, use the first value of the parent branch which is not Inherit. --- .../BranchConfigurationCalculator.cs | 147 +++++++++--------- src/GitVersionCore/GitVersionContext.cs | 2 +- src/GitVersionCore/LibGitExtensions.cs | 6 +- 3 files changed, 78 insertions(+), 77 deletions(-) diff --git a/src/GitVersionCore/BranchConfigurationCalculator.cs b/src/GitVersionCore/BranchConfigurationCalculator.cs index f8a10ba196..af3d6c50db 100644 --- a/src/GitVersionCore/BranchConfigurationCalculator.cs +++ b/src/GitVersionCore/BranchConfigurationCalculator.cs @@ -11,7 +11,15 @@ namespace GitVersion public class BranchConfigurationCalculator { - public static KeyValuePair GetBranchConfiguration(Commit currentCommit, IRepository repository, bool onlyEvaluateTrackedBranches, Config config, Branch currentBranch, IList excludedInheritBranches = null) + private const IncrementStrategy FallbackIncrementStrategy = IncrementStrategy.Minor; + + /// + /// Gets the for the current commit. + /// + /// + /// A KeyValuePair. The key is the name of the branch configuration (from the yaml or the default configs); the value is the actual configuration. + /// + public static KeyValuePair GetBranchConfiguration(Commit currentCommit, IRepository repository, bool onlyEvaluateTrackedBranches, Config config, Branch currentBranch, Branch[] excludedBranches) { var matchingBranches = LookupBranchConfiguration(config, currentBranch); @@ -32,7 +40,11 @@ public static KeyValuePair GetBranchConfiguration(Commit c if (branchConfiguration.Increment == IncrementStrategy.Inherit) { - return InheritBranchConfiguration(onlyEvaluateTrackedBranches, repository, currentCommit, currentBranch, keyValuePair, branchConfiguration, config, excludedInheritBranches); + // Use the parent's increment strategy. If none is found, use FallbackIncrementStrategy, + var parentIncrement = GetParentIncrementStrategy(onlyEvaluateTrackedBranches, repository, currentCommit, currentBranch, branchConfiguration, config, excludedBranches) ?? FallbackIncrementStrategy; + + // Overwrite the Increment with the parent's value. That way, no future searching needs to be done. + branchConfiguration.Increment = parentIncrement; } return keyValuePair; @@ -48,7 +60,7 @@ static KeyValuePair[] LookupBranchConfiguration([NotNull] { throw new ArgumentNullException("config"); } - + if (currentBranch == null) { throw new ArgumentNullException("currentBranch"); @@ -58,74 +70,30 @@ static KeyValuePair[] LookupBranchConfiguration([NotNull] } - static KeyValuePair InheritBranchConfiguration(bool onlyEvaluateTrackedBranches, IRepository repository, Commit currentCommit, Branch currentBranch, KeyValuePair keyValuePair, BranchConfig branchConfiguration, Config config, IList excludedInheritBranches) + /// + /// Recursively look for an IncrementStrategy in the parent branches, which is set and different than . + /// + static IncrementStrategy? GetParentIncrementStrategy(bool onlyEvaluateTrackedBranches, IRepository repository, Commit currentCommit, Branch currentBranch, BranchConfig branchConfiguration, Config config, Branch[] excludedBranches) { - using (Logger.IndentLog("Attempting to inherit branch configuration from parent branch")) + if (branchConfiguration.Increment != IncrementStrategy.Inherit && branchConfiguration.Increment != null) { - var excludedBranches = new[] { currentBranch }; - // Check if we are a merge commit. If so likely we are a pull request - var parentCount = currentCommit.Parents.Count(); - if (parentCount == 2) - { - excludedBranches = CalculateWhenMultipleParents(repository, currentCommit, ref currentBranch, excludedBranches); - } - - if (excludedInheritBranches == null) - { - excludedInheritBranches = repository.Branches.Where(b => - { - var branchConfig = LookupBranchConfiguration(config, b); - - // NOTE: if length is 0 we couldn't find the configuration for the branch e.g. "origin/master" - // NOTE: if the length is greater than 1 we cannot decide which merge strategy to pick - return (branchConfig.Length != 1) || (branchConfig.Length == 1 && branchConfig[0].Value.Increment == IncrementStrategy.Inherit); - }).ToList(); - } - excludedBranches.ToList().ForEach(excludedInheritBranches.Add); - var branchesToEvaluate = repository.Branches.Except(excludedInheritBranches).ToList(); - - var branchPoint = currentBranch.FindCommitBranchWasBranchedFrom(repository, excludedInheritBranches.ToArray()); - List possibleParents; - if (branchPoint == null) - { - possibleParents = currentCommit.GetBranchesContainingCommit(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) - .ToList(); - } - else - { - var branches = branchPoint.GetBranchesContainingCommit(repository, branchesToEvaluate, true).ToList(); - if (branches.Count > 1) - { - var currentTipBranches = currentCommit.GetBranchesContainingCommit(repository, branchesToEvaluate, true).ToList(); - possibleParents = branches.Except(currentTipBranches).ToList(); - } - else - { - possibleParents = branches; - } - } + // Found an increment strategy which can be used. + return branchConfiguration.Increment; + } - Logger.WriteInfo("Found possible parent branches: " + string.Join(", ", possibleParents.Select(p => p.FriendlyName))); + using (Logger.IndentLog("Attempting to get increment value from parent branch")) + { + var possibleParents = FindParentBranches(repository, currentCommit, currentBranch, excludedBranches).ToList(); if (possibleParents.Count == 1) { - var branchConfig = GetBranchConfiguration(currentCommit, repository, onlyEvaluateTrackedBranches, config, possibleParents[0], excludedInheritBranches).Value; - return new KeyValuePair( - keyValuePair.Key, - new BranchConfig(branchConfiguration) - { - Increment = branchConfig.Increment, - PreventIncrementOfMergedBranchVersion = branchConfig.PreventIncrementOfMergedBranchVersion, - // If we are inheriting from develop then we should behave like develop - IsDevelop = branchConfig.IsDevelop - }); + // Single parent found => get its IncrementStrategy. + var branchConfig = GetBranchConfiguration(currentCommit, repository, onlyEvaluateTrackedBranches, config, possibleParents[0], excludedBranches).Value; + return branchConfig.Increment; } - // If we fail to inherit it is probably because the branch has been merged and we can't do much. So we will fall back to develop's config - // if develop exists and master if not + // Multiple parents found; it is probably because the branch has been merged and we can't do much. + // So we will fall back to develop's value if develop exists and master if not. string errorMessage; if (possibleParents.Count == 0) errorMessage = "Failed to inherit Increment branch configuration, no branches found."; @@ -144,16 +112,49 @@ static KeyValuePair InheritBranchConfiguration(bool onlyEv 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).Value; - return new KeyValuePair( - keyValuePair.Key, - new BranchConfig(branchConfiguration) - { - Increment = inheritingBranchConfig.Increment, - PreventIncrementOfMergedBranchVersion = inheritingBranchConfig.PreventIncrementOfMergedBranchVersion, - // If we are inheriting from develop then we should behave like develop - IsDevelop = inheritingBranchConfig.IsDevelop - }); + var inheritingBranchConfig = GetBranchConfiguration(currentCommit, repository, onlyEvaluateTrackedBranches, config, chosenBranch, null).Value; + return inheritingBranchConfig.Increment; + } + } + + public static IEnumerable FindParentBranches(IRepository repository, Commit currentCommit, Branch currentBranch, Branch[] excludedBranches) + { + using (Logger.IndentLog("Searching for parent branches")) + { + // Find out which branches to exclude as possible parent branches: The current branch, and possibly more in case of a merge commit. + var newlyExcludedBranches = new[] + { + currentBranch + }; + // Check if we are a merge commit. If so likely we are a pull request + var parentCount = currentCommit.Parents.Count(); + if (parentCount == 2) + { + newlyExcludedBranches = CalculateWhenMultipleParents(repository, currentCommit, ref currentBranch, newlyExcludedBranches); + } + + excludedBranches = excludedBranches == null ? newlyExcludedBranches : excludedBranches.Union(newlyExcludedBranches).ToArray(); + var branchesToEvaluate = repository.Branches.Where(b => excludedBranches.All(eb => !LibGitExtensions.IsSameBranch(b, eb))).ToList(); + + // Try to find the branch point commit, i.e. the commit where the branch was created from a different branch. + var branchPoint = currentBranch.FindCommitBranchWasBranchedFrom(repository, excludedBranches); + if (branchPoint == null) + { + // For whatever reason, no branch point was found. Return all branches containg the current commit, as possible parents. + // TODO correct? Or better empty list? + return currentCommit.GetBranchesContainingCommit(repository, branchesToEvaluate, true); + } + + // Return the branch of the branch point commit. + var branches = branchPoint.GetBranchesContainingCommit(repository, branchesToEvaluate, true).ToList(); + if (branches.Count > 1) + { + // The commit is contained in multiple branches => return all, except those also belonging to the commit. + var currentTipBranches = currentCommit.GetBranchesContainingCommit(repository, branchesToEvaluate, true); + return branches.Except(currentTipBranches); + } + + return branches; } } diff --git a/src/GitVersionCore/GitVersionContext.cs b/src/GitVersionCore/GitVersionContext.cs index bdf64bdb94..ed639177a2 100644 --- a/src/GitVersionCore/GitVersionContext.cs +++ b/src/GitVersionCore/GitVersionContext.cs @@ -83,7 +83,7 @@ public GitVersionContext(IRepository repository, Branch currentBranch, Config co void CalculateEffectiveConfiguration() { - var currentBranchConfig = BranchConfigurationCalculator.GetBranchConfiguration(CurrentCommit, Repository, OnlyEvaluateTrackedBranches, FullConfiguration, CurrentBranch); + var currentBranchConfig = BranchConfigurationCalculator.GetBranchConfiguration(CurrentCommit, Repository, OnlyEvaluateTrackedBranches, FullConfiguration, CurrentBranch, null); if (!currentBranchConfig.Value.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.Key)); diff --git a/src/GitVersionCore/LibGitExtensions.cs b/src/GitVersionCore/LibGitExtensions.cs index 9179e7ee0b..de2fdeab30 100644 --- a/src/GitVersionCore/LibGitExtensions.cs +++ b/src/GitVersionCore/LibGitExtensions.cs @@ -127,10 +127,10 @@ public static Commit FindMergeBase(this Branch branch, Branch otherBranch, IRepo } } - static bool IsSameBranch(Branch branch, Branch b) + public static bool IsSameBranch(Branch branch, Branch b) { - return (b.IsRemote ? - b.FriendlyName.Substring(b.FriendlyName.IndexOf("/", StringComparison.Ordinal) + 1) : + return (b.IsRemote ? + b.FriendlyName.Substring(b.FriendlyName.IndexOf("/", StringComparison.Ordinal) + 1) : b.FriendlyName) != branch.FriendlyName; } From 46e1a1c7399656a285df0a521e8ed29b6a3ee8ea Mon Sep 17 00:00:00 2001 From: Daniel Rose Date: Tue, 4 Oct 2016 11:33:29 +0200 Subject: [PATCH 06/10] Put the name of the branch configuration in BranchConfig. --- .../BranchConfigurationCalculator.cs | 24 +++++----- .../Configuration/BranchConfig.cs | 7 +++ src/GitVersionCore/Configuration/Config.cs | 2 +- src/GitVersionCore/GitVersionContext.cs | 44 +++++++++---------- 4 files changed, 42 insertions(+), 35 deletions(-) diff --git a/src/GitVersionCore/BranchConfigurationCalculator.cs b/src/GitVersionCore/BranchConfigurationCalculator.cs index af3d6c50db..78e1fef0a7 100644 --- a/src/GitVersionCore/BranchConfigurationCalculator.cs +++ b/src/GitVersionCore/BranchConfigurationCalculator.cs @@ -19,9 +19,9 @@ public class BranchConfigurationCalculator /// /// A KeyValuePair. The key is the name of the branch configuration (from the yaml or the default configs); the value is the actual configuration. /// - public static KeyValuePair GetBranchConfiguration(Commit currentCommit, IRepository repository, bool onlyEvaluateTrackedBranches, Config config, Branch currentBranch, Branch[] excludedBranches) + public static BranchConfig GetBranchConfiguration(Commit currentCommit, IRepository repository, bool onlyEvaluateTrackedBranches, Config config, Branch currentBranch, Branch[] excludedBranches) { - var matchingBranches = LookupBranchConfiguration(config, currentBranch); + var matchingBranches = LookupBranchConfiguration(config, currentBranch).ToArray(); if (matchingBranches.Length == 0) { @@ -29,14 +29,14 @@ public static KeyValuePair GetBranchConfiguration(Commit c "No branch configuration found for branch {0}, falling back to default configuration", currentBranch.FriendlyName)); - var branchConfig = new BranchConfig(); + var branchConfig = new BranchConfig { Name = string.Empty }; ConfigurationProvider.ApplyBranchDefaults(config, branchConfig, ""); - return new KeyValuePair(string.Empty, branchConfig); + return branchConfig; } + if (matchingBranches.Length == 1) { - var keyValuePair = matchingBranches[0]; - var branchConfiguration = keyValuePair.Value; + var branchConfiguration = matchingBranches[0]; if (branchConfiguration.Increment == IncrementStrategy.Inherit) { @@ -47,14 +47,14 @@ public static KeyValuePair GetBranchConfiguration(Commit c branchConfiguration.Increment = parentIncrement; } - return keyValuePair; + return branchConfiguration; } const string format = "Multiple branch configurations match the current branch branchName of '{0}'. Matching configurations: '{1}'"; - throw new Exception(string.Format(format, currentBranch.FriendlyName, string.Join(", ", matchingBranches.Select(b => b.Key)))); + throw new Exception(string.Format(format, currentBranch.FriendlyName, string.Join(", ", matchingBranches.Select(b => b.Name)))); } - static KeyValuePair[] LookupBranchConfiguration([NotNull] Config config, [NotNull] Branch currentBranch) + static IEnumerable LookupBranchConfiguration([NotNull] Config config, [NotNull] Branch currentBranch) { if (config == null) { @@ -66,7 +66,7 @@ static KeyValuePair[] LookupBranchConfiguration([NotNull] throw new ArgumentNullException("currentBranch"); } - return config.Branches.Where(b => Regex.IsMatch(currentBranch.FriendlyName, "^" + b.Value.Regex, RegexOptions.IgnoreCase)).ToArray(); + return config.Branches.Where(b => Regex.IsMatch(currentBranch.FriendlyName, "^" + b.Value.Regex, RegexOptions.IgnoreCase)).Select(kvp => kvp.Value); } @@ -88,7 +88,7 @@ static KeyValuePair[] LookupBranchConfiguration([NotNull] if (possibleParents.Count == 1) { // Single parent found => get its IncrementStrategy. - var branchConfig = GetBranchConfiguration(currentCommit, repository, onlyEvaluateTrackedBranches, config, possibleParents[0], excludedBranches).Value; + var branchConfig = GetBranchConfiguration(currentCommit, repository, onlyEvaluateTrackedBranches, config, possibleParents[0], excludedBranches); return branchConfig.Increment; } @@ -112,7 +112,7 @@ static KeyValuePair[] LookupBranchConfiguration([NotNull] 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, null).Value; + var inheritingBranchConfig = GetBranchConfiguration(currentCommit, repository, onlyEvaluateTrackedBranches, config, chosenBranch, excludedBranches); return inheritingBranchConfig.Increment; } } diff --git a/src/GitVersionCore/Configuration/BranchConfig.cs b/src/GitVersionCore/Configuration/BranchConfig.cs index 8b243f9721..f6916eef9e 100644 --- a/src/GitVersionCore/Configuration/BranchConfig.cs +++ b/src/GitVersionCore/Configuration/BranchConfig.cs @@ -24,6 +24,7 @@ public BranchConfig(BranchConfig branchConfiguration) IsDevelop = branchConfiguration.IsDevelop; IsReleaseBranch = branchConfiguration.IsReleaseBranch; IsMainline = branchConfiguration.IsMainline; + Name = branchConfiguration.Name; } [YamlMember(Alias = "mode")] @@ -61,5 +62,11 @@ public BranchConfig(BranchConfig branchConfiguration) [YamlMember(Alias = "is-mainline")] public bool? IsMainline { get; set; } + + /// + /// The name given to this configuration in the config file. + /// + [YamlIgnore] + public string Name { get; set; } } } diff --git a/src/GitVersionCore/Configuration/Config.cs b/src/GitVersionCore/Configuration/Config.cs index f6e04af6e4..e75cd34a38 100644 --- a/src/GitVersionCore/Configuration/Config.cs +++ b/src/GitVersionCore/Configuration/Config.cs @@ -79,7 +79,7 @@ public Dictionary Branches value.ToList().ForEach(_ => { if (!branches.ContainsKey(_.Key)) - branches.Add(_.Key, new BranchConfig()); + branches.Add(_.Key, new BranchConfig {Name = _.Key}); branches[_.Key] = MergeObjects(branches[_.Key], _.Value); }); diff --git a/src/GitVersionCore/GitVersionContext.cs b/src/GitVersionCore/GitVersionContext.cs index ed639177a2..e2fbd56f56 100644 --- a/src/GitVersionCore/GitVersionContext.cs +++ b/src/GitVersionCore/GitVersionContext.cs @@ -85,18 +85,18 @@ void CalculateEffectiveConfiguration() { var currentBranchConfig = BranchConfigurationCalculator.GetBranchConfiguration(CurrentCommit, Repository, OnlyEvaluateTrackedBranches, FullConfiguration, CurrentBranch, null); - if (!currentBranchConfig.Value.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.Key)); - if (!currentBranchConfig.Value.Increment.HasValue) - throw new Exception(string.Format("Configuration value for 'Increment' for branch {0} has no value. (this should not happen, please report an issue)", currentBranchConfig.Key)); - if (!currentBranchConfig.Value.PreventIncrementOfMergedBranchVersion.HasValue) - throw new Exception(string.Format("Configuration value for 'PreventIncrementOfMergedBranchVersion' for branch {0} has no value. (this should not happen, please report an issue)", currentBranchConfig.Key)); - if (!currentBranchConfig.Value.TrackMergeTarget.HasValue) - throw new Exception(string.Format("Configuration value for 'TrackMergeTarget' for branch {0} has no value. (this should not happen, please report an issue)", currentBranchConfig.Key)); - if (!currentBranchConfig.Value.IsDevelop.HasValue) - throw new Exception(string.Format("Configuration value for 'IsDevelop' for branch {0} has no value. (this should not happen, please report an issue)", currentBranchConfig.Key)); - if (!currentBranchConfig.Value.IsReleaseBranch.HasValue) - throw new Exception(string.Format("Configuration value for 'IsReleaseBranch' for branch {0} has no value. (this should not happen, please report an issue)", currentBranchConfig.Key)); + 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)); + if (!currentBranchConfig.Increment.HasValue) + throw new Exception(string.Format("Configuration value for 'Increment' for branch {0} has no value. (this should not happen, please report an issue)", currentBranchConfig.Name)); + if (!currentBranchConfig.PreventIncrementOfMergedBranchVersion.HasValue) + throw new Exception(string.Format("Configuration value for 'PreventIncrementOfMergedBranchVersion' for branch {0} has no value. (this should not happen, please report an issue)", currentBranchConfig.Name)); + if (!currentBranchConfig.TrackMergeTarget.HasValue) + throw new Exception(string.Format("Configuration value for 'TrackMergeTarget' for branch {0} has no value. (this should not happen, please report an issue)", currentBranchConfig.Name)); + if (!currentBranchConfig.IsDevelop.HasValue) + throw new Exception(string.Format("Configuration value for 'IsDevelop' for branch {0} has no value. (this should not happen, please report an issue)", currentBranchConfig.Name)); + if (!currentBranchConfig.IsReleaseBranch.HasValue) + throw new Exception(string.Format("Configuration value for 'IsReleaseBranch' for branch {0} has no value. (this should not happen, please report an issue)", currentBranchConfig.Name)); if (!FullConfiguration.AssemblyVersioningScheme.HasValue) throw new Exception("Configuration value for 'AssemblyVersioningScheme' has no value. (this should not happen, please report an issue)"); @@ -109,12 +109,12 @@ void CalculateEffectiveConfiguration() if (!FullConfiguration.CommitsSinceVersionSourcePadding.HasValue) throw new Exception("Configuration value for 'CommitsSinceVersionSourcePadding' has no value. (this should not happen, please report an issue)"); - var versioningMode = currentBranchConfig.Value.VersioningMode.Value; - var tag = currentBranchConfig.Value.Tag; - var tagNumberPattern = currentBranchConfig.Value.TagNumberPattern; - var incrementStrategy = currentBranchConfig.Value.Increment.Value; - var preventIncrementForMergedBranchVersion = currentBranchConfig.Value.PreventIncrementOfMergedBranchVersion.Value; - var trackMergeTarget = currentBranchConfig.Value.TrackMergeTarget.Value; + var versioningMode = currentBranchConfig.VersioningMode.Value; + var tag = currentBranchConfig.Tag; + var tagNumberPattern = currentBranchConfig.TagNumberPattern; + var incrementStrategy = currentBranchConfig.Increment.Value; + var preventIncrementForMergedBranchVersion = currentBranchConfig.PreventIncrementOfMergedBranchVersion.Value; + var trackMergeTarget = currentBranchConfig.TrackMergeTarget.Value; var nextVersion = FullConfiguration.NextVersion; var assemblyVersioningScheme = FullConfiguration.AssemblyVersioningScheme.Value; @@ -125,12 +125,12 @@ void CalculateEffectiveConfiguration() var patchMessage = FullConfiguration.PatchVersionBumpMessage; var noBumpMessage = FullConfiguration.NoBumpMessage; - var commitMessageVersionBump = currentBranchConfig.Value.CommitMessageIncrementing ?? FullConfiguration.CommitMessageIncrementing.Value; + var commitMessageVersionBump = currentBranchConfig.CommitMessageIncrementing ?? FullConfiguration.CommitMessageIncrementing.Value; Configuration = new EffectiveConfiguration( assemblyVersioningScheme, assemblyInformationalFormat, versioningMode, gitTagPrefix, tag, nextVersion, incrementStrategy, - currentBranchConfig.Value.Regex, + currentBranchConfig.Regex, preventIncrementForMergedBranchVersion, tagNumberPattern, FullConfiguration.ContinuousDeploymentFallbackTag, trackMergeTarget, @@ -140,8 +140,8 @@ void CalculateEffectiveConfiguration() FullConfiguration.BuildMetaDataPadding.Value, FullConfiguration.CommitsSinceVersionSourcePadding.Value, FullConfiguration.Ignore.ToFilters(), - currentBranchConfig.Value.IsDevelop.Value, - currentBranchConfig.Value.IsReleaseBranch.Value); + currentBranchConfig.IsDevelop.Value, + currentBranchConfig.IsReleaseBranch.Value); } } } From a765000b67f6d6d12c17ee27ff6ad35bfd621425 Mon Sep 17 00:00:00 2001 From: Daniel Rose Date: Tue, 4 Oct 2016 14:50:42 +0200 Subject: [PATCH 07/10] Use new struct BranchCommit to lose less information. Use ExcludingBranches extension method. --- src/GitVersionCore/BranchCommit.cs | 51 +++++++++++++++++++ .../BranchConfigurationCalculator.cs | 14 ++--- src/GitVersionCore/GitVersionCore.csproj | 1 + src/GitVersionCore/LibGitExtensions.cs | 51 +++++++++++-------- .../VersionInBranchBaseVersionStrategy.cs | 2 +- 5 files changed, 89 insertions(+), 30 deletions(-) create mode 100644 src/GitVersionCore/BranchCommit.cs diff --git a/src/GitVersionCore/BranchCommit.cs b/src/GitVersionCore/BranchCommit.cs new file mode 100644 index 0000000000..1a2eb652a5 --- /dev/null +++ b/src/GitVersionCore/BranchCommit.cs @@ -0,0 +1,51 @@ +namespace GitVersion +{ + using LibGit2Sharp; + + /// + /// A commit, together with the branch to which the commit belongs. + /// + public struct BranchCommit + { + public static readonly BranchCommit Empty = new BranchCommit(); + + public BranchCommit(Commit commit, Branch branch) : this() + { + Branch = branch; + Commit = commit; + } + + public Branch Branch { get; private set; } + public Commit Commit { get; private set; } + + public bool Equals(BranchCommit other) + { + return Equals(Branch, other.Branch) && Equals(Commit, other.Commit); + } + + public override bool Equals(object obj) + { + if (ReferenceEquals(null, obj)) + return false; + return obj is BranchCommit && Equals((BranchCommit)obj); + } + + public override int GetHashCode() + { + unchecked + { + return ((Branch != null ? Branch.GetHashCode() : 0) * 397) ^ (Commit != null ? Commit.GetHashCode() : 0); + } + } + + public static bool operator ==(BranchCommit left, BranchCommit right) + { + return left.Equals(right); + } + + public static bool operator !=(BranchCommit left, BranchCommit right) + { + return !left.Equals(right); + } + } +} \ No newline at end of file diff --git a/src/GitVersionCore/BranchConfigurationCalculator.cs b/src/GitVersionCore/BranchConfigurationCalculator.cs index 78e1fef0a7..b7cfce74cf 100644 --- a/src/GitVersionCore/BranchConfigurationCalculator.cs +++ b/src/GitVersionCore/BranchConfigurationCalculator.cs @@ -134,24 +134,24 @@ public static IEnumerable FindParentBranches(IRepository repository, Com } excludedBranches = excludedBranches == null ? newlyExcludedBranches : excludedBranches.Union(newlyExcludedBranches).ToArray(); - var branchesToEvaluate = repository.Branches.Where(b => excludedBranches.All(eb => !LibGitExtensions.IsSameBranch(b, eb))).ToList(); + var branchesToEvaluate = repository.Branches.ExcludingBranches(excludedBranches).ToList(); // Try to find the branch point commit, i.e. the commit where the branch was created from a different branch. var branchPoint = currentBranch.FindCommitBranchWasBranchedFrom(repository, excludedBranches); - if (branchPoint == null) + if (branchPoint == BranchCommit.Empty) { - // For whatever reason, no branch point was found. Return all branches containg the current commit, as possible parents. - // TODO correct? Or better empty list? - return currentCommit.GetBranchesContainingCommit(repository, branchesToEvaluate, true); + // For whatever reason, no branch point was found. + return Enumerable.Empty(); } // Return the branch of the branch point commit. - var branches = branchPoint.GetBranchesContainingCommit(repository, branchesToEvaluate, true).ToList(); + // TODO Or use the branch where the commit was found? + var branches = branchPoint.Commit.GetBranchesContainingCommit(repository, branchesToEvaluate, true).ToList(); if (branches.Count > 1) { // The commit is contained in multiple branches => return all, except those also belonging to the commit. var currentTipBranches = currentCommit.GetBranchesContainingCommit(repository, branchesToEvaluate, true); - return branches.Except(currentTipBranches); + return branches.ExcludingBranches(currentTipBranches); } return branches; diff --git a/src/GitVersionCore/GitVersionCore.csproj b/src/GitVersionCore/GitVersionCore.csproj index cd4b515941..adfee1636c 100644 --- a/src/GitVersionCore/GitVersionCore.csproj +++ b/src/GitVersionCore/GitVersionCore.csproj @@ -72,6 +72,7 @@ + diff --git a/src/GitVersionCore/LibGitExtensions.cs b/src/GitVersionCore/LibGitExtensions.cs index de2fdeab30..c9bb070ad8 100644 --- a/src/GitVersionCore/LibGitExtensions.cs +++ b/src/GitVersionCore/LibGitExtensions.cs @@ -36,7 +36,7 @@ public static IEnumerable GetVersionTagsOnBranch(this Branch br /// 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 Commit FindCommitBranchWasBranchedFrom([NotNull] this Branch branch, IRepository repository, params Branch[] excludedBranches) + 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."; @@ -50,35 +50,25 @@ public static Commit FindCommitBranchWasBranchedFrom([NotNull] this Branch branc if (branch.Tip == null) { Logger.WriteWarning(string.Format(missingTipFormat, branch.FriendlyName)); - return null; + return BranchCommit.Empty; } var otherBranches = repository.Branches - .Except(excludedBranches) - .Where(b => IsSameBranch(branch, b)) - .ToList(); + .ExcludingBranches(excludedBranches) + .Where(b => !IsSameBranch(branch, b)); var mergeBases = otherBranches.Select(otherBranch => { if (otherBranch.Tip == null) { Logger.WriteWarning(string.Format(missingTipFormat, otherBranch.FriendlyName)); - return null; + return BranchCommit.Empty; } var findMergeBase = FindMergeBase(branch, otherBranch, repository); - return new - { - mergeBaseCommit = findMergeBase, - branch = otherBranch - }; - }).Where(b => b.mergeBaseCommit != null).OrderByDescending(b => b.mergeBaseCommit.Committer.When).ToList(); + return new BranchCommit(findMergeBase,otherBranch); + }).Where(b => b.Commit != null).OrderByDescending(b => b.Commit.Committer.When); - var firstOrDefault = mergeBases.FirstOrDefault(); - if (firstOrDefault != null) - { - return firstOrDefault.mergeBaseCommit; - } - return null; + return mergeBases.FirstOrDefault(); } } @@ -127,11 +117,28 @@ public static Commit FindMergeBase(this Branch branch, Branch otherBranch, IRepo } } - public static bool IsSameBranch(Branch branch, Branch b) + /// + /// Checks if the two branch objects refer to the same branch (have the same friendly name). + /// + public static bool IsSameBranch(Branch branch, Branch otherBranch) + { + // For each branch, fixup the friendly name if the branch is remote. + var otherBranchFriendlyName = otherBranch.IsRemote ? + otherBranch.FriendlyName.Substring(otherBranch.FriendlyName.IndexOf("/", StringComparison.Ordinal) + 1) : + otherBranch.FriendlyName; + var branchFriendlyName = branch.IsRemote ? + otherBranch.FriendlyName.Substring(branch.FriendlyName.IndexOf("/", StringComparison.Ordinal) + 1) : + branch.FriendlyName; + + 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 (b.IsRemote ? - b.FriendlyName.Substring(b.FriendlyName.IndexOf("/", StringComparison.Ordinal) + 1) : - b.FriendlyName) != branch.FriendlyName; + return branches.Where(b => branchesToExclude.All(bte => !IsSameBranch(b, bte))); } public static IEnumerable GetBranchesContainingCommit([NotNull] this Commit commit, IRepository repository, IList branches, bool onlyTrackedBranches) diff --git a/src/GitVersionCore/VersionCalculation/BaseVersionCalculators/VersionInBranchBaseVersionStrategy.cs b/src/GitVersionCore/VersionCalculation/BaseVersionCalculators/VersionInBranchBaseVersionStrategy.cs index c6749d8f55..6244a73561 100644 --- a/src/GitVersionCore/VersionCalculation/BaseVersionCalculators/VersionInBranchBaseVersionStrategy.cs +++ b/src/GitVersionCore/VersionCalculation/BaseVersionCalculators/VersionInBranchBaseVersionStrategy.cs @@ -27,7 +27,7 @@ public IEnumerable GetVersions(string tagPrefixRegex, Branch curren { var commitBranchWasBranchedFrom = currentBranch.FindCommitBranchWasBranchedFrom(repository); var branchNameOverride = branchName.RegexReplace("[-/]" + versionInBranch.Item1, string.Empty); - yield return new BaseVersion("Version in branch name", false, versionInBranch.Item2, commitBranchWasBranchedFrom, branchNameOverride); + yield return new BaseVersion("Version in branch name", false, versionInBranch.Item2, commitBranchWasBranchedFrom.Commit, branchNameOverride); } } From 80eaf8e17bbc22b2dd2a1362b8d16fae489bdc48 Mon Sep 17 00:00:00 2001 From: Daniel Rose Date: Tue, 4 Oct 2016 15:12:21 +0200 Subject: [PATCH 08/10] Use the first found parent branch. --- .../BranchConfigurationCalculator.cs | 43 +++++-------------- 1 file changed, 10 insertions(+), 33 deletions(-) diff --git a/src/GitVersionCore/BranchConfigurationCalculator.cs b/src/GitVersionCore/BranchConfigurationCalculator.cs index b7cfce74cf..630cce9d58 100644 --- a/src/GitVersionCore/BranchConfigurationCalculator.cs +++ b/src/GitVersionCore/BranchConfigurationCalculator.cs @@ -83,22 +83,17 @@ static IEnumerable LookupBranchConfiguration([NotNull] Config conf using (Logger.IndentLog("Attempting to get increment value from parent branch")) { - var possibleParents = FindParentBranches(repository, currentCommit, currentBranch, excludedBranches).ToList(); - - if (possibleParents.Count == 1) + var firstParentBranch = FindFirstParentBranch(repository, currentCommit, currentBranch, excludedBranches); + if (firstParentBranch != BranchCommit.Empty) { - // Single parent found => get its IncrementStrategy. - var branchConfig = GetBranchConfiguration(currentCommit, repository, onlyEvaluateTrackedBranches, config, possibleParents[0], excludedBranches); + // A parent was found => get its IncrementStrategy. + var branchConfig = GetBranchConfiguration(currentCommit, repository, onlyEvaluateTrackedBranches, config, firstParentBranch.Branch, excludedBranches); return branchConfig.Increment; } - // Multiple parents found; it is probably because the branch has been merged and we can't do much. + // No parent found; it is probably because the branch has been merged and we can't do much. // So we will fall back to develop's value if develop exists and master if not. - string errorMessage; - if (possibleParents.Count == 0) - errorMessage = "Failed to inherit Increment branch configuration, no branches found."; - else - errorMessage = "Failed to inherit Increment branch configuration, ended up with: " + string.Join(", ", possibleParents.Select(p => p.FriendlyName)); + const string errorMessage = "Failed to inherit Increment branch configuration, no branches found."; var chosenBranch = repository.Branches.FirstOrDefault(b => Regex.IsMatch(b.FriendlyName, "^develop", RegexOptions.IgnoreCase) || Regex.IsMatch(b.FriendlyName, "master$", RegexOptions.IgnoreCase)); @@ -117,11 +112,11 @@ static IEnumerable LookupBranchConfiguration([NotNull] Config conf } } - public static IEnumerable FindParentBranches(IRepository repository, Commit currentCommit, Branch currentBranch, Branch[] excludedBranches) + public static BranchCommit FindFirstParentBranch(IRepository repository, Commit currentCommit, Branch currentBranch, Branch[] excludedBranches) { - using (Logger.IndentLog("Searching for parent branches")) + using (Logger.IndentLog("Searching for parent branch")) { - // Find out which branches to exclude as possible parent branches: The current branch, and possibly more in case of a merge commit. + // Find out which branches to exclude as possible parent branch: The current branch, and possibly more in case of a merge commit. var newlyExcludedBranches = new[] { currentBranch @@ -134,27 +129,9 @@ public static IEnumerable FindParentBranches(IRepository repository, Com } excludedBranches = excludedBranches == null ? newlyExcludedBranches : excludedBranches.Union(newlyExcludedBranches).ToArray(); - var branchesToEvaluate = repository.Branches.ExcludingBranches(excludedBranches).ToList(); // Try to find the branch point commit, i.e. the commit where the branch was created from a different branch. - var branchPoint = currentBranch.FindCommitBranchWasBranchedFrom(repository, excludedBranches); - if (branchPoint == BranchCommit.Empty) - { - // For whatever reason, no branch point was found. - return Enumerable.Empty(); - } - - // Return the branch of the branch point commit. - // TODO Or use the branch where the commit was found? - var branches = branchPoint.Commit.GetBranchesContainingCommit(repository, branchesToEvaluate, true).ToList(); - if (branches.Count > 1) - { - // The commit is contained in multiple branches => return all, except those also belonging to the commit. - var currentTipBranches = currentCommit.GetBranchesContainingCommit(repository, branchesToEvaluate, true); - return branches.ExcludingBranches(currentTipBranches); - } - - return branches; + return currentBranch.FindCommitBranchWasBranchedFrom(repository, excludedBranches); } } From f3cbcf801061088d16f3f788224a479e22d11f6c Mon Sep 17 00:00:00 2001 From: Daniel Rose Date: Tue, 4 Oct 2016 16:00:04 +0200 Subject: [PATCH 09/10] Store the excluded branches in a HashSet. --- .../BranchConfigurationCalculator.cs | 40 +++++++++---------- src/GitVersionCore/GitVersionContext.cs | 10 +++-- 2 files changed, 24 insertions(+), 26 deletions(-) diff --git a/src/GitVersionCore/BranchConfigurationCalculator.cs b/src/GitVersionCore/BranchConfigurationCalculator.cs index 630cce9d58..a0085d1577 100644 --- a/src/GitVersionCore/BranchConfigurationCalculator.cs +++ b/src/GitVersionCore/BranchConfigurationCalculator.cs @@ -19,7 +19,7 @@ public class BranchConfigurationCalculator /// /// A KeyValuePair. The key is the name of the branch configuration (from the yaml or the default configs); the value is the actual configuration. /// - public static BranchConfig GetBranchConfiguration(Commit currentCommit, IRepository repository, bool onlyEvaluateTrackedBranches, Config config, Branch currentBranch, Branch[] excludedBranches) + public static BranchConfig GetBranchConfiguration(Commit currentCommit, IRepository repository, bool onlyEvaluateTrackedBranches, Config config, Branch currentBranch, [NotNull] HashSet excludedBranches) { var matchingBranches = LookupBranchConfiguration(config, currentBranch).ToArray(); @@ -73,7 +73,7 @@ static IEnumerable LookupBranchConfiguration([NotNull] Config conf /// /// Recursively look for an IncrementStrategy in the parent branches, which is set and different than . /// - static IncrementStrategy? GetParentIncrementStrategy(bool onlyEvaluateTrackedBranches, IRepository repository, Commit currentCommit, Branch currentBranch, BranchConfig branchConfiguration, Config config, Branch[] excludedBranches) + static IncrementStrategy? GetParentIncrementStrategy(bool onlyEvaluateTrackedBranches, IRepository repository, Commit currentCommit, Branch currentBranch, BranchConfig branchConfiguration, Config config, HashSet excludedBranches) { if (branchConfiguration.Increment != IncrementStrategy.Inherit && branchConfiguration.Increment != null) { @@ -112,49 +112,47 @@ static IEnumerable LookupBranchConfiguration([NotNull] Config conf } } - public static BranchCommit FindFirstParentBranch(IRepository repository, Commit currentCommit, Branch currentBranch, Branch[] excludedBranches) + public static BranchCommit FindFirstParentBranch(IRepository repository, Commit currentCommit, Branch currentBranch, HashSet excludedBranches) { using (Logger.IndentLog("Searching for parent branch")) { // Find out which branches to exclude as possible parent branch: The current branch, and possibly more in case of a merge commit. - var newlyExcludedBranches = new[] - { - currentBranch - }; - // Check if we are a merge commit. If so likely we are a pull request + excludedBranches.Add(currentBranch); + + // Check if we are a merge commit. If so, likely we are a pull request. var parentCount = currentCommit.Parents.Count(); if (parentCount == 2) { - newlyExcludedBranches = CalculateWhenMultipleParents(repository, currentCommit, ref currentBranch, newlyExcludedBranches); + CalculateWhenMultipleParents(repository, currentCommit, ref currentBranch, excludedBranches); } - excludedBranches = excludedBranches == null ? newlyExcludedBranches : excludedBranches.Union(newlyExcludedBranches).ToArray(); - // Try to find the branch point commit, i.e. the commit where the branch was created from a different branch. - return currentBranch.FindCommitBranchWasBranchedFrom(repository, excludedBranches); + return currentBranch.FindCommitBranchWasBranchedFrom(repository, excludedBranches.ToArray()); } } - static Branch[] CalculateWhenMultipleParents(IRepository repository, Commit currentCommit, ref Branch currentBranch, Branch[] excludedBranches) + /// + /// Figure out what to do when there are multiple candidate parent branches (due to a merge commit). + /// + static void CalculateWhenMultipleParents(IRepository repository, Commit currentCommit, ref Branch currentBranch, HashSet excludedBranches) { var parents = currentCommit.Parents.ToArray(); var branches = repository.Branches.Where(b => !b.IsRemote && b.Tip == parents[1]).ToList(); if (branches.Count == 1) { - var branch = branches[0]; - excludedBranches = new[] - { - currentBranch, - branch - }; - currentBranch = branch; + // Only one parent branch is relevant => use it. + var parentBranchToUse = branches[0]; + excludedBranches.Add(parentBranchToUse); + currentBranch = parentBranchToUse; } else if (branches.Count > 1) { + // Both branches can be used => use 'master', otherwise the first one. currentBranch = branches.FirstOrDefault(b => b.FriendlyName == "master") ?? branches.First(); } else { + // None is relevant => check the other parent. var possibleTargetBranches = repository.Branches.Where(b => !b.IsRemote && b.Tip == parents[0]).ToList(); if (possibleTargetBranches.Count > 1) { @@ -167,8 +165,6 @@ static Branch[] CalculateWhenMultipleParents(IRepository repository, Commit curr } Logger.WriteInfo("HEAD is merge commit, this is likely a pull request using " + currentBranch.FriendlyName + " as base"); - - return excludedBranches; } } } \ No newline at end of file diff --git a/src/GitVersionCore/GitVersionContext.cs b/src/GitVersionCore/GitVersionContext.cs index e2fbd56f56..c42fb24a27 100644 --- a/src/GitVersionCore/GitVersionContext.cs +++ b/src/GitVersionCore/GitVersionContext.cs @@ -2,6 +2,7 @@ { using LibGit2Sharp; using System; + using System.Collections.Generic; using System.Linq; /// @@ -53,7 +54,7 @@ public GitVersionContext(IRepository repository, Branch currentBranch, Config co CurrentBranch = currentBranch; } - CalculateEffectiveConfiguration(); + Configuration = CalculateEffectiveConfiguration(); CurrentCommitTaggedVersion = repository.Tags .SelectMany(t => @@ -81,9 +82,10 @@ public GitVersionContext(IRepository repository, Branch currentBranch, Config co public Commit CurrentCommit { get; private set; } public bool IsCurrentCommitTagged { get; private set; } - void CalculateEffectiveConfiguration() + EffectiveConfiguration CalculateEffectiveConfiguration() { - var currentBranchConfig = BranchConfigurationCalculator.GetBranchConfiguration(CurrentCommit, Repository, OnlyEvaluateTrackedBranches, FullConfiguration, CurrentBranch, null); + var excludedBranches = new HashSet(); + var currentBranchConfig = BranchConfigurationCalculator.GetBranchConfiguration(CurrentCommit, Repository, OnlyEvaluateTrackedBranches, FullConfiguration, CurrentBranch, excludedBranches); 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)); @@ -127,7 +129,7 @@ void CalculateEffectiveConfiguration() var commitMessageVersionBump = currentBranchConfig.CommitMessageIncrementing ?? FullConfiguration.CommitMessageIncrementing.Value; - Configuration = new EffectiveConfiguration( + return new EffectiveConfiguration( assemblyVersioningScheme, assemblyInformationalFormat, versioningMode, gitTagPrefix, tag, nextVersion, incrementStrategy, currentBranchConfig.Regex, From b24c817e1a85e5bc49d5421769fc9e824efd2b48 Mon Sep 17 00:00:00 2001 From: Daniel Rose Date: Wed, 16 Nov 2016 11:14:20 +0100 Subject: [PATCH 10/10] Use parent branches's configuration. --- .../GitToolsTestingExtensions.cs | 3 +- .../GitVersionContextTests.cs | 7 +- .../FeatureBranchScenarios.cs | 6 +- .../TestEffectiveConfiguration.cs | 6 +- .../BranchConfigurationCalculator.cs | 2 +- src/GitVersionCore/EffectiveConfiguration.cs | 13 +- src/GitVersionCore/ExecuteCore.cs | 2 +- src/GitVersionCore/GitVersionContext.cs | 160 ++++++++++++------ src/GitVersionCore/IncrementStrategyFinder.cs | 24 +-- .../BaseVersionCalculator.cs | 41 +++-- .../ConfigNextVersionBaseVersionStrategy.cs | 6 +- .../MergeMessageBaseVersionStrategy.cs | 39 +++-- .../TaggedCommitVersionStrategy.cs | 49 +++--- .../VersionInBranchBaseVersionStrategy.cs | 24 +-- .../DevelopVersionStrategy.cs | 27 ++- .../NextVersionCalculator.cs | 17 +- .../VersioningModes/ContinuousDeliveryMode.cs | 4 +- .../ContinuousDeploymentMode.cs | 4 +- .../AssemblyInfoFileUpdateTests.cs | 4 +- 19 files changed, 261 insertions(+), 177 deletions(-) diff --git a/src/GitVersionCore.Tests/GitToolsTestingExtensions.cs b/src/GitVersionCore.Tests/GitToolsTestingExtensions.cs index c556e0d7ab..b0898c39f3 100644 --- a/src/GitVersionCore.Tests/GitToolsTestingExtensions.cs +++ b/src/GitVersionCore.Tests/GitToolsTestingExtensions.cs @@ -1,6 +1,7 @@ namespace GitVersionCore.Tests { using System; + using System.Linq; using GitTools; using GitTools.Testing; using GitVersion; @@ -24,7 +25,7 @@ public static VersionVariables GetVersion(this RepositoryFixtureBase fixture, Co } var gitVersionContext = new GitVersionContext(repository ?? fixture.Repository, configuration, isForTrackedBranchOnly, commitId); var executeGitVersion = ExecuteGitVersion(gitVersionContext); - var variables = VariableProvider.GetVariablesFor(executeGitVersion, gitVersionContext.Configuration, gitVersionContext.IsCurrentCommitTagged); + var variables = VariableProvider.GetVariablesFor(executeGitVersion, gitVersionContext.Configurations.First(), gitVersionContext.IsCurrentCommitTagged); try { return variables; diff --git a/src/GitVersionCore.Tests/GitVersionContextTests.cs b/src/GitVersionCore.Tests/GitVersionContextTests.cs index b5a567703a..436a016184 100644 --- a/src/GitVersionCore.Tests/GitVersionContextTests.cs +++ b/src/GitVersionCore.Tests/GitVersionContextTests.cs @@ -1,5 +1,6 @@ namespace GitVersionCore.Tests { + using System.Linq; using GitTools.Testing; using GitVersion; using LibGit2Sharp; @@ -28,7 +29,7 @@ public void CanInheritVersioningMode(VersioningMode mode) }; var context = new GitVersionContext(mockRepository, mockBranch, config); - context.Configuration.VersioningMode.ShouldBe(mode); + context.Configurations.First().VersioningMode.ShouldBe(mode); } [Test] @@ -59,7 +60,7 @@ public void UsesBranchSpecificConfigOverTopLevelDefaults() } }; var context = new GitVersionContext(mockRepository, develop, config); - context.Configuration.Tag.ShouldBe("alpha"); + context.Configurations.First().Tag.ShouldBe("alpha"); } [Test] @@ -84,7 +85,7 @@ public void CanFindParentBranchForInheritingIncrementStrategy() repo.Repository.MakeACommit(); var context = new GitVersionContext(repo.Repository, config); - context.Configuration.Increment.ShouldBe(IncrementStrategy.Major); + context.Configurations.First().Increment.ShouldBe(IncrementStrategy.Major); } } } diff --git a/src/GitVersionCore.Tests/IntegrationTests/FeatureBranchScenarios.cs b/src/GitVersionCore.Tests/IntegrationTests/FeatureBranchScenarios.cs index 0f0609167a..419b18b7eb 100644 --- a/src/GitVersionCore.Tests/IntegrationTests/FeatureBranchScenarios.cs +++ b/src/GitVersionCore.Tests/IntegrationTests/FeatureBranchScenarios.cs @@ -305,11 +305,11 @@ public void ShouldPickUpVersionFromMasterAfterReleaseBranchCreated() using (var fixture = new EmptyRepositoryFixture()) { // Create release branch - fixture.MakeACommit(); + fixture.MakeACommit("master #1"); fixture.BranchTo("release/1.0"); - fixture.MakeACommit(); + fixture.MakeACommit("release #1"); fixture.Checkout("master"); - fixture.MakeACommit(); + fixture.MakeACommit("master #2"); fixture.AssertFullSemver(config, "1.0.1+1"); // create a feature branch from master and verify the version diff --git a/src/GitVersionCore.Tests/TestEffectiveConfiguration.cs b/src/GitVersionCore.Tests/TestEffectiveConfiguration.cs index d8ea075bc7..13d3b743ab 100644 --- a/src/GitVersionCore.Tests/TestEffectiveConfiguration.cs +++ b/src/GitVersionCore.Tests/TestEffectiveConfiguration.cs @@ -29,14 +29,16 @@ public TestEffectiveConfiguration( int commitsSinceVersionSourcePadding = 4, IEnumerable versionFilters = null, bool isDevelop = false, - bool isRelease = false) : + bool isRelease = false, + ConfigInfo currentBranchInfo = null) : base(assemblyVersioningScheme, assemblyInformationalFormat, versioningMode, gitTagPrefix, tag, nextVersion, IncrementStrategy.Patch, branchPrefixToTrim, preventIncrementForMergedBranchVersion, tagNumberPattern, continuousDeploymentFallbackTag, trackMergeTarget, majorMessage, minorMessage, patchMessage, noBumpMessage, commitMessageMode, legacySemVerPadding, buildMetaDataPadding, commitsSinceVersionSourcePadding, versionFilters ?? Enumerable.Empty(), - isDevelop, isRelease) + isDevelop, isRelease, + currentBranchInfo) { } } diff --git a/src/GitVersionCore/BranchConfigurationCalculator.cs b/src/GitVersionCore/BranchConfigurationCalculator.cs index a0085d1577..bebb0c14be 100644 --- a/src/GitVersionCore/BranchConfigurationCalculator.cs +++ b/src/GitVersionCore/BranchConfigurationCalculator.cs @@ -114,7 +114,7 @@ static IEnumerable LookupBranchConfiguration([NotNull] Config conf public static BranchCommit FindFirstParentBranch(IRepository repository, Commit currentCommit, Branch currentBranch, HashSet excludedBranches) { - using (Logger.IndentLog("Searching for parent branch")) + using (Logger.IndentLog(string.Format("Searching for parent branch of '{0}'", currentBranch.FriendlyName))) { // Find out which branches to exclude as possible parent branch: The current branch, and possibly more in case of a merge commit. excludedBranches.Add(currentBranch); diff --git a/src/GitVersionCore/EffectiveConfiguration.cs b/src/GitVersionCore/EffectiveConfiguration.cs index 522e98b4e0..613a6d3151 100644 --- a/src/GitVersionCore/EffectiveConfiguration.cs +++ b/src/GitVersionCore/EffectiveConfiguration.cs @@ -11,8 +11,11 @@ public class EffectiveConfiguration public EffectiveConfiguration( AssemblyVersioningScheme assemblyVersioningScheme, string assemblyInformationalFormat, - VersioningMode versioningMode, string gitTagPrefix, - string tag, string nextVersion, IncrementStrategy increment, + VersioningMode versioningMode, + string gitTagPrefix, + string tag, + string nextVersion, + IncrementStrategy increment, string branchPrefixToTrim, bool preventIncrementForMergedBranchVersion, string tagNumberPattern, @@ -28,7 +31,8 @@ public EffectiveConfiguration( int commitsSinceVersionSourcePadding, IEnumerable versionFilters, bool isCurrentBranchDevelop, - bool isCurrentBranchRelease) + bool isCurrentBranchRelease, + ConfigInfo currentBranchInfo) { AssemblyVersioningScheme = assemblyVersioningScheme; AssemblyInformationalFormat = assemblyInformationalFormat; @@ -53,8 +57,11 @@ public EffectiveConfiguration( VersionFilters = versionFilters; IsCurrentBranchDevelop = isCurrentBranchDevelop; IsCurrentBranchRelease = isCurrentBranchRelease; + CurrentBranchInfo = currentBranchInfo; } + public ConfigInfo CurrentBranchInfo { get; private set; } + public bool IsCurrentBranchDevelop { get; private set; } public bool IsCurrentBranchRelease { get; private set; } diff --git a/src/GitVersionCore/ExecuteCore.cs b/src/GitVersionCore/ExecuteCore.cs index b207f41f84..22c2f192a3 100644 --- a/src/GitVersionCore/ExecuteCore.cs +++ b/src/GitVersionCore/ExecuteCore.cs @@ -110,7 +110,7 @@ VersionVariables ExecuteInternal(string targetBranch, string commitId, GitPrepar var gitVersionContext = new GitVersionContext(repo, configuration, commitId: commitId); var semanticVersion = versionFinder.FindVersion(gitVersionContext); - return VariableProvider.GetVariablesFor(semanticVersion, gitVersionContext.Configuration, gitVersionContext.IsCurrentCommitTagged); + return VariableProvider.GetVariablesFor(semanticVersion, gitVersionContext.Configurations.First(), gitVersionContext.IsCurrentCommitTagged); }); } diff --git a/src/GitVersionCore/GitVersionContext.cs b/src/GitVersionCore/GitVersionContext.cs index c42fb24a27..bd98213343 100644 --- a/src/GitVersionCore/GitVersionContext.cs +++ b/src/GitVersionCore/GitVersionContext.cs @@ -54,13 +54,13 @@ public GitVersionContext(IRepository repository, Branch currentBranch, Config co CurrentBranch = currentBranch; } - Configuration = CalculateEffectiveConfiguration(); + Configurations = CalculateEffectiveConfiguration().ToArray(); CurrentCommitTaggedVersion = repository.Tags .SelectMany(t => { SemanticVersion version; - if (t.PeeledTarget() == CurrentCommit && SemanticVersion.TryParse(t.FriendlyName, Configuration.GitTagPrefix, out version)) + if (t.PeeledTarget() == CurrentCommit && SemanticVersion.TryParse(t.FriendlyName, Configurations.First().GitTagPrefix, out version)) return new[] { version }; return new SemanticVersion[0]; }) @@ -69,37 +69,21 @@ public GitVersionContext(IRepository repository, Branch currentBranch, Config co } /// - /// Contains the raw configuration, use Configuration for specific config based on the current GitVersion context. + /// Contains the raw configuration, use Configurations for the specific configs based on the current GitVersion context. /// public Config FullConfiguration { get; private set; } public SemanticVersion CurrentCommitTaggedVersion { get; private set; } public bool OnlyEvaluateTrackedBranches { get; private set; } - public EffectiveConfiguration Configuration { get; private set; } + public ICollection Configurations { get; private set; } public IRepository Repository { get; private set; } public Branch CurrentBranch { get; private set; } public Commit CurrentCommit { get; private set; } public bool IsCurrentCommitTagged { get; private set; } - EffectiveConfiguration CalculateEffectiveConfiguration() + IEnumerable CalculateEffectiveConfiguration() { - var excludedBranches = new HashSet(); - var currentBranchConfig = BranchConfigurationCalculator.GetBranchConfiguration(CurrentCommit, Repository, OnlyEvaluateTrackedBranches, FullConfiguration, CurrentBranch, excludedBranches); - - 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)); - if (!currentBranchConfig.Increment.HasValue) - throw new Exception(string.Format("Configuration value for 'Increment' for branch {0} has no value. (this should not happen, please report an issue)", currentBranchConfig.Name)); - if (!currentBranchConfig.PreventIncrementOfMergedBranchVersion.HasValue) - throw new Exception(string.Format("Configuration value for 'PreventIncrementOfMergedBranchVersion' for branch {0} has no value. (this should not happen, please report an issue)", currentBranchConfig.Name)); - if (!currentBranchConfig.TrackMergeTarget.HasValue) - throw new Exception(string.Format("Configuration value for 'TrackMergeTarget' for branch {0} has no value. (this should not happen, please report an issue)", currentBranchConfig.Name)); - if (!currentBranchConfig.IsDevelop.HasValue) - throw new Exception(string.Format("Configuration value for 'IsDevelop' for branch {0} has no value. (this should not happen, please report an issue)", currentBranchConfig.Name)); - if (!currentBranchConfig.IsReleaseBranch.HasValue) - throw new Exception(string.Format("Configuration value for 'IsReleaseBranch' for branch {0} has no value. (this should not happen, please report an issue)", currentBranchConfig.Name)); - if (!FullConfiguration.AssemblyVersioningScheme.HasValue) throw new Exception("Configuration value for 'AssemblyVersioningScheme' has no value. (this should not happen, please report an issue)"); if (!FullConfiguration.CommitMessageIncrementing.HasValue) @@ -111,39 +95,107 @@ EffectiveConfiguration CalculateEffectiveConfiguration() if (!FullConfiguration.CommitsSinceVersionSourcePadding.HasValue) throw new Exception("Configuration value for 'CommitsSinceVersionSourcePadding' has no value. (this should not happen, please report an issue)"); - var versioningMode = currentBranchConfig.VersioningMode.Value; - var tag = currentBranchConfig.Tag; - var tagNumberPattern = currentBranchConfig.TagNumberPattern; - var incrementStrategy = currentBranchConfig.Increment.Value; - var preventIncrementForMergedBranchVersion = currentBranchConfig.PreventIncrementOfMergedBranchVersion.Value; - var trackMergeTarget = currentBranchConfig.TrackMergeTarget.Value; - - var nextVersion = FullConfiguration.NextVersion; - var assemblyVersioningScheme = FullConfiguration.AssemblyVersioningScheme.Value; - var assemblyInformationalFormat = FullConfiguration.AssemblyInformationalFormat; - var gitTagPrefix = FullConfiguration.TagPrefix; - var majorMessage = FullConfiguration.MajorVersionBumpMessage; - var minorMessage = FullConfiguration.MinorVersionBumpMessage; - var patchMessage = FullConfiguration.PatchVersionBumpMessage; - var noBumpMessage = FullConfiguration.NoBumpMessage; - - var commitMessageVersionBump = currentBranchConfig.CommitMessageIncrementing ?? FullConfiguration.CommitMessageIncrementing.Value; - - return new EffectiveConfiguration( - assemblyVersioningScheme, assemblyInformationalFormat, versioningMode, gitTagPrefix, - tag, nextVersion, incrementStrategy, - currentBranchConfig.Regex, - preventIncrementForMergedBranchVersion, - tagNumberPattern, FullConfiguration.ContinuousDeploymentFallbackTag, - trackMergeTarget, - majorMessage, minorMessage, patchMessage, noBumpMessage, - commitMessageVersionBump, - FullConfiguration.LegacySemVerPadding.Value, - FullConfiguration.BuildMetaDataPadding.Value, - FullConfiguration.CommitsSinceVersionSourcePadding.Value, - FullConfiguration.Ignore.ToFilters(), - currentBranchConfig.IsDevelop.Value, - currentBranchConfig.IsReleaseBranch.Value); + var excludedBranches = new HashSet(); + var firstCommit = CurrentCommit; + var branch = CurrentBranch; + + var parentBranchesInfo = new List(); + while (true) + { + var branchConfig = BranchConfigurationCalculator.GetBranchConfiguration(firstCommit, Repository, OnlyEvaluateTrackedBranches, FullConfiguration, branch, new HashSet(excludedBranches)); + + var firstParentBranch = BranchConfigurationCalculator.FindFirstParentBranch(Repository, firstCommit, branch, excludedBranches); + if (firstParentBranch != BranchCommit.Empty) + { + // A parent was found. + var configInfo = new ConfigInfo(branchConfig, branch, firstParentBranch.Branch, firstCommit, firstParentBranch.Commit, Repository); + parentBranchesInfo.Add(configInfo); + + firstCommit = firstParentBranch.Commit; + branch = firstParentBranch.Branch; + } + else + { + // No more parents => We are done. + var configInfo = new ConfigInfo(branchConfig, branch, null, firstCommit, null, Repository); + parentBranchesInfo.Add(configInfo); + break; + } + } + + foreach (var currentBranchInfo in parentBranchesInfo) + { + var currentBranchConfig = currentBranchInfo.Config; + 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)); + if (!currentBranchConfig.Increment.HasValue) + throw new Exception(string.Format("Configuration value for 'Increment' for branch {0} has no value. (this should not happen, please report an issue)", currentBranchConfig.Name)); + if (!currentBranchConfig.PreventIncrementOfMergedBranchVersion.HasValue) + throw new Exception(string.Format("Configuration value for 'PreventIncrementOfMergedBranchVersion' for branch {0} has no value. (this should not happen, please report an issue)", currentBranchConfig.Name)); + if (!currentBranchConfig.TrackMergeTarget.HasValue) + throw new Exception(string.Format("Configuration value for 'TrackMergeTarget' for branch {0} has no value. (this should not happen, please report an issue)", currentBranchConfig.Name)); + if (!currentBranchConfig.IsDevelop.HasValue) + throw new Exception(string.Format("Configuration value for 'IsDevelop' for branch {0} has no value. (this should not happen, please report an issue)", currentBranchConfig.Name)); + if (!currentBranchConfig.IsReleaseBranch.HasValue) + throw new Exception(string.Format("Configuration value for 'IsReleaseBranch' for branch {0} has no value. (this should not happen, please report an issue)", currentBranchConfig.Name)); + + yield return new EffectiveConfiguration( + FullConfiguration.AssemblyVersioningScheme.Value, + FullConfiguration.AssemblyInformationalFormat, + currentBranchConfig.VersioningMode.Value, + FullConfiguration.TagPrefix, + currentBranchConfig.Tag, + FullConfiguration.NextVersion, + currentBranchConfig.Increment.Value, + currentBranchConfig.Regex, + currentBranchConfig.PreventIncrementOfMergedBranchVersion.Value, + currentBranchConfig.TagNumberPattern, + FullConfiguration.ContinuousDeploymentFallbackTag, + currentBranchConfig.TrackMergeTarget.Value, + FullConfiguration.MajorVersionBumpMessage, + FullConfiguration.MinorVersionBumpMessage, + FullConfiguration.PatchVersionBumpMessage, + FullConfiguration.NoBumpMessage, + currentBranchConfig.CommitMessageIncrementing ?? FullConfiguration.CommitMessageIncrementing.Value, + FullConfiguration.LegacySemVerPadding.Value, + FullConfiguration.BuildMetaDataPadding.Value, + FullConfiguration.CommitsSinceVersionSourcePadding.Value, + FullConfiguration.Ignore.ToFilters(), + currentBranchConfig.IsDevelop.Value, + currentBranchConfig.IsReleaseBranch.Value, + currentBranchInfo); + } + } + } + + public class ConfigInfo + { + public ConfigInfo(BranchConfig config, Branch branch, Branch parentBranch, Commit firstCommit, Commit lastCommit, IRepository repository) + { + Config = config; + Branch = branch; + ParentBranch = parentBranch; + FirstCommit = firstCommit; + LastCommit = lastCommit; + Repository = repository; + } + + public BranchConfig Config { get; private set; } + public Branch Branch { get; private set; } + public Branch ParentBranch { get; private set; } + public Commit FirstCommit { get; private set; } + public Commit LastCommit { get; private set; } + public IRepository Repository { get; private set; } + + /// + /// Gets the relevant commits in the branch, i.e. all the commits between the and . + /// + public IEnumerable RelevantCommits + { + get + { + return Branch.Commits.SkipWhile(commit => commit != FirstCommit).TakeWhile(commit => commit != LastCommit); + } } } } diff --git a/src/GitVersionCore/IncrementStrategyFinder.cs b/src/GitVersionCore/IncrementStrategyFinder.cs index 73723862a3..035c34ad01 100644 --- a/src/GitVersionCore/IncrementStrategyFinder.cs +++ b/src/GitVersionCore/IncrementStrategyFinder.cs @@ -23,8 +23,8 @@ public static class IncrementStrategyFinder public static VersionField? DetermineIncrementedField(GitVersionContext context, BaseVersion baseVersion) { - var commitMessageIncrement = FindCommitMessageIncrement(context, baseVersion); - var defaultIncrement = context.Configuration.Increment.ToVersionField(); + var commitMessageIncrement = FindCommitMessageIncrement(context, context.Configurations.First(), baseVersion); + var defaultIncrement = context.Configurations.First().Increment.ToVersionField(); // use the default branch config increment strategy if there are no commit message overrides if (commitMessageIncrement == null) @@ -48,29 +48,29 @@ public static class IncrementStrategyFinder return commitMessageIncrement; } - private static VersionField? FindCommitMessageIncrement(GitVersionContext context, BaseVersion baseVersion) + private static VersionField? FindCommitMessageIncrement(GitVersionContext context, EffectiveConfiguration configuration, BaseVersion baseVersion) { - if (context.Configuration.CommitMessageIncrementing == CommitMessageIncrementMode.Disabled) + if (configuration.CommitMessageIncrementing == CommitMessageIncrementMode.Disabled) { return null; } - + var commits = GetIntermediateCommits(context.Repository, baseVersion.BaseVersionSource, context.CurrentCommit); - if (context.Configuration.CommitMessageIncrementing == CommitMessageIncrementMode.MergeMessageOnly) + if (configuration.CommitMessageIncrementing == CommitMessageIncrementMode.MergeMessageOnly) { commits = commits.Where(c => c.Parents.Count() > 1); } - return GetIncrementForCommits(context, commits); + return GetIncrementForCommits(configuration, commits); } - public static VersionField? GetIncrementForCommits(GitVersionContext context, IEnumerable commits) + public static VersionField? GetIncrementForCommits(EffectiveConfiguration configuration, IEnumerable commits) { - var majorRegex = CreateRegex(context.Configuration.MajorVersionBumpMessage ?? DefaultMajorPattern); - var minorRegex = CreateRegex(context.Configuration.MinorVersionBumpMessage ?? DefaultMinorPattern); - var patchRegex = CreateRegex(context.Configuration.PatchVersionBumpMessage ?? DefaultPatchPattern); - var none = CreateRegex(context.Configuration.NoBumpMessage ?? DefaultNoBumpPattern); + var majorRegex = CreateRegex(configuration.MajorVersionBumpMessage ?? DefaultMajorPattern); + var minorRegex = CreateRegex(configuration.MinorVersionBumpMessage ?? DefaultMinorPattern); + var patchRegex = CreateRegex(configuration.PatchVersionBumpMessage ?? DefaultPatchPattern); + var none = CreateRegex(configuration.NoBumpMessage ?? DefaultNoBumpPattern); var increments = commits .Select(c => FindIncrementFromMessage(c.Message, majorRegex, minorRegex, patchRegex, none)) diff --git a/src/GitVersionCore/VersionCalculation/BaseVersionCalculator.cs b/src/GitVersionCore/VersionCalculation/BaseVersionCalculator.cs index e3b9c29275..4f873f85a8 100644 --- a/src/GitVersionCore/VersionCalculation/BaseVersionCalculator.cs +++ b/src/GitVersionCore/VersionCalculation/BaseVersionCalculator.cs @@ -18,20 +18,26 @@ public BaseVersion GetBaseVersion(GitVersionContext context) using (Logger.IndentLog("Calculating base versions")) { var baseVersions = strategies - .SelectMany(s => s.GetVersions(context)) + .SelectMany(s => + // TODO Return the configuration used. + s.GetVersions(context).Select(version => Tuple.Create(s, version))) .Where(v => { - if (v == null) return false; + if (v == null || v.Item2 == null) + return false; Logger.WriteInfo(v.ToString()); - foreach (var filter in context.Configuration.VersionFilters) + foreach (var config in context.Configurations) { - string reason; - if (filter.Exclude(v, out reason)) + foreach (var filter in config.VersionFilters) { - Logger.WriteInfo(reason); - return false; + string reason; + if (filter.Exclude(v.Item2, out reason)) + { + Logger.WriteInfo(reason); + return false; + } } } @@ -39,19 +45,21 @@ public BaseVersion GetBaseVersion(GitVersionContext context) }) .Select(v => new { - IncrementedVersion = MaybeIncrement(context, v), - Version = v + IncrementedVersion = MaybeIncrement(context, v.Item2), + Version = v, + Source = v.Item2.Source, + Strategy = v.Item1 }) .ToList(); var maxVersion = baseVersions.Aggregate((v1, v2) => v1.IncrementedVersion > v2.IncrementedVersion ? v1 : v2); var matchingVersionsOnceIncremented = baseVersions - .Where(b => b.Version.BaseVersionSource != null && b.IncrementedVersion == maxVersion.IncrementedVersion) + .Where(b => b.Version.Item2.BaseVersionSource != null && b.IncrementedVersion == maxVersion.IncrementedVersion) .ToList(); BaseVersion baseVersionWithOldestSource; if (matchingVersionsOnceIncremented.Any()) { - baseVersionWithOldestSource = matchingVersionsOnceIncremented.Aggregate((v1, v2) => v1.Version.BaseVersionSource.Committer.When < v2.Version.BaseVersionSource.Committer.When ? v1 : v2).Version; + baseVersionWithOldestSource = matchingVersionsOnceIncremented.Aggregate((v1, v2) => v1.Version.Item2.BaseVersionSource.Committer.When < v2.Version.Item2.BaseVersionSource.Committer.When ? v1 : v2).Version.Item2; Logger.WriteInfo(string.Format( "Found multiple base versions which will produce the same SemVer ({0}), taking oldest source for commit counting ({1})", maxVersion.IncrementedVersion, @@ -60,22 +68,23 @@ public BaseVersion GetBaseVersion(GitVersionContext context) else { baseVersionWithOldestSource = baseVersions - .Where(v => v.Version.BaseVersionSource != null) + .Where(v => v.Version.Item2.BaseVersionSource != null) .OrderByDescending(v => v.IncrementedVersion) - .ThenByDescending(v => v.Version.BaseVersionSource.Committer.When) + .ThenByDescending(v => v.Version.Item2.BaseVersionSource.Committer.When) .First() - .Version; + .Version.Item2; } if (baseVersionWithOldestSource.BaseVersionSource == null) throw new Exception("Base version should not be null"); var calculatedBase = new BaseVersion( - maxVersion.Version.Source, maxVersion.Version.ShouldIncrement, maxVersion.Version.SemanticVersion, - baseVersionWithOldestSource.BaseVersionSource, maxVersion.Version.BranchNameOverride); + maxVersion.Version.Item2.Source, maxVersion.Version.Item2.ShouldIncrement, maxVersion.Version.Item2.SemanticVersion, + baseVersionWithOldestSource.BaseVersionSource, maxVersion.Version.Item2.BranchNameOverride); Logger.WriteInfo(string.Format("Base version used: {0}", calculatedBase)); + // TODO Return the configuration used. return calculatedBase; } } diff --git a/src/GitVersionCore/VersionCalculation/BaseVersionCalculators/ConfigNextVersionBaseVersionStrategy.cs b/src/GitVersionCore/VersionCalculation/BaseVersionCalculators/ConfigNextVersionBaseVersionStrategy.cs index 8ab379a5fb..bf1ead6aa4 100644 --- a/src/GitVersionCore/VersionCalculation/BaseVersionCalculators/ConfigNextVersionBaseVersionStrategy.cs +++ b/src/GitVersionCore/VersionCalculation/BaseVersionCalculators/ConfigNextVersionBaseVersionStrategy.cs @@ -1,6 +1,7 @@ namespace GitVersion.VersionCalculation.BaseVersionCalculators { using System.Collections.Generic; + using System.Linq; /// /// Version is from NextVersion (the configuration value), unless the current commit is tagged. @@ -11,9 +12,10 @@ public class ConfigNextVersionBaseVersionStrategy : BaseVersionStrategy { public override IEnumerable GetVersions(GitVersionContext context) { - if (string.IsNullOrEmpty(context.Configuration.NextVersion) || context.IsCurrentCommitTagged) + var configToUse = context.Configurations.First(); + if (string.IsNullOrEmpty(configToUse.NextVersion) || context.IsCurrentCommitTagged) yield break; - var semanticVersion = SemanticVersion.Parse(context.Configuration.NextVersion, context.Configuration.GitTagPrefix); + var semanticVersion = SemanticVersion.Parse(configToUse.NextVersion, configToUse.GitTagPrefix); yield return new BaseVersion("NextVersion in GitVersion configuration file", false, semanticVersion, null, null); } } diff --git a/src/GitVersionCore/VersionCalculation/BaseVersionCalculators/MergeMessageBaseVersionStrategy.cs b/src/GitVersionCore/VersionCalculation/BaseVersionCalculators/MergeMessageBaseVersionStrategy.cs index 8703409b12..4f02b10bdf 100644 --- a/src/GitVersionCore/VersionCalculation/BaseVersionCalculators/MergeMessageBaseVersionStrategy.cs +++ b/src/GitVersionCore/VersionCalculation/BaseVersionCalculators/MergeMessageBaseVersionStrategy.cs @@ -15,32 +15,37 @@ public class MergeMessageBaseVersionStrategy : BaseVersionStrategy { public override IEnumerable GetVersions(GitVersionContext context) { - var commitsPriorToThan = context.CurrentBranch - .CommitsPriorToThan(context.CurrentCommit.When()); - var baseVersions = commitsPriorToThan - .SelectMany(c => - { - SemanticVersion semanticVersion; - if (TryParse(c, context.Configuration, out semanticVersion)) + foreach (var config in context.Configurations) + { + var baseVersions = config.CurrentBranchInfo.RelevantCommits.Skip(1) + .SelectMany(commit => { - var shouldIncrement = !context.Configuration.PreventIncrementForMergedBranchVersion; - return new[] + SemanticVersion semanticVersion; + if (TryParse(commit, config, out semanticVersion)) { - new BaseVersion(string.Format("Merge message '{0}'", c.Message.Trim()), shouldIncrement, semanticVersion, c, null) - }; - } - return Enumerable.Empty(); - }).ToList(); - return baseVersions; + var shouldIncrement = !config.PreventIncrementForMergedBranchVersion; + return new[] + { + new BaseVersion(string.Format("Merge message '{0}'", commit.Message.Trim()), shouldIncrement, semanticVersion, commit, null) + }; + } + return Enumerable.Empty(); + }).ToList(); + + foreach (var version in baseVersions) + { + yield return version; + } + } } static bool TryParse(Commit mergeCommit, EffectiveConfiguration configuration, out SemanticVersion semanticVersion) { - semanticVersion = Inner(mergeCommit, configuration); + semanticVersion = ExtractVersionFromMessage(mergeCommit, configuration); return semanticVersion != null; } - private static SemanticVersion Inner(Commit mergeCommit, EffectiveConfiguration configuration) + private static SemanticVersion ExtractVersionFromMessage(Commit mergeCommit, EffectiveConfiguration configuration) { if (mergeCommit.Parents.Count() < 2) { diff --git a/src/GitVersionCore/VersionCalculation/BaseVersionCalculators/TaggedCommitVersionStrategy.cs b/src/GitVersionCore/VersionCalculation/BaseVersionCalculators/TaggedCommitVersionStrategy.cs index 2f91955cd8..5e72469656 100644 --- a/src/GitVersionCore/VersionCalculation/BaseVersionCalculators/TaggedCommitVersionStrategy.cs +++ b/src/GitVersionCore/VersionCalculation/BaseVersionCalculators/TaggedCommitVersionStrategy.cs @@ -1,6 +1,5 @@ namespace GitVersion.VersionCalculation.BaseVersionCalculators { - using System; using System.Collections.Generic; using System.Linq; using LibGit2Sharp; @@ -14,32 +13,38 @@ public class TaggedCommitVersionStrategy : BaseVersionStrategy { public override IEnumerable GetVersions(GitVersionContext context) { - return GetTaggedVersions(context, context.CurrentBranch, context.CurrentCommit.When()); + return GetTaggedVersions(context); } - public IEnumerable GetTaggedVersions(GitVersionContext context, Branch currentBranch, DateTimeOffset? olderThan) + public IEnumerable GetTaggedVersions(GitVersionContext context) { - var allTags = context.Repository.Tags - .Where(tag => !olderThan.HasValue || ((Commit) tag.PeeledTarget()).When() <= olderThan.Value) - .ToList(); - var tagsOnBranch = currentBranch - .Commits - .SelectMany(commit => { return allTags.Where(t => IsValidTag(t, commit)); }) - .Select(t => - { - SemanticVersion version; - if (SemanticVersion.TryParse(t.FriendlyName, context.Configuration.GitTagPrefix, out version)) + foreach (var config in context.Configurations) + { + var olderThan = config.CurrentBranchInfo.FirstCommit.When(); + var allTagsForConfig = context.Repository.Tags + .Where(tag => ((Commit) tag.PeeledTarget()).When() <= olderThan) + .ToList(); + var tagsOnBranch = config.CurrentBranchInfo.RelevantCommits + .SelectMany(commit => allTagsForConfig.Where(tag => IsValidTag(tag, commit))) + .Select(tag => { - var commit = t.PeeledTarget() as Commit; - if (commit != null) - return new VersionTaggedCommit(commit, version, t.FriendlyName); - } - return null; - }) - .Where(a => a != null) - .ToList(); + SemanticVersion version; + if (SemanticVersion.TryParse(tag.FriendlyName, config.GitTagPrefix, out version)) + { + var commit = tag.PeeledTarget() as Commit; + if (commit != null) + return new VersionTaggedCommit(commit, version, tag.FriendlyName); + } + return null; + }) + .Where(commit => commit != null) + .ToList(); - return tagsOnBranch.Select(t => CreateBaseVersion(context, t)); + foreach (var version in tagsOnBranch.Select(t => CreateBaseVersion(context, t))) + { + yield return version; + } + } } BaseVersion CreateBaseVersion(GitVersionContext context, VersionTaggedCommit version) diff --git a/src/GitVersionCore/VersionCalculation/BaseVersionCalculators/VersionInBranchBaseVersionStrategy.cs b/src/GitVersionCore/VersionCalculation/BaseVersionCalculators/VersionInBranchBaseVersionStrategy.cs index 6244a73561..97de653867 100644 --- a/src/GitVersionCore/VersionCalculation/BaseVersionCalculators/VersionInBranchBaseVersionStrategy.cs +++ b/src/GitVersionCore/VersionCalculation/BaseVersionCalculators/VersionInBranchBaseVersionStrategy.cs @@ -2,7 +2,6 @@ { using System; using System.Collections.Generic; - using LibGit2Sharp; /// /// Version is extracted from the name of the branch. @@ -13,21 +12,22 @@ public class VersionInBranchBaseVersionStrategy : BaseVersionStrategy { public override IEnumerable GetVersions(GitVersionContext context) { - var currentBranch = context.CurrentBranch; - var tagPrefixRegex = context.Configuration.GitTagPrefix; - var repository = context.Repository; - return GetVersions(tagPrefixRegex, currentBranch, repository); + return GetBranchBaseVersions(context); } - public IEnumerable GetVersions(string tagPrefixRegex, Branch currentBranch, IRepository repository) + public IEnumerable GetBranchBaseVersions(GitVersionContext context) { - var branchName = currentBranch.FriendlyName; - var versionInBranch = GetVersionInBranch(branchName, tagPrefixRegex); - if (versionInBranch != null) + foreach (var config in context.Configurations) { - var commitBranchWasBranchedFrom = currentBranch.FindCommitBranchWasBranchedFrom(repository); - var branchNameOverride = branchName.RegexReplace("[-/]" + versionInBranch.Item1, string.Empty); - yield return new BaseVersion("Version in branch name", false, versionInBranch.Item2, commitBranchWasBranchedFrom.Commit, branchNameOverride); + var branchName = config.CurrentBranchInfo.Branch.FriendlyName; + var tagPrefixRegex = config.GitTagPrefix; + var versionInBranch = GetVersionInBranch(branchName, tagPrefixRegex); + if (versionInBranch != null) + { + var parentBranchCommit = config.CurrentBranchInfo.LastCommit; + var branchNameOverride = branchName.RegexReplace("[-/]" + versionInBranch.Item1, string.Empty); + yield return new BaseVersion("Version in branch name", false, versionInBranch.Item2, parentBranchCommit, branchNameOverride); + } } } diff --git a/src/GitVersionCore/VersionCalculation/DevelopVersionStrategy.cs b/src/GitVersionCore/VersionCalculation/DevelopVersionStrategy.cs index aac8be529d..4ba7021933 100644 --- a/src/GitVersionCore/VersionCalculation/DevelopVersionStrategy.cs +++ b/src/GitVersionCore/VersionCalculation/DevelopVersionStrategy.cs @@ -30,12 +30,9 @@ public class DevelopVersionStrategy : BaseVersionStrategy public override IEnumerable GetVersions(GitVersionContext context) { - if (context.Configuration.IsCurrentBranchDevelop) - { - return ReleaseBranchBaseVersions(context).Union(MasterTagsVersions(context)); - } - - return new BaseVersion[0]; + return context.Configurations + .Where(config => config.IsCurrentBranchDevelop) + .SelectMany(config => ReleaseBranchBaseVersions(context).Union(MasterTagsVersions(context))); } private IEnumerable MasterTagsVersions(GitVersionContext context) @@ -43,7 +40,7 @@ private IEnumerable MasterTagsVersions(GitVersionContext context) var master = context.Repository.FindBranch("master"); if (master != null) { - return taggedCommitVersionStrategy.GetTaggedVersions(context, master, null); + //return taggedCommitVersionStrategy.GetTaggedVersions(context, master, null); } return new BaseVersion[0]; @@ -79,20 +76,20 @@ private IEnumerable ReleaseBranchBaseVersions(GitVersionContext con IEnumerable GetReleaseVersion(GitVersionContext context, Branch releaseBranch) { - var tagPrefixRegex = context.Configuration.GitTagPrefix; - var repository = context.Repository; + //var tagPrefixRegex = context.Configurations.First().GitTagPrefix; + //var repository = context.Repository; - // Find the commit where the child branch was created. - var baseSource = releaseBranch.FindMergeBase(context.CurrentBranch, repository); - if (baseSource == context.CurrentCommit) + //// Find the commit where the child branch was created. + //var baseSource = releaseBranch.FindMergeBase(context.CurrentBranch, repository); + //if (baseSource == context.CurrentCommit) { // Ignore the branch if it has no commits. return new BaseVersion[0]; } - return releaseVersionStrategy - .GetVersions(tagPrefixRegex, releaseBranch, repository) - .Select(b => new BaseVersion(b.Source, true, b.SemanticVersion, baseSource, b.BranchNameOverride)); + //return releaseVersionStrategy + // .GetVersions(tagPrefixRegex, releaseBranch, repository) + // .Select(b => new BaseVersion(b.Source, true, b.SemanticVersion, baseSource, b.BranchNameOverride)); } } } \ No newline at end of file diff --git a/src/GitVersionCore/VersionCalculation/NextVersionCalculator.cs b/src/GitVersionCore/VersionCalculation/NextVersionCalculator.cs index f60d72c5f4..84114eb306 100644 --- a/src/GitVersionCore/VersionCalculation/NextVersionCalculator.cs +++ b/src/GitVersionCore/VersionCalculation/NextVersionCalculator.cs @@ -28,6 +28,7 @@ public NextVersionCalculator(IBaseVersionCalculator baseVersionCalculator = null public SemanticVersion FindVersion(GitVersionContext context) { SemanticVersion taggedSemanticVersion = null; + // If current commit is tagged, don't do anything except add build metadata if (context.IsCurrentCommitTagged) { @@ -44,15 +45,17 @@ public SemanticVersion FindVersion(GitVersionContext context) var baseVersion = baseVersionFinder.GetBaseVersion(context); SemanticVersion semver; - if (context.Configuration.VersioningMode == VersioningMode.Mainline) + if (context.Configurations.First().VersioningMode == VersioningMode.Mainline) + { semver = FindMainlineModeVersion(baseVersion, context); + } else { semver = PerformIncrement(context, baseVersion); semver.BuildMetaData = metaDataCalculator.Create(baseVersion.BaseVersionSource, context); } - if (!semver.PreReleaseTag.HasTag() && !string.IsNullOrEmpty(context.Configuration.Tag)) + if (!semver.PreReleaseTag.HasTag() && !string.IsNullOrEmpty(context.Configurations.First().Tag)) { UpdatePreReleaseTag(context, semver, baseVersion.BranchNameOverride); } @@ -94,7 +97,7 @@ SemanticVersion FindMainlineModeVersion(BaseVersion baseVersion, GitVersionConte // * feature/foo // / | // master * * - // + // var commitLog = context.Repository.Commits.QueryBy(new CommitFilter { IncludeReachableFrom = context.CurrentBranch, @@ -218,7 +221,7 @@ private static SemanticVersion IncrementForEachCommit(GitVersionContext context, { foreach (var directCommit in directCommits) { - var directCommitIncrement = IncrementStrategyFinder.GetIncrementForCommits(context, new[] + var directCommitIncrement = IncrementStrategyFinder.GetIncrementForCommits(context.Configurations.First(), new[] { directCommit }) ?? VersionField.Patch; @@ -241,7 +244,7 @@ private static VersionField FindMessageIncrement( context.Repository.Commits.QueryBy(filter).ToList() : new[] { mergeCommit }.Union(context.Repository.Commits.QueryBy(filter)).ToList(); commitLog.RemoveAll(c => commits.Any(c1 => c1.Sha == c.Sha)); - return IncrementStrategyFinder.GetIncrementForCommits(context, commits) ?? VersionField.Patch; + return IncrementStrategyFinder.GetIncrementForCommits(context.Configurations.First(), commits) ?? VersionField.Patch; } private Commit GetMergedHead(Commit mergeCommit) @@ -254,12 +257,12 @@ private Commit GetMergedHead(Commit mergeCommit) void UpdatePreReleaseTag(GitVersionContext context, SemanticVersion semanticVersion, string branchNameOverride) { - var tagToUse = GetBranchSpecificTag(context.Configuration, context.CurrentBranch.FriendlyName, branchNameOverride); + var tagToUse = GetBranchSpecificTag(context.Configurations.First(), context.CurrentBranch.FriendlyName, branchNameOverride); int? number = null; var lastTag = context.CurrentBranch - .GetVersionTagsOnBranch(context.Repository, context.Configuration.GitTagPrefix) + .GetVersionTagsOnBranch(context.Repository, context.Configurations.First().GitTagPrefix) .FirstOrDefault(v => v.PreReleaseTag.Name == tagToUse); if (lastTag != null && diff --git a/src/GitVersionCore/VersioningModes/ContinuousDeliveryMode.cs b/src/GitVersionCore/VersioningModes/ContinuousDeliveryMode.cs index cf3cda1ee3..20e61aaf0c 100644 --- a/src/GitVersionCore/VersioningModes/ContinuousDeliveryMode.cs +++ b/src/GitVersionCore/VersioningModes/ContinuousDeliveryMode.cs @@ -8,7 +8,7 @@ public class ContinuousDeliveryMode : VersioningModeBase { public override SemanticVersionPreReleaseTag GetPreReleaseTag(GitVersionContext context, List possibleCommits, int numberOfCommits) { - return RetrieveMostRecentOptionalTagVersion(context, possibleCommits) ?? context.Configuration.Tag + ".1"; + return RetrieveMostRecentOptionalTagVersion(context, possibleCommits) ?? context.Configurations.First().Tag + ".1"; } static SemanticVersionPreReleaseTag RetrieveMostRecentOptionalTagVersion(GitVersionContext context, List applicableTagsInDescendingOrder) @@ -16,7 +16,7 @@ static SemanticVersionPreReleaseTag RetrieveMostRecentOptionalTagVersion(GitVers if (applicableTagsInDescendingOrder.Any()) { var taggedCommit = applicableTagsInDescendingOrder.First().PeeledTarget(); - var preReleaseVersion = applicableTagsInDescendingOrder.Select(tag => SemanticVersion.Parse(tag.FriendlyName, context.Configuration.GitTagPrefix)).FirstOrDefault(); + var preReleaseVersion = applicableTagsInDescendingOrder.Select(tag => SemanticVersion.Parse(tag.FriendlyName, context.Configurations.First().GitTagPrefix)).FirstOrDefault(); if (preReleaseVersion != null) { if (taggedCommit != context.CurrentCommit) diff --git a/src/GitVersionCore/VersioningModes/ContinuousDeploymentMode.cs b/src/GitVersionCore/VersioningModes/ContinuousDeploymentMode.cs index 9b7c038d7d..bf94b544b5 100644 --- a/src/GitVersionCore/VersioningModes/ContinuousDeploymentMode.cs +++ b/src/GitVersionCore/VersioningModes/ContinuousDeploymentMode.cs @@ -1,14 +1,14 @@ namespace GitVersion.VersioningModes { using System.Collections.Generic; - + using System.Linq; using LibGit2Sharp; public class ContinuousDeploymentMode : VersioningModeBase { public override SemanticVersionPreReleaseTag GetPreReleaseTag(GitVersionContext context, List possibleTags, int numberOfCommits) { - return context.Configuration.Tag + "." + numberOfCommits; + return context.Configurations.First().Tag + "." + numberOfCommits; } } } \ No newline at end of file diff --git a/src/GitVersionExe.Tests/AssemblyInfoFileUpdateTests.cs b/src/GitVersionExe.Tests/AssemblyInfoFileUpdateTests.cs index 2339e79664..5f25190235 100644 --- a/src/GitVersionExe.Tests/AssemblyInfoFileUpdateTests.cs +++ b/src/GitVersionExe.Tests/AssemblyInfoFileUpdateTests.cs @@ -348,8 +348,8 @@ public void ShouldReplaceAssemblyVersionWithAtttributeSuffix(string fileExtensio !s.Contains(@"AssemblyVersionAttribute(""1.0.0.0"")") && !s.Contains(@"AssemblyInformationalVersionAttribute(""1.0.0.0"")") && !s.Contains(@"AssemblyFileVersionAttribute(""1.0.0.0"")") && - s.Contains(@"AssemblyVersion(""2.3.1.0"")") && - s.Contains(@"AssemblyInformationalVersion(""2.3.1+3.Branch.foo.Sha.hash"")") && + s.Contains(@"AssemblyVersion(""2.3.1.0"")") && + s.Contains(@"AssemblyInformationalVersion(""2.3.1+3.Branch.foo.Sha.hash"")") && s.Contains(@"AssemblyFileVersion(""2.3.1.0"")"))); } });