diff --git a/GitVersionCore.Tests/GitVersionContextBuilder.cs b/GitVersionCore.Tests/GitVersionContextBuilder.cs
new file mode 100644
index 0000000000..9894e3fcba
--- /dev/null
+++ b/GitVersionCore.Tests/GitVersionContextBuilder.cs
@@ -0,0 +1,76 @@
+namespace GitVersionCore.Tests
+{
+ using GitVersion;
+ using LibGit2Sharp;
+
+ public class GitVersionContextBuilder
+ {
+ IRepository repository;
+ Config config;
+
+ public GitVersionContextBuilder WithRepository(IRepository repository)
+ {
+ this.repository = repository;
+ return this;
+ }
+
+ public GitVersionContextBuilder WithConfig(Config config)
+ {
+ this.config = config;
+ return this;
+ }
+
+ public GitVersionContextBuilder WithTaggedMaster()
+ {
+ repository = CreateRepository();
+ var target = repository.Head.Tip;
+ ((MockTagCollection)repository.Tags).Add(new MockTag ("1.0.0", target));
+ ((MockBranch)repository.Head).Add(new MockCommit { CommitterEx = SignatureBuilder.SignatureNow() });
+ return this;
+ }
+
+ public GitVersionContextBuilder AddCommit()
+ {
+ ((MockBranch)repository.Head).Add(new MockCommit());
+ return this;
+ }
+
+ public GitVersionContextBuilder WithDevelopBranch()
+ {
+ return WithBranch("develop");
+ }
+
+ public GitVersionContextBuilder WithBranch(string branchName)
+ {
+ repository = CreateRepository();
+ var mockBranch = new MockBranch(branchName)
+ {
+ new MockCommit()
+ };
+ ((MockBranchCollection)repository.Branches).Add(mockBranch);
+ ((MockRepository)repository).Head = mockBranch;
+ return this;
+ }
+
+ public GitVersionContext Build()
+ {
+ return new GitVersionContext(repository ?? CreateRepository(), config ?? new Config());
+ }
+
+ IRepository CreateRepository()
+ {
+ var mockBranch = new MockBranch("master") { new MockCommit { CommitterEx = SignatureBuilder.SignatureNow() } };
+ var mockRepository = new MockRepository
+ {
+ Branches = new MockBranchCollection
+ {
+ mockBranch
+ },
+ Tags = new MockTagCollection(),
+ Head = mockBranch
+ };
+
+ return mockRepository;
+ }
+ }
+}
\ No newline at end of file
diff --git a/GitVersionCore.Tests/GitVersionCore.Tests.csproj b/GitVersionCore.Tests/GitVersionCore.Tests.csproj
index 1ee1fb42dc..1874bf8dfd 100644
--- a/GitVersionCore.Tests/GitVersionCore.Tests.csproj
+++ b/GitVersionCore.Tests/GitVersionCore.Tests.csproj
@@ -115,6 +115,15 @@
+
+
+
+
+
+
+
+
+
diff --git a/GitVersionCore.Tests/Mocks/MockTag.cs b/GitVersionCore.Tests/Mocks/MockTag.cs
index 4ea1364815..5400fb5ee0 100644
--- a/GitVersionCore.Tests/Mocks/MockTag.cs
+++ b/GitVersionCore.Tests/Mocks/MockTag.cs
@@ -15,6 +15,15 @@ public override GitObject Target
get { return TargetEx; }
}
public TagAnnotation AnnotationEx;
+
+ public MockTag() { }
+
+ public MockTag(string name, Commit target)
+ {
+ NameEx = name;
+ TargetEx = target;
+ }
+
public override TagAnnotation Annotation
{
get { return AnnotationEx; }
diff --git a/GitVersionCore.Tests/TestEffectiveConfiguration.cs b/GitVersionCore.Tests/TestEffectiveConfiguration.cs
index 055be59556..e6ef0a893e 100644
--- a/GitVersionCore.Tests/TestEffectiveConfiguration.cs
+++ b/GitVersionCore.Tests/TestEffectiveConfiguration.cs
@@ -10,7 +10,7 @@ public TestEffectiveConfiguration(
string gitTagPrefix = "v",
string tag = "",
string nextVersion = null) :
- base(assemblyVersioningScheme, versioningMode, gitTagPrefix, tag, nextVersion)
+ base(assemblyVersioningScheme, versioningMode, gitTagPrefix, tag, nextVersion, IncrementStrategy.Patch)
{
}
}
diff --git a/GitVersionCore.Tests/VersionCalculation/BaseVersionCalculatorTests.cs b/GitVersionCore.Tests/VersionCalculation/BaseVersionCalculatorTests.cs
new file mode 100644
index 0000000000..f2fe0e1afe
--- /dev/null
+++ b/GitVersionCore.Tests/VersionCalculation/BaseVersionCalculatorTests.cs
@@ -0,0 +1,86 @@
+namespace GitVersionCore.Tests.VersionCalculation
+{
+ using System;
+ using GitVersion;
+ using GitVersion.VersionCalculation;
+ using GitVersion.VersionCalculation.BaseVersionCalculators;
+ using LibGit2Sharp;
+ using NUnit.Framework;
+ using Shouldly;
+
+ [TestFixture]
+ public class BaseVersionCalculatorTests
+ {
+ [Test]
+ public void ChoosesHighestVersionReturnedFromStrategies()
+ {
+ var context = new GitVersionContextBuilder().Build();
+ var dateTimeOffset = DateTimeOffset.Now;
+ var sut = new BaseVersionCalculator(new V1Strategy(DateTimeOffset.Now), new V2Strategy(dateTimeOffset));
+
+ var baseVersion = sut.GetBaseVersion(context);
+
+ baseVersion.SemanticVersion.ToString().ShouldBe("2.0.0");
+ baseVersion.ShouldIncrement.ShouldBe(true);
+ baseVersion.BaseVersionSource.When().ShouldBe(dateTimeOffset);
+ }
+
+ [Test]
+ public void UsesWhenFromNextBestMatchIfHighestDoesntHaveWhen()
+ {
+ var context = new GitVersionContextBuilder().Build();
+ var when = DateTimeOffset.Now;
+ var sut = new BaseVersionCalculator(new V1Strategy(when), new V2Strategy(null));
+
+ var baseVersion = sut.GetBaseVersion(context);
+
+ baseVersion.SemanticVersion.ToString().ShouldBe("2.0.0");
+ baseVersion.ShouldIncrement.ShouldBe(true);
+ baseVersion.BaseVersionSource.When().ShouldBe(when);
+ }
+
+ [Test]
+ public void UsesWhenFromNextBestMatchIfHighestDoesntHaveWhenReversedOrder()
+ {
+ var context = new GitVersionContextBuilder().Build();
+ var when = DateTimeOffset.Now;
+ var sut = new BaseVersionCalculator(new V1Strategy(null), new V2Strategy(when));
+
+ var baseVersion = sut.GetBaseVersion(context);
+
+ baseVersion.SemanticVersion.ToString().ShouldBe("2.0.0");
+ baseVersion.ShouldIncrement.ShouldBe(true);
+ baseVersion.BaseVersionSource.When().ShouldBe(when);
+ }
+
+ class V1Strategy : BaseVersionStrategy
+ {
+ readonly Commit when;
+
+ public V1Strategy(DateTimeOffset? when)
+ {
+ this.when = when == null ? null : new MockCommit { CommitterEx = when.Value.ToSignature() };
+ }
+
+ public override BaseVersion GetVersion(GitVersionContext context)
+ {
+ return new BaseVersion(false, new SemanticVersion(1), when);
+ }
+ }
+
+ class V2Strategy : BaseVersionStrategy
+ {
+ Commit when;
+
+ public V2Strategy(DateTimeOffset? when)
+ {
+ this.when = when == null ? null : new MockCommit { CommitterEx = when.Value.ToSignature() };
+ }
+
+ public override BaseVersion GetVersion(GitVersionContext context)
+ {
+ return new BaseVersion(true, new SemanticVersion(2), when);
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/GitVersionCore.Tests/VersionCalculation/NewNextVersionCalculatorTests.cs b/GitVersionCore.Tests/VersionCalculation/NewNextVersionCalculatorTests.cs
new file mode 100644
index 0000000000..4b934a362c
--- /dev/null
+++ b/GitVersionCore.Tests/VersionCalculation/NewNextVersionCalculatorTests.cs
@@ -0,0 +1,62 @@
+namespace GitVersionCore.Tests.VersionCalculation
+{
+ using System;
+ using GitVersion;
+ using GitVersion.VersionCalculation;
+ using NUnit.Framework;
+ using Shouldly;
+
+ public class NewNextVersionCalculatorTests
+ {
+ [Test]
+ public void ShouldIncrementVersionBasedOnConfig()
+ {
+ var baseCalculator = new TestBaseVersionCalculator(true, new SemanticVersion(1), new MockCommit());
+ var semanticVersionBuildMetaData = new SemanticVersionBuildMetaData(1, "master", "b1a34e", DateTimeOffset.Now);
+ var sut = new NewNextVersionCalculator(baseCalculator, new TestMetaDataCalculator(semanticVersionBuildMetaData));
+ var config = new Config();
+ config.Branches.Add("master", new BranchConfig
+ {
+ Increment = IncrementStrategy.Major
+ });
+ var context = new GitVersionContextBuilder().WithConfig(config).Build();
+
+ var version = sut.FindVersion(context);
+
+ version.ToString().ShouldBe("2.0.0");
+ }
+
+ [Test]
+ public void DoesNotIncrementWhenBaseVersionSaysNotTo()
+ {
+ var baseCalculator = new TestBaseVersionCalculator(false, new SemanticVersion(1), new MockCommit());
+ var semanticVersionBuildMetaData = new SemanticVersionBuildMetaData(1, "master", "b1a34e", DateTimeOffset.Now);
+ var sut = new NewNextVersionCalculator(baseCalculator, new TestMetaDataCalculator(semanticVersionBuildMetaData));
+ var config = new Config();
+ config.Branches.Add("master", new BranchConfig
+ {
+ Increment = IncrementStrategy.Major
+ });
+ var context = new GitVersionContextBuilder().WithConfig(config).Build();
+
+ var version = sut.FindVersion(context);
+
+ version.ToString().ShouldBe("1.0.0");
+ }
+
+ [Test]
+ public void AppliesBranchPreReleaseTag()
+ {
+ var baseCalculator = new TestBaseVersionCalculator(false, new SemanticVersion(1), new MockCommit());
+ var semanticVersionBuildMetaData = new SemanticVersionBuildMetaData(1, "develop", "b1a34e", DateTimeOffset.Now);
+ var sut = new NewNextVersionCalculator(baseCalculator, new TestMetaDataCalculator(semanticVersionBuildMetaData));
+ var context = new GitVersionContextBuilder()
+ .WithDevelopBranch()
+ .Build();
+
+ var version = sut.FindVersion(context);
+
+ version.ToString().ShouldBe("1.0.0-unstable.1");
+ }
+ }
+}
\ No newline at end of file
diff --git a/GitVersionCore.Tests/VersionCalculation/Strategies/ConfigNextVersionBaseVersionStrategyTests.cs b/GitVersionCore.Tests/VersionCalculation/Strategies/ConfigNextVersionBaseVersionStrategyTests.cs
new file mode 100644
index 0000000000..d68469ccfd
--- /dev/null
+++ b/GitVersionCore.Tests/VersionCalculation/Strategies/ConfigNextVersionBaseVersionStrategyTests.cs
@@ -0,0 +1,38 @@
+namespace GitVersionCore.Tests.VersionCalculation.Strategies
+{
+ using GitVersion;
+ using GitVersion.VersionCalculation.BaseVersionCalculators;
+ using NUnit.Framework;
+ using Shouldly;
+
+ [TestFixture]
+ public class ConfigNextVersionBaseVersionStrategyTests
+ {
+ [Test]
+ public void ShouldNotBeIncremented()
+ {
+ var contextBuilder = new GitVersionContextBuilder()
+ .WithConfig(new Config
+ {
+ NextVersion = "1.0.0"
+ });
+ var sut = new ConfigNextVersionBaseVersionStrategy();
+
+ var baseVersion = sut.GetVersion(contextBuilder.Build());
+
+ baseVersion.ShouldIncrement.ShouldBe(false);
+ baseVersion.SemanticVersion.ToString().ShouldBe("1.0.0");
+ }
+
+ [Test]
+ public void ReturnsNullWhenNoNextVersionIsInConfig()
+ {
+ var contextBuilder = new GitVersionContextBuilder();
+ var sut = new ConfigNextVersionBaseVersionStrategy();
+
+ var baseVersion = sut.GetVersion(contextBuilder.Build());
+
+ baseVersion.ShouldBe(null);
+ }
+ }
+}
\ No newline at end of file
diff --git a/GitVersionCore.Tests/VersionCalculation/Strategies/LastTagBaseVersionStrategyTests.cs b/GitVersionCore.Tests/VersionCalculation/Strategies/LastTagBaseVersionStrategyTests.cs
new file mode 100644
index 0000000000..0f99fcd46f
--- /dev/null
+++ b/GitVersionCore.Tests/VersionCalculation/Strategies/LastTagBaseVersionStrategyTests.cs
@@ -0,0 +1,37 @@
+namespace GitVersionCore.Tests.VersionCalculation.Strategies
+{
+ using GitVersion.VersionCalculation.BaseVersionCalculators;
+ using NUnit.Framework;
+ using Shouldly;
+
+ [TestFixture]
+ public class LastTagBaseVersionStrategyTests
+ {
+ [Test]
+ public void ShouldAllowVersionIncrement()
+ {
+ var context = new GitVersionContextBuilder()
+ .WithTaggedMaster()
+ .AddCommit()
+ .Build();
+ var sut = new LastTagBaseVersionStrategy();
+
+ var baseVersion = sut.GetVersion(context);
+
+ baseVersion.ShouldIncrement.ShouldBe(true);
+ }
+
+ [Test]
+ public void ShouldNotAllowVersionIncrementWhenTagComesFromCurrentCommit()
+ {
+ var context = new GitVersionContextBuilder()
+ .WithTaggedMaster()
+ .Build();
+ var sut = new LastTagBaseVersionStrategy();
+
+ var baseVersion = sut.GetVersion(context);
+
+ baseVersion.ShouldIncrement.ShouldBe(false);
+ }
+ }
+}
\ No newline at end of file
diff --git a/GitVersionCore.Tests/VersionCalculation/Strategies/MergeMessageBaseVersionStrategyTests.cs b/GitVersionCore.Tests/VersionCalculation/Strategies/MergeMessageBaseVersionStrategyTests.cs
new file mode 100644
index 0000000000..ac22497e58
--- /dev/null
+++ b/GitVersionCore.Tests/VersionCalculation/Strategies/MergeMessageBaseVersionStrategyTests.cs
@@ -0,0 +1,110 @@
+namespace GitVersionCore.Tests.VersionCalculation.Strategies
+{
+ using System.Collections.Generic;
+ using GitVersion.VersionCalculation.BaseVersionCalculators;
+ using LibGit2Sharp;
+ using NUnit.Framework;
+ using Shouldly;
+
+ [TestFixture]
+ public class MergeMessageBaseVersionStrategyTests
+ {
+ [Test]
+ public void ShouldAllowIncrementOfVersion()
+ {
+ var context = new GitVersionContextBuilder().WithRepository(new MockRepository
+ {
+ Head = new MockBranch("master") { new MockCommit
+ {
+ MessageEx = "Merge branch 'hotfix-0.1.5'",
+ ParentsEx = GetParents(true)
+ } }
+ }).Build();
+ var sut = new MergeMessageBaseVersionStrategy();
+
+ var baseVersion = sut.GetVersion(context);
+
+ baseVersion.ShouldIncrement.ShouldBe(true);
+ }
+
+ [TestCase("Merge branch 'hotfix-0.1.5'", false, null)]
+ [TestCase("Merge branch 'develop' of github.com:Particular/NServiceBus into develop", true, null)]
+ [TestCase("Merge branch '4.0.3'", true, "4.0.3")] //TODO: possible make it a config option to support this
+ [TestCase("Merge branch 'release-10.10.50'", true, "10.10.50")]
+ [TestCase("Merge branch 's'", true, null)] // Must start with a number
+ [TestCase("Merge branch 'release-0.2.0'", true, "0.2.0")]
+ [TestCase("Merge branch 'hotfix-4.6.6' into support-4.6", true, "4.6.6")]
+ [TestCase("Merge branch 'hotfix-10.10.50'", true, "10.10.50")]
+ [TestCase("Merge branch 'hotfix-0.1.5'", true, "0.1.5")]
+ [TestCase("Merge branch 'hotfix-0.1.5'\n\nRelates to: TicketId", true, "0.1.5")]
+ [TestCase("Merge branch 'alpha-0.1.5'", true, "0.1.5")]
+ [TestCase("Merge pull request #165 from Particular/release-1.0.0", true, "1.0.0")]
+ [TestCase("Merge pull request #95 from Particular/issue-94", false, null)]
+ [TestCase("Merge pull request #165 in Particular/release-1.0.0", true, "1.0.0")]
+ [TestCase("Merge pull request #95 in Particular/issue-94", true, null)]
+ [TestCase("Merge pull request #95 in Particular/issue-94", false, null)]
+ [TestCase("Merge pull request #64 from arledesma/feature-VS2013_3rd_party_test_framework_support", true, null)]
+ [TestCase("Finish Release-0.12.0", true, "0.12.0")] //Support Syntevo SmartGit/Hg's Gitflow merge commit messages for finishing a 'Release' branch
+ [TestCase("Finish 0.14.1", true, "0.14.1")] //Support Syntevo SmartGit/Hg's Gitflow merge commit messages for finishing a 'Hotfix' branch
+ public void AssertMergeMessage(string message, bool isMergeCommit, string expectedVersion)
+ {
+ var parents = GetParents(isMergeCommit);
+ AssertMergeMessage(message, expectedVersion, parents);
+ AssertMergeMessage(message + " ", expectedVersion, parents);
+ AssertMergeMessage(message + "\r ", expectedVersion, parents);
+ AssertMergeMessage(message + "\r", expectedVersion, parents);
+ AssertMergeMessage(message + "\r\n", expectedVersion, parents);
+ AssertMergeMessage(message + "\r\n ", expectedVersion, parents);
+ AssertMergeMessage(message + "\n", expectedVersion, parents);
+ AssertMergeMessage(message + "\n ", expectedVersion, parents);
+ }
+
+ static void AssertMergeMessage(string message, string expectedVersion, List parents)
+ {
+ var commit = new MockCommit
+ {
+ MessageEx = message,
+ ParentsEx = parents
+ };
+
+ var context = new GitVersionContextBuilder()
+ .WithRepository(new MockRepository
+ {
+ Head = new MockBranch("master")
+ {
+ commit,
+ new MockCommit()
+ }
+ })
+ .Build();
+ var sut = new MergeMessageBaseVersionStrategy();
+
+ var baseVersion = sut.GetVersion(context);
+
+ if (expectedVersion == null)
+ {
+ baseVersion.ShouldBe(null);
+ }
+ else
+ {
+ baseVersion.SemanticVersion.ToString().ShouldBe(expectedVersion);
+ }
+ }
+
+ static List GetParents(bool isMergeCommit)
+ {
+ if (isMergeCommit)
+ {
+ return new List
+ {
+ null,
+ null
+ };
+ }
+ return new List
+ {
+ null
+ };
+ }
+ }
+}
\ No newline at end of file
diff --git a/GitVersionCore.Tests/VersionCalculation/Strategies/VersionInBranchBaseVersionStrategyTests.cs b/GitVersionCore.Tests/VersionCalculation/Strategies/VersionInBranchBaseVersionStrategyTests.cs
new file mode 100644
index 0000000000..bffb3f0a0e
--- /dev/null
+++ b/GitVersionCore.Tests/VersionCalculation/Strategies/VersionInBranchBaseVersionStrategyTests.cs
@@ -0,0 +1,34 @@
+namespace GitVersionCore.Tests.VersionCalculation.Strategies
+{
+ using GitVersion.VersionCalculation.BaseVersionCalculators;
+ using NUnit.Framework;
+ using Shouldly;
+
+ [TestFixture]
+ public class VersionInBranchBaseVersionStrategyTests
+ {
+ [Test]
+ [TestCase("release-2.0.0", "2.0.0")]
+ [TestCase("release/2.0.0", "2.0.0")]
+ [TestCase("hotfix-2.0.0", "2.0.0")]
+ [TestCase("hotfix/2.0.0", "2.0.0")]
+ [TestCase("hotfix/2.0.0", "2.0.0")]
+ [TestCase("feature/JIRA-123", null)]
+ public void CanTakeVersionFromBranchName(string branchName, string expectedBaseVersion)
+ {
+ var context = new GitVersionContextBuilder()
+ .WithBranch(branchName)
+ .AddCommit()
+ .Build();
+
+ var sut = new VersionInBranchBaseVersionStrategy();
+
+ var baseVersion = sut.GetVersion(context);
+
+ if (expectedBaseVersion == null)
+ baseVersion.ShouldBe(null);
+ else
+ baseVersion.SemanticVersion.ToString().ShouldBe(expectedBaseVersion);
+ }
+ }
+}
diff --git a/GitVersionCore.Tests/VersionCalculation/TestBaseVersionCalculator.cs b/GitVersionCore.Tests/VersionCalculation/TestBaseVersionCalculator.cs
new file mode 100644
index 0000000000..c094ad625e
--- /dev/null
+++ b/GitVersionCore.Tests/VersionCalculation/TestBaseVersionCalculator.cs
@@ -0,0 +1,26 @@
+namespace GitVersionCore.Tests.VersionCalculation
+{
+ using GitVersion;
+ using GitVersion.VersionCalculation;
+ using GitVersion.VersionCalculation.BaseVersionCalculators;
+ using LibGit2Sharp;
+
+ public class TestBaseVersionCalculator : IBaseVersionCalculator
+ {
+ readonly SemanticVersion semanticVersion;
+ bool shouldIncrement;
+ Commit source;
+
+ public TestBaseVersionCalculator(bool shouldIncrement, SemanticVersion semanticVersion, Commit source)
+ {
+ this.semanticVersion = semanticVersion;
+ this.source = source;
+ this.shouldIncrement = shouldIncrement;
+ }
+
+ public BaseVersion GetBaseVersion(GitVersionContext context)
+ {
+ return new BaseVersion(shouldIncrement, semanticVersion, source);
+ }
+ }
+}
\ No newline at end of file
diff --git a/GitVersionCore.Tests/VersionCalculation/TestMetaDataCalculator.cs b/GitVersionCore.Tests/VersionCalculation/TestMetaDataCalculator.cs
new file mode 100644
index 0000000000..51f7a95b22
--- /dev/null
+++ b/GitVersionCore.Tests/VersionCalculation/TestMetaDataCalculator.cs
@@ -0,0 +1,21 @@
+namespace GitVersionCore.Tests.VersionCalculation
+{
+ using GitVersion;
+ using GitVersion.VersionCalculation;
+ using LibGit2Sharp;
+
+ public class TestMetaDataCalculator : IMetaDataCalculator
+ {
+ SemanticVersionBuildMetaData metaData;
+
+ public TestMetaDataCalculator(SemanticVersionBuildMetaData metaData)
+ {
+ this.metaData = metaData;
+ }
+
+ public SemanticVersionBuildMetaData Create(Commit baseVersionSource, GitVersionContext context)
+ {
+ return metaData;
+ }
+ }
+}
\ No newline at end of file
diff --git a/GitVersionCore/Configuration/BranchConfig.cs b/GitVersionCore/Configuration/BranchConfig.cs
index 1b7494e0f0..e0f10d561e 100644
--- a/GitVersionCore/Configuration/BranchConfig.cs
+++ b/GitVersionCore/Configuration/BranchConfig.cs
@@ -9,5 +9,8 @@ public class BranchConfig
[YamlAlias("tag")]
public string Tag { get; set; }
+
+ [YamlAlias("increment")]
+ public IncrementStrategy? Increment { get; set; }
}
}
diff --git a/GitVersionCore/Configuration/Config.cs b/GitVersionCore/Configuration/Config.cs
index ed487c57db..9157e84293 100644
--- a/GitVersionCore/Configuration/Config.cs
+++ b/GitVersionCore/Configuration/Config.cs
@@ -18,6 +18,7 @@ public Config()
Branches["develop"] = new BranchConfig
{
Tag = "unstable",
+ Increment = IncrementStrategy.Minor,
VersioningMode = GitVersion.VersioningMode.ContinuousDeployment
};
}
diff --git a/GitVersionCore/Configuration/IncrementStrategy.cs b/GitVersionCore/Configuration/IncrementStrategy.cs
new file mode 100644
index 0000000000..49c251a9b2
--- /dev/null
+++ b/GitVersionCore/Configuration/IncrementStrategy.cs
@@ -0,0 +1,10 @@
+namespace GitVersion
+{
+ public enum IncrementStrategy
+ {
+ None,
+ Major,
+ Minor,
+ Patch
+ }
+}
\ No newline at end of file
diff --git a/GitVersionCore/EffectiveConfiguration.cs b/GitVersionCore/EffectiveConfiguration.cs
index 9daed63748..5a8211349f 100644
--- a/GitVersionCore/EffectiveConfiguration.cs
+++ b/GitVersionCore/EffectiveConfiguration.cs
@@ -5,13 +5,14 @@
///
public class EffectiveConfiguration
{
- public EffectiveConfiguration(AssemblyVersioningScheme assemblyVersioningScheme, VersioningMode versioningMode, string gitTagPrefix, string tag, string nextVersion)
+ public EffectiveConfiguration(AssemblyVersioningScheme assemblyVersioningScheme, VersioningMode versioningMode, string gitTagPrefix, string tag, string nextVersion, IncrementStrategy increment)
{
AssemblyVersioningScheme = assemblyVersioningScheme;
VersioningMode = versioningMode;
GitTagPrefix = gitTagPrefix;
Tag = tag;
NextVersion = nextVersion;
+ Increment = increment;
}
public VersioningMode VersioningMode { get; private set; }
@@ -29,5 +30,6 @@ public EffectiveConfiguration(AssemblyVersioningScheme assemblyVersioningScheme,
public string Tag { get; private set; }
public string NextVersion { get; private set; }
+ public IncrementStrategy Increment { get; private set; }
}
}
\ No newline at end of file
diff --git a/GitVersionCore/GitVersionContext.cs b/GitVersionCore/GitVersionContext.cs
index 3bd8a0ef7e..c858437386 100644
--- a/GitVersionCore/GitVersionContext.cs
+++ b/GitVersionCore/GitVersionContext.cs
@@ -88,8 +88,9 @@ void CalculateEffectiveConfiguration()
var versioningMode = currentBranchConfig.VersioningMode ?? configuration.VersioningMode ?? VersioningMode.ContinuousDelivery;
var tag = currentBranchConfig.Tag;
var nextVersion = configuration.NextVersion;
+ var incrementStrategy = currentBranchConfig.Increment ?? IncrementStrategy.Patch;
- Configuration = new EffectiveConfiguration(configuration.AssemblyVersioningScheme, versioningMode, configuration.TagPrefix, tag, nextVersion);
+ Configuration = new EffectiveConfiguration(configuration.AssemblyVersioningScheme, versioningMode, configuration.TagPrefix, tag, nextVersion, incrementStrategy);
}
BranchConfig GetBranchConfiguration(KeyValuePair[] matchingBranches)
diff --git a/GitVersionCore/GitVersionCore.csproj b/GitVersionCore/GitVersionCore.csproj
index a906b5bb25..cd29124ef3 100644
--- a/GitVersionCore/GitVersionCore.csproj
+++ b/GitVersionCore/GitVersionCore.csproj
@@ -74,6 +74,7 @@
+
@@ -87,6 +88,17 @@
+
+
+
+
+
+
+
+
+
+
+
@@ -144,6 +156,7 @@
+
diff --git a/GitVersionCore/GitVersionFinder.cs b/GitVersionCore/GitVersionFinder.cs
index 418c934ec7..41a71066f9 100644
--- a/GitVersionCore/GitVersionFinder.cs
+++ b/GitVersionCore/GitVersionFinder.cs
@@ -10,6 +10,8 @@ public SemanticVersion FindVersion(GitVersionContext context)
Logger.WriteInfo("Running against branch: " + context.CurrentBranch.Name);
EnsureMainTopologyConstraints(context);
+ //return new NewNextVersionCalculator().FindVersion(context);
+
if (ShouldGitHubFlowVersioningSchemeApply(context.Repository))
{
Logger.WriteInfo("GitHubFlow version strategy will be used");
diff --git a/GitVersionCore/MergeMessageParser.cs b/GitVersionCore/MergeMessageParser.cs
index e97b741335..a477a4da27 100644
--- a/GitVersionCore/MergeMessageParser.cs
+++ b/GitVersionCore/MergeMessageParser.cs
@@ -6,14 +6,14 @@ namespace GitVersion
static class MergeMessageParser
{
- public static bool TryParse(Commit mergeCommit, EffectiveConfiguration configuration, out SemanticVersion shortVersion)
+ public static bool TryParse(Commit mergeCommit, EffectiveConfiguration configuration, out SemanticVersion semanticVersion)
{
string versionPart;
if (Inner(mergeCommit, out versionPart))
{
- return SemanticVersion.TryParse(versionPart, configuration.GitTagPrefix, out shortVersion);
+ return SemanticVersion.TryParse(versionPart, configuration.GitTagPrefix, out semanticVersion);
}
- shortVersion = null;
+ semanticVersion = null;
return false;
}
diff --git a/GitVersionCore/SemanticVersion.cs b/GitVersionCore/SemanticVersion.cs
index 77e628ce14..e5a4778854 100644
--- a/GitVersionCore/SemanticVersion.cs
+++ b/GitVersionCore/SemanticVersion.cs
@@ -15,8 +15,11 @@ public class SemanticVersion : IFormattable, IComparable
public SemanticVersionPreReleaseTag PreReleaseTag;
public SemanticVersionBuildMetaData BuildMetaData;
- public SemanticVersion()
+ public SemanticVersion(int major = 0, int minor = 0, int patch = 0)
{
+ Major = major;
+ Minor = minor;
+ Patch = patch;
PreReleaseTag = new SemanticVersionPreReleaseTag();
BuildMetaData = new SemanticVersionBuildMetaData();
}
diff --git a/GitVersionCore/VersionCalculation/BaseVersionCalculator.cs b/GitVersionCore/VersionCalculation/BaseVersionCalculator.cs
new file mode 100644
index 0000000000..ebe6c56153
--- /dev/null
+++ b/GitVersionCore/VersionCalculation/BaseVersionCalculator.cs
@@ -0,0 +1,31 @@
+namespace GitVersion.VersionCalculation
+{
+ using System.Linq;
+ using BaseVersionCalculators;
+
+ public class BaseVersionCalculator : IBaseVersionCalculator
+ {
+ readonly BaseVersionStrategy[] strategies;
+
+ public BaseVersionCalculator(params BaseVersionStrategy[] strategies)
+ {
+ this.strategies = strategies;
+ }
+
+ public BaseVersion GetBaseVersion(GitVersionContext context)
+ {
+ return strategies
+ .Select(s => s.GetVersion(context))
+ .Where(v => v != null)
+ .Aggregate((v1, v2) =>
+ {
+ if (v1.SemanticVersion > v2.SemanticVersion)
+ {
+ return new BaseVersion(v1.ShouldIncrement, v1.SemanticVersion, v1.BaseVersionSource ?? v2.BaseVersionSource);
+ }
+
+ return new BaseVersion(v2.ShouldIncrement, v2.SemanticVersion, v2.BaseVersionSource ?? v1.BaseVersionSource);
+ });
+ }
+ }
+}
\ No newline at end of file
diff --git a/GitVersionCore/VersionCalculation/BaseVersionCalculators/BaseVersion.cs b/GitVersionCore/VersionCalculation/BaseVersionCalculators/BaseVersion.cs
new file mode 100644
index 0000000000..9f4b417db9
--- /dev/null
+++ b/GitVersionCore/VersionCalculation/BaseVersionCalculators/BaseVersion.cs
@@ -0,0 +1,20 @@
+namespace GitVersion.VersionCalculation.BaseVersionCalculators
+{
+ using LibGit2Sharp;
+
+ public class BaseVersion
+ {
+ public BaseVersion(bool shouldIncrement, SemanticVersion semanticVersion, Commit baseVersionSource)
+ {
+ ShouldIncrement = shouldIncrement;
+ SemanticVersion = semanticVersion;
+ BaseVersionSource = baseVersionSource;
+ }
+
+ public bool ShouldIncrement { get; private set; }
+
+ public SemanticVersion SemanticVersion { get; private set; }
+
+ public Commit BaseVersionSource { get; private set; }
+ }
+}
\ No newline at end of file
diff --git a/GitVersionCore/VersionCalculation/BaseVersionCalculators/ConfigNextVersionBaseVersionStrategy.cs b/GitVersionCore/VersionCalculation/BaseVersionCalculators/ConfigNextVersionBaseVersionStrategy.cs
new file mode 100644
index 0000000000..cd1f907ec1
--- /dev/null
+++ b/GitVersionCore/VersionCalculation/BaseVersionCalculators/ConfigNextVersionBaseVersionStrategy.cs
@@ -0,0 +1,12 @@
+namespace GitVersion.VersionCalculation.BaseVersionCalculators
+{
+ public class ConfigNextVersionBaseVersionStrategy : BaseVersionStrategy
+ {
+ public override BaseVersion GetVersion(GitVersionContext context)
+ {
+ if (string.IsNullOrEmpty(context.Configuration.NextVersion))
+ return null;
+ return new BaseVersion(false, SemanticVersion.Parse(context.Configuration.NextVersion, context.Configuration.GitTagPrefix), null);
+ }
+ }
+}
\ No newline at end of file
diff --git a/GitVersionCore/VersionCalculation/BaseVersionCalculators/LastTagBaseVersionStrategy.cs b/GitVersionCore/VersionCalculation/BaseVersionCalculators/LastTagBaseVersionStrategy.cs
new file mode 100644
index 0000000000..a3a6749196
--- /dev/null
+++ b/GitVersionCore/VersionCalculation/BaseVersionCalculators/LastTagBaseVersionStrategy.cs
@@ -0,0 +1,17 @@
+namespace GitVersion.VersionCalculation.BaseVersionCalculators
+{
+ public class LastTagBaseVersionStrategy : BaseVersionStrategy
+ {
+ public override BaseVersion GetVersion(GitVersionContext context)
+ {
+ VersionTaggedCommit version;
+ if (new LastTaggedReleaseFinder(context).GetVersion(out version))
+ {
+ var shouldIncrement = version.Commit != context.CurrentCommit;
+ return new BaseVersion(shouldIncrement, version.SemVer, version.Commit);
+ }
+
+ return null;
+ }
+ }
+}
\ No newline at end of file
diff --git a/GitVersionCore/VersionCalculation/BaseVersionCalculators/MergeMessageBaseVersionStrategy.cs b/GitVersionCore/VersionCalculation/BaseVersionCalculators/MergeMessageBaseVersionStrategy.cs
new file mode 100644
index 0000000000..44af2a1865
--- /dev/null
+++ b/GitVersionCore/VersionCalculation/BaseVersionCalculators/MergeMessageBaseVersionStrategy.cs
@@ -0,0 +1,17 @@
+namespace GitVersion.VersionCalculation.BaseVersionCalculators
+{
+ public class MergeMessageBaseVersionStrategy : BaseVersionStrategy
+ {
+ public override BaseVersion GetVersion(GitVersionContext context)
+ {
+ foreach (var commit in context.CurrentBranch.CommitsPriorToThan(context.CurrentCommit.When()))
+ {
+ SemanticVersion semanticVersion;
+ // TODO when this approach works, inline the other class into here
+ if (MergeMessageParser.TryParse(context.CurrentCommit, context.Configuration, out semanticVersion))
+ return new BaseVersion(true, semanticVersion, commit);
+ }
+ return null;
+ }
+ }
+}
\ No newline at end of file
diff --git a/GitVersionCore/VersionCalculation/BaseVersionCalculators/VersionInBranchBaseVersionStrategy.cs b/GitVersionCore/VersionCalculation/BaseVersionCalculators/VersionInBranchBaseVersionStrategy.cs
new file mode 100644
index 0000000000..1f384f7131
--- /dev/null
+++ b/GitVersionCore/VersionCalculation/BaseVersionCalculators/VersionInBranchBaseVersionStrategy.cs
@@ -0,0 +1,35 @@
+namespace GitVersion.VersionCalculation.BaseVersionCalculators
+{
+ using System;
+ using System.Linq;
+
+ public class VersionInBranchBaseVersionStrategy : BaseVersionStrategy
+ {
+ public override BaseVersion GetVersion(GitVersionContext context)
+ {
+ var versionInBranch = GetVersionInBranch(context);
+ if (versionInBranch != null)
+ {
+ var firstCommitOfBranch = context.CurrentBranch.Commits.Last();
+ return new BaseVersion(false, versionInBranch.Item2, firstCommitOfBranch);
+ }
+
+ return null;
+ }
+
+ Tuple GetVersionInBranch(GitVersionContext context)
+ {
+ var branchParts = context.CurrentBranch.Name.Split('/', '-');
+ foreach (var part in branchParts)
+ {
+ SemanticVersion semanticVersion;
+ if (SemanticVersion.TryParse(part, context.Configuration.GitTagPrefix, out semanticVersion))
+ {
+ return Tuple.Create(part, semanticVersion);
+ }
+ }
+
+ return null;
+ }
+ }
+}
\ No newline at end of file
diff --git a/GitVersionCore/VersionCalculation/BaseVersionStrategy.cs b/GitVersionCore/VersionCalculation/BaseVersionStrategy.cs
new file mode 100644
index 0000000000..855d4cbc3a
--- /dev/null
+++ b/GitVersionCore/VersionCalculation/BaseVersionStrategy.cs
@@ -0,0 +1,9 @@
+namespace GitVersion.VersionCalculation
+{
+ using GitVersion.VersionCalculation.BaseVersionCalculators;
+
+ public abstract class BaseVersionStrategy
+ {
+ public abstract BaseVersion GetVersion(GitVersionContext context);
+ }
+}
\ No newline at end of file
diff --git a/GitVersionCore/VersionCalculation/IBaseVersionCalculator.cs b/GitVersionCore/VersionCalculation/IBaseVersionCalculator.cs
new file mode 100644
index 0000000000..b6e8f3d67a
--- /dev/null
+++ b/GitVersionCore/VersionCalculation/IBaseVersionCalculator.cs
@@ -0,0 +1,9 @@
+namespace GitVersion.VersionCalculation
+{
+ using GitVersion.VersionCalculation.BaseVersionCalculators;
+
+ public interface IBaseVersionCalculator
+ {
+ BaseVersion GetBaseVersion(GitVersionContext context);
+ }
+}
\ No newline at end of file
diff --git a/GitVersionCore/VersionCalculation/IMetaDataCalculator.cs b/GitVersionCore/VersionCalculation/IMetaDataCalculator.cs
new file mode 100644
index 0000000000..967baf8528
--- /dev/null
+++ b/GitVersionCore/VersionCalculation/IMetaDataCalculator.cs
@@ -0,0 +1,9 @@
+namespace GitVersion.VersionCalculation
+{
+ using LibGit2Sharp;
+
+ public interface IMetaDataCalculator
+ {
+ SemanticVersionBuildMetaData Create(Commit baseVersionSource, GitVersionContext context);
+ }
+}
\ No newline at end of file
diff --git a/GitVersionCore/VersionCalculation/MetaDataCalculator.cs b/GitVersionCore/VersionCalculation/MetaDataCalculator.cs
new file mode 100644
index 0000000000..ac0f76bb32
--- /dev/null
+++ b/GitVersionCore/VersionCalculation/MetaDataCalculator.cs
@@ -0,0 +1,26 @@
+namespace GitVersion.VersionCalculation
+{
+ using System.Linq;
+ using LibGit2Sharp;
+
+ public class MetaDataCalculator : IMetaDataCalculator
+ {
+ public SemanticVersionBuildMetaData Create(Commit baseVersionSource, GitVersionContext context)
+ {
+ var qf = new CommitFilter
+ {
+ Since = baseVersionSource,
+ Until = context.CurrentCommit,
+ SortBy = CommitSortStrategies.Topological | CommitSortStrategies.Time
+ };
+
+ var commitsSinceTag = context.Repository.Commits.QueryBy(qf).Count();
+
+ return new SemanticVersionBuildMetaData(
+ commitsSinceTag,
+ context.CurrentBranch.Name,
+ context.CurrentCommit.Sha,
+ context.CurrentCommit.When());
+ }
+ }
+}
\ No newline at end of file
diff --git a/GitVersionCore/VersionCalculation/NewNextVersionCalculator.cs b/GitVersionCore/VersionCalculation/NewNextVersionCalculator.cs
new file mode 100644
index 0000000000..d5f2ec7c37
--- /dev/null
+++ b/GitVersionCore/VersionCalculation/NewNextVersionCalculator.cs
@@ -0,0 +1,69 @@
+namespace GitVersion.VersionCalculation
+{
+ using System;
+ using BaseVersionCalculators;
+
+ public class NewNextVersionCalculator
+ {
+ IBaseVersionCalculator baseVersionFinder;
+ IMetaDataCalculator metaDataCalculator;
+
+ public NewNextVersionCalculator(IBaseVersionCalculator baseVersionCalculator = null, IMetaDataCalculator metaDataCalculator = null)
+ {
+ this.metaDataCalculator = metaDataCalculator ?? new MetaDataCalculator();
+ baseVersionFinder = baseVersionCalculator ??
+ new BaseVersionCalculator(
+ new ConfigNextVersionBaseVersionStrategy(),
+ new LastTagBaseVersionStrategy(),
+ new MergeMessageBaseVersionStrategy(),
+ new VersionInBranchBaseVersionStrategy());
+ }
+
+ public SemanticVersion FindVersion(GitVersionContext context)
+ {
+ var baseVersion = baseVersionFinder.GetBaseVersion(context);
+
+ if (baseVersion.ShouldIncrement) IncrementVersion(context, baseVersion);
+
+ if (!baseVersion.SemanticVersion.PreReleaseTag.HasTag() && !string.IsNullOrEmpty(context.Configuration.Tag))
+ {
+ baseVersion.SemanticVersion.PreReleaseTag = new SemanticVersionPreReleaseTag(context.Configuration.Tag, 1);
+ }
+
+ baseVersion.SemanticVersion.BuildMetaData = metaDataCalculator.Create(baseVersion.BaseVersionSource, context);
+
+ return baseVersion.SemanticVersion;
+ }
+
+ static void IncrementVersion(GitVersionContext context, BaseVersion baseVersion)
+ {
+ if (!baseVersion.SemanticVersion.PreReleaseTag.HasTag())
+ {
+ switch (context.Configuration.Increment)
+ {
+ case IncrementStrategy.None:
+ break;
+ case IncrementStrategy.Major:
+ baseVersion.SemanticVersion.Major++;
+ break;
+ case IncrementStrategy.Minor:
+ baseVersion.SemanticVersion.Minor++;
+ break;
+ case IncrementStrategy.Patch:
+ baseVersion.SemanticVersion.Patch++;
+ break;
+ default:
+ throw new ArgumentOutOfRangeException();
+ }
+ }
+ else
+ {
+ if (baseVersion.SemanticVersion.PreReleaseTag.Number != null)
+ {
+ baseVersion.SemanticVersion.PreReleaseTag.Number = baseVersion.SemanticVersion.PreReleaseTag.Number;
+ baseVersion.SemanticVersion.PreReleaseTag.Number++;
+ }
+ }
+ }
+ }
+}
\ No newline at end of file