From 1fe37c3a4a3d06e6b7e6e8d2ffcd0e4cfad8c1a2 Mon Sep 17 00:00:00 2001 From: Daniel Rose Date: Tue, 16 Aug 2016 10:43:55 +0200 Subject: [PATCH 1/9] Add various tests for inheriting version numbers in feature branches. --- .../FeatureBranchScenarios.cs | 235 ++++++++++++++++++ 1 file changed, 235 insertions(+) diff --git a/src/GitVersionCore.Tests/IntegrationTests/FeatureBranchScenarios.cs b/src/GitVersionCore.Tests/IntegrationTests/FeatureBranchScenarios.cs index 02125d0be4..9186a5bb6b 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; @@ -239,6 +240,240 @@ public void BranchCreatedAfterFinishReleaseShouldInheritAndIncrementFromLastMast } } + [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, + Regex = "master" + } + } + } + }; + + 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, + Regex = "master" + } + } + } + }; + + 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 + { + [Test] + public void ShouldPickUpVersionFromMasterAfterReleaseBranchCreated() + { + 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 misnamed feature branch (i.e. it uses the default config) from develop and verify the version + fixture.BranchTo("misnamed"); + fixture.AssertFullSemver("1.1.0-misnamed.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 misnamed feature branch (i.e. it uses the default config) from develop and verify the version + fixture.BranchTo("misnamed"); + fixture.AssertFullSemver("1.1.0-misnamed.1+2"); + } + } + + // ReSharper disable once MemberHidesStaticFromOuterClass + public class WhenMasterMarkedAsIsDevelop + { + [Test] + public void ShouldPickUpVersionFromMasterAfterReleaseBranchCreated() + { + var config = new Config + { + Branches = new Dictionary + { + { + "master", new BranchConfig() + { + IsDevelop = true, + Regex = "master" + } + } + } + }; + + 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 (i.e. it uses the default config) from master and verify the version + fixture.BranchTo("misnamed"); + fixture.AssertFullSemver(config, "1.0.1-misnamed.1+1"); + } + } + + [Test] + public void ShouldPickUpVersionFromMasterAfterReleaseBranchMergedBack() + { + var config = new Config + { + Branches = new Dictionary + { + { + "master", new BranchConfig() + { + IsDevelop = true, + Regex = "master" + } + } + } + }; + + 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 (i.e. it uses the default config) from master and verify the version + fixture.BranchTo("misnamed"); + fixture.AssertFullSemver(config, "1.0.1-misnamed.1+2"); + } + } + } + } + [Test] public void PickUpVersionFromMasterMarkedWithIsTracksReleaseBranches() { From b8c34c3c0389b0e71f6de29703c2f60ac4bbc0f7 Mon Sep 17 00:00:00 2001 From: Daniel Rose Date: Fri, 30 Sep 2016 15:00:03 +0200 Subject: [PATCH 2/9] Add comments. --- .../Configuration/BranchConfig.cs | 5 ++++- .../Configuration/IncrementStrategy.cs | 3 ++- src/GitVersionCore/IncrementStrategyFinder.cs | 4 ++-- 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 +++++ 11 files changed, 71 insertions(+), 10 deletions(-) diff --git a/src/GitVersionCore/Configuration/BranchConfig.cs b/src/GitVersionCore/Configuration/BranchConfig.cs index c0d5bd35ce..f33b6f2fa6 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; @@ -19,6 +21,7 @@ public BranchConfig(BranchConfig branchConfiguration) TrackMergeTarget = branchConfiguration.TrackMergeTarget; CommitMessageIncrementing = branchConfiguration.CommitMessageIncrementing; TracksReleaseBranches = branchConfiguration.TracksReleaseBranches; + Regex = branchConfiguration.Regex; IsReleaseBranch = branchConfiguration.IsReleaseBranch; IsMainline = branchConfiguration.IsMainline; } diff --git a/src/GitVersionCore/Configuration/IncrementStrategy.cs b/src/GitVersionCore/Configuration/IncrementStrategy.cs index 17a420899c..2d4e677a89 100644 --- a/src/GitVersionCore/Configuration/IncrementStrategy.cs +++ b/src/GitVersionCore/Configuration/IncrementStrategy.cs @@ -9,7 +9,8 @@ public enum IncrementStrategy Minor, Patch, /// - /// Uses the increment strategy from the branch the current branch was branched from + /// Uses the , and + /// of the "parent" branch (i.e. the branch where the current branch was branched from). /// Inherit } diff --git a/src/GitVersionCore/IncrementStrategyFinder.cs b/src/GitVersionCore/IncrementStrategyFinder.cs index 73723862a3..e40f9976e6 100644 --- a/src/GitVersionCore/IncrementStrategyFinder.cs +++ b/src/GitVersionCore/IncrementStrategyFinder.cs @@ -38,7 +38,7 @@ public static class IncrementStrategyFinder commitMessageIncrement = VersionField.Minor; } - // don't increment for less than the branch config increment, if the absense of commit messages would have + // don't increment for less than the branch config increment, if the absence of commit messages would have // still resulted in an increment of configuration.Increment if (baseVersion.ShouldIncrement && commitMessageIncrement < defaultIncrement) { @@ -54,7 +54,7 @@ public static class IncrementStrategyFinder { return null; } - + var commits = GetIntermediateCommits(context.Repository, baseVersion.BaseVersionSource, context.CurrentCommit); if (context.Configuration.CommitMessageIncrementing == CommitMessageIncrementMode.MergeMessageOnly) 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 d3332dfa65..d69cf450c4 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 458cdd94de..27a53b3191 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 480cd9c308..4955be0203 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 09afaef1a9..deb4434956 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 77bd3fd3aa..39bd62b31a 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 TrackReleaseBranchesVersionStrategy : BaseVersionStrategy { @@ -70,9 +83,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(context, tagPrefixRegex, releaseBranch, repository) diff --git a/src/GitVersionCore/VersionCalculation/FallbackBaseVersionStrategy.cs b/src/GitVersionCore/VersionCalculation/FallbackBaseVersionStrategy.cs index 1ee6fa2299..85a2c966f1 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 cb77f97698057f696ee8be06bb4aff707f5bcd46 Mon Sep 17 00:00:00 2001 From: Daniel Rose Date: Tue, 4 Oct 2016 11:33:29 +0200 Subject: [PATCH 3/9] Put the name of the branch configuration in BranchConfig. --- .../FeatureBranchScenarios.cs | 9 ++- .../BranchConfigurationCalculator.cs | 67 +++++++++---------- .../Configuration/BranchConfig.cs | 7 ++ src/GitVersionCore/Configuration/Config.cs | 2 +- .../Configuration/ConfigurationProvider.cs | 2 +- .../Configuration/IncrementStrategy.cs | 2 +- .../Init/SetConfig/ConfigureBranches.cs | 2 +- src/GitVersionCore/GitVersionContext.cs | 44 ++++++------ 8 files changed, 70 insertions(+), 65 deletions(-) diff --git a/src/GitVersionCore.Tests/IntegrationTests/FeatureBranchScenarios.cs b/src/GitVersionCore.Tests/IntegrationTests/FeatureBranchScenarios.cs index 9186a5bb6b..5e65ab2c53 100644 --- a/src/GitVersionCore.Tests/IntegrationTests/FeatureBranchScenarios.cs +++ b/src/GitVersionCore.Tests/IntegrationTests/FeatureBranchScenarios.cs @@ -4,7 +4,6 @@ using GitVersionCore.Tests; using LibGit2Sharp; using NUnit.Framework; -using System.Collections.Generic; [TestFixture] public class FeatureBranchScenarios @@ -296,7 +295,7 @@ public void ShouldPickUpVersionFromMasterAfterReleaseBranchCreated() { "master", new BranchConfig() { - IsDevelop = true, + TracksReleaseBranches = true, Regex = "master" } } @@ -329,7 +328,7 @@ public void ShouldPickUpVersionFromMasterAfterReleaseBranchMergedBack() { "master", new BranchConfig() { - IsDevelop = true, + TracksReleaseBranches = true, Regex = "master" } } @@ -414,7 +413,7 @@ public void ShouldPickUpVersionFromMasterAfterReleaseBranchCreated() { "master", new BranchConfig() { - IsDevelop = true, + TracksReleaseBranches = true, Regex = "master" } } @@ -447,7 +446,7 @@ public void ShouldPickUpVersionFromMasterAfterReleaseBranchMergedBack() { "master", new BranchConfig() { - IsDevelop = true, + TracksReleaseBranches = true, Regex = "master" } } diff --git a/src/GitVersionCore/BranchConfigurationCalculator.cs b/src/GitVersionCore/BranchConfigurationCalculator.cs index 4ff1d2cbfc..4650875626 100644 --- a/src/GitVersionCore/BranchConfigurationCalculator.cs +++ b/src/GitVersionCore/BranchConfigurationCalculator.cs @@ -9,9 +9,12 @@ namespace GitVersion public class BranchConfigurationCalculator { - public static KeyValuePair GetBranchConfiguration(Commit currentCommit, IRepository repository, bool onlyEvaluateTrackedBranches, Config config, Branch currentBranch, IList excludedInheritBranches = null) + /// + /// Gets the for the current commit. + /// + public static BranchConfig GetBranchConfiguration(Commit currentCommit, IRepository repository, bool onlyEvaluateTrackedBranches, Config config, Branch currentBranch, IList excludedInheritBranches = null) { - var matchingBranches = LookupBranchConfiguration(config, currentBranch); + var matchingBranches = LookupBranchConfiguration(config, currentBranch).ToArray(); if (matchingBranches.Length == 0) { @@ -19,28 +22,28 @@ 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) { - return InheritBranchConfiguration(onlyEvaluateTrackedBranches, repository, currentCommit, currentBranch, keyValuePair, branchConfiguration, config, excludedInheritBranches); + return InheritBranchConfiguration(onlyEvaluateTrackedBranches, repository, currentCommit, currentBranch, branchConfiguration, config, excludedInheritBranches); } - 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) { @@ -52,11 +55,11 @@ 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); } - static KeyValuePair InheritBranchConfiguration(bool onlyEvaluateTrackedBranches, IRepository repository, Commit currentCommit, Branch currentBranch, KeyValuePair keyValuePair, BranchConfig branchConfiguration, Config config, IList excludedInheritBranches) + static BranchConfig InheritBranchConfiguration(bool onlyEvaluateTrackedBranches, IRepository repository, Commit currentCommit, Branch currentBranch, BranchConfig branchConfiguration, Config config, IList excludedInheritBranches) { using (Logger.IndentLog("Attempting to inherit branch configuration from parent branch")) { @@ -72,11 +75,11 @@ static KeyValuePair InheritBranchConfiguration(bool onlyEv { excludedInheritBranches = repository.Branches.Where(b => { - var branchConfig = LookupBranchConfiguration(config, b); + var branchConfig = LookupBranchConfiguration(config, b).ToArray(); // 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); + return (branchConfig.Length != 1) || (branchConfig.Length == 1 && branchConfig[0].Increment == IncrementStrategy.Inherit); }).ToList(); } excludedBranches.ToList().ForEach(excludedInheritBranches.Add); @@ -110,16 +113,14 @@ static KeyValuePair InheritBranchConfiguration(bool onlyEv 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 - TracksReleaseBranches = branchConfig.TracksReleaseBranches - }); + var branchConfig = GetBranchConfiguration(currentCommit, repository, onlyEvaluateTrackedBranches, config, possibleParents[0], excludedInheritBranches); + return new BranchConfig(branchConfiguration) + { + Increment = branchConfig.Increment, + PreventIncrementOfMergedBranchVersion = branchConfig.PreventIncrementOfMergedBranchVersion, + // If we are inheriting from develop then we should behave like develop + TracksReleaseBranches = branchConfig.TracksReleaseBranches + }; } // 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 @@ -142,16 +143,14 @@ 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 - TracksReleaseBranches = inheritingBranchConfig.TracksReleaseBranches - }); + var inheritingBranchConfig = GetBranchConfiguration(currentCommit, repository, onlyEvaluateTrackedBranches, config, chosenBranch); + return new BranchConfig(branchConfiguration) + { + Increment = inheritingBranchConfig.Increment, + PreventIncrementOfMergedBranchVersion = inheritingBranchConfig.PreventIncrementOfMergedBranchVersion, + // If we are inheriting from develop then we should behave like develop + TracksReleaseBranches = inheritingBranchConfig.TracksReleaseBranches + }; } } diff --git a/src/GitVersionCore/Configuration/BranchConfig.cs b/src/GitVersionCore/Configuration/BranchConfig.cs index f33b6f2fa6..662f29b971 100644 --- a/src/GitVersionCore/Configuration/BranchConfig.cs +++ b/src/GitVersionCore/Configuration/BranchConfig.cs @@ -24,6 +24,7 @@ public BranchConfig(BranchConfig branchConfiguration) Regex = branchConfiguration.Regex; 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 c5dd6dcf37..34826f6425 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/Configuration/ConfigurationProvider.cs b/src/GitVersionCore/Configuration/ConfigurationProvider.cs index f08ccd90be..0b53827603 100644 --- a/src/GitVersionCore/Configuration/ConfigurationProvider.cs +++ b/src/GitVersionCore/Configuration/ConfigurationProvider.cs @@ -147,7 +147,7 @@ static BranchConfig GetOrCreateBranchDefaults(Config config, string branchKey) { if (!config.Branches.ContainsKey(branchKey)) { - var branchConfig = new BranchConfig(); + var branchConfig = new BranchConfig {Name = branchKey}; config.Branches.Add(branchKey, branchConfig); return branchConfig; } diff --git a/src/GitVersionCore/Configuration/IncrementStrategy.cs b/src/GitVersionCore/Configuration/IncrementStrategy.cs index 2d4e677a89..695002fd1a 100644 --- a/src/GitVersionCore/Configuration/IncrementStrategy.cs +++ b/src/GitVersionCore/Configuration/IncrementStrategy.cs @@ -9,7 +9,7 @@ public enum IncrementStrategy Minor, Patch, /// - /// Uses the , and + /// Uses the , and /// of the "parent" branch (i.e. the branch where the current branch was branched from). /// Inherit diff --git a/src/GitVersionCore/Configuration/Init/SetConfig/ConfigureBranches.cs b/src/GitVersionCore/Configuration/Init/SetConfig/ConfigureBranches.cs index 57ad92ac88..5a7061299d 100644 --- a/src/GitVersionCore/Configuration/Init/SetConfig/ConfigureBranches.cs +++ b/src/GitVersionCore/Configuration/Init/SetConfig/ConfigureBranches.cs @@ -29,7 +29,7 @@ protected override StepResult HandleResult(string result, Queue Date: Tue, 4 Oct 2016 14:50:42 +0200 Subject: [PATCH 4/9] Use new struct BranchCommit to lose less information. Use ExcludingBranches extension method. --- src/GitVersionCore/BranchCommit.cs | 51 +++++++++++++++++++ .../BranchConfigurationCalculator.cs | 4 +- src/GitVersionCore/GitVersionCore.csproj | 1 + src/GitVersionCore/LibGitExtensions.cs | 51 +++++++++++-------- .../VersionInBranchBaseVersionStrategy.cs | 2 +- 5 files changed, 84 insertions(+), 25 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 4650875626..ff98caaf86 100644 --- a/src/GitVersionCore/BranchConfigurationCalculator.cs +++ b/src/GitVersionCore/BranchConfigurationCalculator.cs @@ -87,7 +87,7 @@ static BranchConfig InheritBranchConfiguration(bool onlyEvaluateTrackedBranches, var branchPoint = currentBranch.FindCommitBranchWasBranchedFrom(repository, excludedInheritBranches.ToArray()); List possibleParents; - if (branchPoint == null) + if (branchPoint == BranchCommit.Empty) { possibleParents = currentCommit.GetBranchesContainingCommit(repository, branchesToEvaluate, true) // It fails to inherit Increment branch configuration if more than 1 parent; @@ -97,7 +97,7 @@ static BranchConfig InheritBranchConfiguration(bool onlyEvaluateTrackedBranches, } else { - var branches = branchPoint.GetBranchesContainingCommit(repository, branchesToEvaluate, true).ToList(); + var branches = branchPoint.Commit.GetBranchesContainingCommit(repository, branchesToEvaluate, true).ToList(); if (branches.Count > 1) { var currentTipBranches = currentCommit.GetBranchesContainingCommit(repository, branchesToEvaluate, true).ToList(); diff --git a/src/GitVersionCore/GitVersionCore.csproj b/src/GitVersionCore/GitVersionCore.csproj index a25b595fad..174198e149 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 9179e7ee0b..3fc994da90 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 } } - 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 ? + branch.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 deb4434956..84129fcc0d 100644 --- a/src/GitVersionCore/VersionCalculation/BaseVersionCalculators/VersionInBranchBaseVersionStrategy.cs +++ b/src/GitVersionCore/VersionCalculation/BaseVersionCalculators/VersionInBranchBaseVersionStrategy.cs @@ -27,7 +27,7 @@ public IEnumerable GetVersions(GitVersionContext context, string ta { var commitBranchWasBranchedFrom = currentBranch.FindCommitBranchWasBranchedFrom(repository); var branchNameOverride = branchName.RegexReplace("[-/]" + versionInBranch.Item1, string.Empty); - yield return new BaseVersion(context, "Version in branch name", false, versionInBranch.Item2, commitBranchWasBranchedFrom, branchNameOverride); + yield return new BaseVersion(context, "Version in branch name", false, versionInBranch.Item2, commitBranchWasBranchedFrom.Commit, branchNameOverride); } } From d2f4d347475c8da29bde940cc33387a68a9450f9 Mon Sep 17 00:00:00 2001 From: Daniel Rose Date: Thu, 17 Nov 2016 15:51:19 +0100 Subject: [PATCH 5/9] Use Inherit strategy by default. --- .../GitVersionContextTests.cs | 28 ++++++++++++ .../BranchConfigurationCalculator.cs | 34 +++++++------- src/GitVersionCore/Configuration/Config.cs | 3 ++ .../Configuration/ConfigurationProvider.cs | 44 ++++++++++++++----- 4 files changed, 80 insertions(+), 29 deletions(-) diff --git a/src/GitVersionCore.Tests/GitVersionContextTests.cs b/src/GitVersionCore.Tests/GitVersionContextTests.cs index 396a7ea95a..d91910af75 100644 --- a/src/GitVersionCore.Tests/GitVersionContextTests.cs +++ b/src/GitVersionCore.Tests/GitVersionContextTests.cs @@ -31,6 +31,34 @@ public void CanInheritVersioningMode(VersioningMode mode) context.Configuration.VersioningMode.ShouldBe(mode); } + [TestCase(IncrementStrategy.Inherit, IncrementStrategy.Patch)] // Since it inherits, the increment strategy of master is used => Patch + [TestCase(IncrementStrategy.Patch, null)] + [TestCase(IncrementStrategy.Major, null)] + [TestCase(IncrementStrategy.Minor, null)] + [TestCase(IncrementStrategy.None, null)] + public void CanInheritIncrement(IncrementStrategy increment, IncrementStrategy? alternateExpected) + { + // Dummy branch name to make sure that no default config exists. + const string dummyBranchName = "dummy"; + + var config = new Config + { + Increment = increment + }; + ConfigurationProvider.ApplyDefaultsTo(config); + + using (var fixture = new EmptyRepositoryFixture()) + { + fixture.MakeACommit(); + fixture.BranchTo(dummyBranchName); + fixture.MakeACommit(); + + var context = new GitVersionContext(fixture.Repository, fixture.Repository.Branches[dummyBranchName], config); + context.Configuration.Increment.ShouldBe(alternateExpected ?? increment); + } + + } + [Test] public void UsesBranchSpecificConfigOverTopLevelDefaults() { diff --git a/src/GitVersionCore/BranchConfigurationCalculator.cs b/src/GitVersionCore/BranchConfigurationCalculator.cs index ff98caaf86..5409bebd8f 100644 --- a/src/GitVersionCore/BranchConfigurationCalculator.cs +++ b/src/GitVersionCore/BranchConfigurationCalculator.cs @@ -16,31 +16,30 @@ public static BranchConfig GetBranchConfiguration(Commit currentCommit, IReposit { var matchingBranches = LookupBranchConfiguration(config, currentBranch).ToArray(); - if (matchingBranches.Length == 0) + if (matchingBranches.Length > 1) { - Logger.WriteInfo(string.Format( - "No branch configuration found for branch {0}, falling back to default configuration", - currentBranch.FriendlyName)); - - var branchConfig = new BranchConfig { Name = string.Empty }; - ConfigurationProvider.ApplyBranchDefaults(config, branchConfig, ""); - return branchConfig; + 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.Name)))); } + BranchConfig branchConfiguration; if (matchingBranches.Length == 1) { - var branchConfiguration = matchingBranches[0]; - - if (branchConfiguration.Increment == IncrementStrategy.Inherit) - { - return InheritBranchConfiguration(onlyEvaluateTrackedBranches, repository, currentCommit, currentBranch, branchConfiguration, config, excludedInheritBranches); - } + branchConfiguration = matchingBranches[0]; + } + else + { + Logger.WriteInfo(string.Format( + "No branch configuration found for branch {0}, falling back to default configuration", + currentBranch.FriendlyName)); - return branchConfiguration; + branchConfiguration = new BranchConfig { Name = string.Empty }; + ConfigurationProvider.ApplyBranchDefaults(config, 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.Name)))); + return branchConfiguration.Increment == IncrementStrategy.Inherit ? + InheritBranchConfiguration(onlyEvaluateTrackedBranches, repository, currentCommit, currentBranch, branchConfiguration, config, excludedInheritBranches) : + branchConfiguration; } static IEnumerable LookupBranchConfiguration([NotNull] Config config, [NotNull] Branch currentBranch) @@ -58,7 +57,6 @@ static IEnumerable LookupBranchConfiguration([NotNull] Config conf return config.Branches.Where(b => Regex.IsMatch(currentBranch.FriendlyName, "^" + b.Value.Regex, RegexOptions.IgnoreCase)).Select(kvp => kvp.Value); } - static BranchConfig InheritBranchConfiguration(bool onlyEvaluateTrackedBranches, IRepository repository, Commit currentCommit, Branch currentBranch, BranchConfig branchConfiguration, Config config, IList excludedInheritBranches) { using (Logger.IndentLog("Attempting to inherit branch configuration from parent branch")) diff --git a/src/GitVersionCore/Configuration/Config.cs b/src/GitVersionCore/Configuration/Config.cs index 34826f6425..a0dd35c832 100644 --- a/src/GitVersionCore/Configuration/Config.cs +++ b/src/GitVersionCore/Configuration/Config.cs @@ -99,5 +99,8 @@ T MergeObjects(T target, T source) [YamlMember(Alias = "ignore")] public IgnoreConfig Ignore { get; set; } + + [YamlMember(Alias = "increment")] + public IncrementStrategy? Increment { get; set; } } } \ No newline at end of file diff --git a/src/GitVersionCore/Configuration/ConfigurationProvider.cs b/src/GitVersionCore/Configuration/ConfigurationProvider.cs index 0b53827603..4801c7d879 100644 --- a/src/GitVersionCore/Configuration/ConfigurationProvider.cs +++ b/src/GitVersionCore/Configuration/ConfigurationProvider.cs @@ -30,6 +30,8 @@ public class ConfigurationProvider public const string SupportBranchKey = "support"; public const string DevelopBranchKey = "develop"; + private const IncrementStrategy DefaultIncrementStrategy = IncrementStrategy.Inherit; + public static Config Provide(GitPreparer gitPreparer, IFileSystem fileSystem, bool applyDefaults = true, Config overrideConfig = null) { var workingDirectory = gitPreparer.WorkingDirectory; @@ -99,24 +101,44 @@ public static void ApplyDefaultsTo(Config config) var configBranches = config.Branches.ToList(); - ApplyBranchDefaults(config, GetOrCreateBranchDefaults(config, MasterBranchKey), + ApplyBranchDefaults(config, + GetOrCreateBranchDefaults(config, MasterBranchKey), MasterBranchRegex, defaultTag: string.Empty, defaultPreventIncrement: true, + defaultIncrementStrategy: IncrementStrategy.Patch, isMainline: true); - ApplyBranchDefaults(config, GetOrCreateBranchDefaults(config, ReleaseBranchKey), ReleaseBranchRegex, defaultTag: "beta", defaultPreventIncrement: true, isReleaseBranch: true); - ApplyBranchDefaults(config, GetOrCreateBranchDefaults(config, FeatureBranchKey), FeatureBranchRegex, defaultIncrementStrategy: IncrementStrategy.Inherit); - ApplyBranchDefaults(config, GetOrCreateBranchDefaults(config, PullRequestBranchKey), PullRequestRegex, + ApplyBranchDefaults(config, + GetOrCreateBranchDefaults(config, ReleaseBranchKey), + ReleaseBranchRegex, + defaultTag: "beta", + defaultPreventIncrement: true, + defaultIncrementStrategy: IncrementStrategy.Patch, + isReleaseBranch: true); + ApplyBranchDefaults(config, + GetOrCreateBranchDefaults(config, FeatureBranchKey), + FeatureBranchRegex, + defaultIncrementStrategy: IncrementStrategy.Inherit); + ApplyBranchDefaults(config, + GetOrCreateBranchDefaults(config, PullRequestBranchKey), + PullRequestRegex, defaultTag: "PullRequest", defaultTagNumberPattern: @"[/-](?\d+)[-/]", defaultIncrementStrategy: IncrementStrategy.Inherit); - ApplyBranchDefaults(config, GetOrCreateBranchDefaults(config, HotfixBranchKey), HotfixBranchRegex, defaultTag: "beta"); - ApplyBranchDefaults(config, GetOrCreateBranchDefaults(config, SupportBranchKey), + ApplyBranchDefaults(config, + GetOrCreateBranchDefaults(config, HotfixBranchKey), + HotfixBranchRegex, + defaultTag: "beta", + defaultIncrementStrategy: IncrementStrategy.Patch); + ApplyBranchDefaults(config, + GetOrCreateBranchDefaults(config, SupportBranchKey), SupportBranchRegex, defaultTag: string.Empty, defaultPreventIncrement: true, + defaultIncrementStrategy: IncrementStrategy.Patch, isMainline: true); - ApplyBranchDefaults(config, GetOrCreateBranchDefaults(config, DevelopBranchKey), + ApplyBranchDefaults(config, + GetOrCreateBranchDefaults(config, DevelopBranchKey), DevelopBranchRegex, defaultTag: "alpha", defaultIncrementStrategy: IncrementStrategy.Minor, @@ -124,8 +146,8 @@ public static void ApplyDefaultsTo(Config config) defaultTrackMergeTarget: true, tracksReleaseBranches: true); - // Any user defined branches should have other values defaulted after known branches filled in - // This allows users to override one value of + // Any user defined branches should have other values defaulted after known branches filled in. + // This allows users to override any of the value. foreach (var branchConfig in configBranches) { var regex = branchConfig.Value.Regex; @@ -159,7 +181,7 @@ public static void ApplyBranchDefaults(Config config, BranchConfig branchConfig, string branchRegex, string defaultTag = "useBranchName", - IncrementStrategy defaultIncrementStrategy = IncrementStrategy.Patch, + IncrementStrategy? defaultIncrementStrategy = null, // Looked up from main config bool defaultPreventIncrement = false, VersioningMode? defaultVersioningMode = null, // Looked up from main config bool defaultTrackMergeTarget = false, @@ -171,7 +193,7 @@ public static void ApplyBranchDefaults(Config config, branchConfig.Regex = string.IsNullOrEmpty(branchConfig.Regex) ? branchRegex : branchConfig.Regex; branchConfig.Tag = branchConfig.Tag ?? defaultTag; branchConfig.TagNumberPattern = branchConfig.TagNumberPattern ?? defaultTagNumberPattern; - branchConfig.Increment = branchConfig.Increment ?? defaultIncrementStrategy; + branchConfig.Increment = branchConfig.Increment ?? defaultIncrementStrategy ?? config.Increment ?? DefaultIncrementStrategy; branchConfig.PreventIncrementOfMergedBranchVersion = branchConfig.PreventIncrementOfMergedBranchVersion ?? defaultPreventIncrement; branchConfig.TrackMergeTarget = branchConfig.TrackMergeTarget ?? defaultTrackMergeTarget; branchConfig.VersioningMode = branchConfig.VersioningMode ?? defaultVersioningMode ?? config.VersioningMode; From 5a2fb17174f239b123d62c5cae86aba072e388cd Mon Sep 17 00:00:00 2001 From: Daniel Rose Date: Thu, 17 Nov 2016 15:52:49 +0100 Subject: [PATCH 6/9] Fix unit tests. The GitVersionContextBuilder does not create an actual repository, causing exceptions. --- .../NextVersionCalculatorTests.cs | 74 +++++++++++-------- 1 file changed, 44 insertions(+), 30 deletions(-) diff --git a/src/GitVersionCore.Tests/VersionCalculation/NextVersionCalculatorTests.cs b/src/GitVersionCore.Tests/VersionCalculation/NextVersionCalculatorTests.cs index ba8f0b2feb..6bb4a5553d 100644 --- a/src/GitVersionCore.Tests/VersionCalculation/NextVersionCalculatorTests.cs +++ b/src/GitVersionCore.Tests/VersionCalculation/NextVersionCalculatorTests.cs @@ -58,47 +58,61 @@ public void AppliesBranchPreReleaseTag() [Test] public void PreReleaseTagCanUseBranchName() { - var baseCalculator = new TestBaseVersionCalculator(false, new SemanticVersion(1), new MockCommit()); - var semanticVersionBuildMetaData = new SemanticVersionBuildMetaData(2, "develop", "b1a34e", DateTimeOffset.Now); - var sut = new NextVersionCalculator(baseCalculator, new TestMetaDataCalculator(semanticVersionBuildMetaData)); - var config = new Config(); - config.Branches.Add("custom", new BranchConfig + var config = new Config { - Regex = "custom/", - Tag = "useBranchName" - }); - var context = new GitVersionContextBuilder() - .WithConfig(config) - .WithDevelopBranch() - .AddBranch("custom/foo") - .Build(); + NextVersion = "1.0.0", + Branches = new Dictionary + { + { + "custom", new BranchConfig + { + Regex = "custom/", + Tag = "useBranchName" + } + } + } + }; - var version = sut.FindVersion(context); + using (var fixture = new EmptyRepositoryFixture()) + { + fixture.MakeACommit(); + fixture.BranchTo("develop"); + fixture.MakeACommit(); + fixture.BranchTo("custom/foo"); + fixture.MakeACommit(); - version.ToString("f").ShouldBe("1.0.0-foo.1+2"); + fixture.AssertFullSemver(config, "1.0.0-foo.1+2"); + } } [Test] public void PreReleaseTagCanUseBranchNameVariable() { - var baseCalculator = new TestBaseVersionCalculator(false, new SemanticVersion(1), new MockCommit()); - var semanticVersionBuildMetaData = new SemanticVersionBuildMetaData(2, "develop", "b1a34e", DateTimeOffset.Now); - var sut = new NextVersionCalculator(baseCalculator, new TestMetaDataCalculator(semanticVersionBuildMetaData)); - var config = new Config(); - config.Branches.Add("custom", new BranchConfig + var config = new Config { - Regex = "custom/", - Tag = "alpha.{BranchName}" - }); - var context = new GitVersionContextBuilder() - .WithConfig(config) - .WithDevelopBranch() - .AddBranch("custom/foo") - .Build(); + NextVersion = "1.0.0", + Branches = new Dictionary + { + { + "custom", new BranchConfig + { + Regex = "custom/", + Tag = "alpha.{BranchName}" + } + } + } + }; - var version = sut.FindVersion(context); + using (var fixture = new EmptyRepositoryFixture()) + { + fixture.MakeACommit(); + fixture.BranchTo("develop"); + fixture.MakeACommit(); + fixture.BranchTo("custom/foo"); + fixture.MakeACommit(); - version.ToString("f").ShouldBe("1.0.0-alpha.foo.1+2"); + fixture.AssertFullSemver(config, "1.0.0-alpha.foo.1+2"); + } } [Test] From 6170586b9347bb091a3b2258f480910145421f06 Mon Sep 17 00:00:00 2001 From: Daniel Rose Date: Thu, 17 Nov 2016 17:30:32 +0100 Subject: [PATCH 7/9] Update documentation. --- docs/configuration.md | 9 +++++++-- docs/more-info/version-sources.md | 28 ++++++++++++++++++++-------- 2 files changed, 27 insertions(+), 10 deletions(-) diff --git a/docs/configuration.md b/docs/configuration.md index 67a09ae4d7..967de0e138 100644 --- a/docs/configuration.md +++ b/docs/configuration.md @@ -32,6 +32,7 @@ next-version: 1.0 assembly-versioning-scheme: MajorMinorPatch assembly-informational-format: '{InformationalVersion}' mode: ContinuousDelivery +increment: Inherit continuous-delivery-fallback-tag: ci tag-prefix: '[vV]' major-version-bump-message: '\+semver:\s?(breaking|major)' @@ -70,6 +71,11 @@ value of the `AssemblyInformationalVersion` attribute. Default set to Sets the `mode` of how GitVersion should create a new version. Read more at [versioning mode](/reference/versioning-mode.md). +### increment +The part of the SemVer to increment when GitVersion detects it needs to be increased, such as for commits after a tag: `Major`, `Minor`, `Patch`, `None`. + +The special value `Inherit` means that GitVersion should find the parent branch (i.e. the branch where the current branch was branched from), and use its values for [increment](#increment), [prevent-increment-of-merged-branch-version](#prevent-increment-of-merged-branch-version) and [is-develop](#is-develop). + ### continuous-delivery-fallback-tag When using `mode: ContinuousDeployment`, the value specified in `continuous-delivery-fallback-tag` will be used as the pre-release tag for @@ -246,8 +252,7 @@ of `alpha.foo` with the value of `alpha.{BranchName}`. **Note:** To clear a default use an empty string: `tag: ''` ### increment -The part of the SemVer to increment when GitVersion detects it needs to be (i.e -commit after a tag) +Same as for the [global configuration, explained above](#increment). ### prevent-increment-of-merged-branch-version When `release-2.0.0` is merged into master, we want master to build `2.0.0`. If diff --git a/docs/more-info/version-sources.md b/docs/more-info/version-sources.md index 06e243223f..d402303944 100644 --- a/docs/more-info/version-sources.md +++ b/docs/more-info/version-sources.md @@ -1,5 +1,5 @@ # Version Sources -GitVersion has a two step process for calculating the version number, the first is to calculate the base version which is used to then calculate what the next version should be. +GitVersion has a two step process for calculating the version number. First it calculates the base version, which is then used to calculate what the next version should be. The logic of GitVersion is something like this: @@ -8,26 +8,38 @@ The logic of GitVersion is something like this: - No: continue - Calculate the base version (highest version from all the sources) - Increment version if needed based on branch config - - Calculate the build metadata (everything after the +) and append to the calcuated version + - Calculate the build metadata (everything after the +) and append to the calculated version ## Version Sources -### Highest Accessible Tag -GitVersion will find all tags on the current branch and return the highest one. +### Tag name +Returns the version numbers extracted from the current branch's tags. Will increment: true ### Version in branch name -If the branch has a version in it, then that version will be returned. +Returns the version number from the branch's name. Will increment: false ### Merge message -If a branch with a version number in it is merged into the current branch, that version number will be used. +Returns the version number of any branch (with a version number in its name) merged into the current branch. -Will increment: false +Will increment: depends on the value of `prevent-increment-of-merged-branch-version` ### GitVersion.yml -If the `next-version` property is specified in the config file, it will be used as a version source. +Returns the value of the `next-version` property in the config file. + +Will increment: false + +### Develop branch +For the develop branch, i.e. marked with `is-develop: true` +- Returns the version number extracted from any child release-branches, i.e. those marked with `is-release-branch: true` +- Returns the version number of any tags on the master branch + +Will increment: true + +### Fallback +Returns the version number `0.1.0`. Will increment: false From c74114c42475fce76c44863c9046b6c513071e09 Mon Sep 17 00:00:00 2001 From: Daniel Rose Date: Thu, 17 Nov 2016 17:38:29 +0100 Subject: [PATCH 8/9] Rename class to match what it does. --- src/GitVersionCore.Tests/GitVersionCore.Tests.csproj | 2 +- ...ests.cs => VersionInBranchNameBaseVersionStrategyTests.cs} | 4 ++-- src/GitVersionCore/GitVersionCore.csproj | 2 +- ...nStrategy.cs => VersionInBranchNameBaseVersionStrategy.cs} | 2 +- .../VersionCalculation/DevelopVersionStrategy.cs | 4 ++-- .../VersionCalculation/NextVersionCalculator.cs | 2 +- 6 files changed, 8 insertions(+), 8 deletions(-) rename src/GitVersionCore.Tests/VersionCalculation/Strategies/{VersionInBranchBaseVersionStrategyTests.cs => VersionInBranchNameBaseVersionStrategyTests.cs} (90%) rename src/GitVersionCore/VersionCalculation/BaseVersionCalculators/{VersionInBranchBaseVersionStrategy.cs => VersionInBranchNameBaseVersionStrategy.cs} (96%) diff --git a/src/GitVersionCore.Tests/GitVersionCore.Tests.csproj b/src/GitVersionCore.Tests/GitVersionCore.Tests.csproj index 01852f82fa..df63914c1d 100644 --- a/src/GitVersionCore.Tests/GitVersionCore.Tests.csproj +++ b/src/GitVersionCore.Tests/GitVersionCore.Tests.csproj @@ -173,7 +173,7 @@ - + diff --git a/src/GitVersionCore.Tests/VersionCalculation/Strategies/VersionInBranchBaseVersionStrategyTests.cs b/src/GitVersionCore.Tests/VersionCalculation/Strategies/VersionInBranchNameBaseVersionStrategyTests.cs similarity index 90% rename from src/GitVersionCore.Tests/VersionCalculation/Strategies/VersionInBranchBaseVersionStrategyTests.cs rename to src/GitVersionCore.Tests/VersionCalculation/Strategies/VersionInBranchNameBaseVersionStrategyTests.cs index 55530b8894..01afaa0ea8 100644 --- a/src/GitVersionCore.Tests/VersionCalculation/Strategies/VersionInBranchBaseVersionStrategyTests.cs +++ b/src/GitVersionCore.Tests/VersionCalculation/Strategies/VersionInBranchNameBaseVersionStrategyTests.cs @@ -9,7 +9,7 @@ using Shouldly; [TestFixture] - public class VersionInBranchBaseVersionStrategyTests + public class VersionInBranchNameBaseVersionStrategyTests { [Test] [TestCase("release-2.0.0", "2.0.0")] @@ -23,7 +23,7 @@ public void CanTakeVersionFromBranchName(string branchName, string expectedBaseV { fixture.Repository.MakeACommit(); var branch = fixture.Repository.CreateBranch(branchName); - var sut = new VersionInBranchBaseVersionStrategy(); + var sut = new VersionInBranchNameBaseVersionStrategy(); var gitVersionContext = new GitVersionContext(fixture.Repository, branch, new Config().ApplyDefaults()); var baseVersion = sut.GetVersions(gitVersionContext).SingleOrDefault(); diff --git a/src/GitVersionCore/GitVersionCore.csproj b/src/GitVersionCore/GitVersionCore.csproj index 174198e149..c77971821e 100644 --- a/src/GitVersionCore/GitVersionCore.csproj +++ b/src/GitVersionCore/GitVersionCore.csproj @@ -146,7 +146,7 @@ - + diff --git a/src/GitVersionCore/VersionCalculation/BaseVersionCalculators/VersionInBranchBaseVersionStrategy.cs b/src/GitVersionCore/VersionCalculation/BaseVersionCalculators/VersionInBranchNameBaseVersionStrategy.cs similarity index 96% rename from src/GitVersionCore/VersionCalculation/BaseVersionCalculators/VersionInBranchBaseVersionStrategy.cs rename to src/GitVersionCore/VersionCalculation/BaseVersionCalculators/VersionInBranchNameBaseVersionStrategy.cs index 84129fcc0d..89a6ff7cf8 100644 --- a/src/GitVersionCore/VersionCalculation/BaseVersionCalculators/VersionInBranchBaseVersionStrategy.cs +++ b/src/GitVersionCore/VersionCalculation/BaseVersionCalculators/VersionInBranchNameBaseVersionStrategy.cs @@ -9,7 +9,7 @@ /// BaseVersionSource is the commit where the branch was branched from its parent. /// Does not increment. /// - public class VersionInBranchBaseVersionStrategy : BaseVersionStrategy + public class VersionInBranchNameBaseVersionStrategy : BaseVersionStrategy { public override IEnumerable GetVersions(GitVersionContext context) { diff --git a/src/GitVersionCore/VersionCalculation/DevelopVersionStrategy.cs b/src/GitVersionCore/VersionCalculation/DevelopVersionStrategy.cs index 39bd62b31a..71e1591bb5 100644 --- a/src/GitVersionCore/VersionCalculation/DevelopVersionStrategy.cs +++ b/src/GitVersionCore/VersionCalculation/DevelopVersionStrategy.cs @@ -11,7 +11,7 @@ namespace GitVersion.VersionCalculation /// Active only when the branch is marked as IsDevelop. /// Two different algorithms (results are merged): /// - /// Using : + /// 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. @@ -25,7 +25,7 @@ namespace GitVersion.VersionCalculation /// public class TrackReleaseBranchesVersionStrategy : BaseVersionStrategy { - VersionInBranchBaseVersionStrategy releaseVersionStrategy = new VersionInBranchBaseVersionStrategy(); + VersionInBranchNameBaseVersionStrategy releaseVersionStrategy = new VersionInBranchNameBaseVersionStrategy(); TaggedCommitVersionStrategy taggedCommitVersionStrategy = new TaggedCommitVersionStrategy(); public override IEnumerable GetVersions(GitVersionContext context) diff --git a/src/GitVersionCore/VersionCalculation/NextVersionCalculator.cs b/src/GitVersionCore/VersionCalculation/NextVersionCalculator.cs index 6d28f27d07..03ac5325eb 100644 --- a/src/GitVersionCore/VersionCalculation/NextVersionCalculator.cs +++ b/src/GitVersionCore/VersionCalculation/NextVersionCalculator.cs @@ -21,7 +21,7 @@ public NextVersionCalculator(IBaseVersionCalculator baseVersionCalculator = null new ConfigNextVersionBaseVersionStrategy(), new TaggedCommitVersionStrategy(), new MergeMessageBaseVersionStrategy(), - new VersionInBranchBaseVersionStrategy(), + new VersionInBranchNameBaseVersionStrategy(), new TrackReleaseBranchesVersionStrategy()); } From ad3590d74a284733bfa85a10736eef926d979cf5 Mon Sep 17 00:00:00 2001 From: Daniel Rose Date: Fri, 25 Nov 2016 16:18:02 +0100 Subject: [PATCH 9/9] More detail when logging. --- src/GitVersionCore/LibGitExtensions.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/GitVersionCore/LibGitExtensions.cs b/src/GitVersionCore/LibGitExtensions.cs index 3fc994da90..130cc91c76 100644 --- a/src/GitVersionCore/LibGitExtensions.cs +++ b/src/GitVersionCore/LibGitExtensions.cs @@ -45,7 +45,7 @@ public static BranchCommit FindCommitBranchWasBranchedFrom([NotNull] this Branch throw new ArgumentNullException("branch"); } - using (Logger.IndentLog("Finding branch source")) + using (Logger.IndentLog(string.Format("Finding branch source of '{0}'", branch.FriendlyName))) { if (branch.Tip == null) { @@ -77,7 +77,7 @@ public static BranchCommit FindCommitBranchWasBranchedFrom([NotNull] this Branch /// 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))) + using (Logger.IndentLog(string.Format("Finding merge base between '{0}' and '{1}'.", branch.FriendlyName, otherBranch.FriendlyName))) { // Otherbranch tip is a forward merge var commitToFindCommonBase = otherBranch.Tip;