Skip to content

Commit e5e9abb

Browse files
committed
Base version commit counting source now takes oldest source which would produce the same version
This fixes #465
1 parent 7f8f8fe commit e5e9abb

21 files changed

+154
-137
lines changed

GitVersionCore.Tests/GitVersionCore.Tests.csproj

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -127,7 +127,6 @@
127127
<Compile Include="VersionCalculation\NextVersionCalculatorTests.cs" />
128128
<Compile Include="VersionCalculation\Strategies\ConfigNextVersionBaseVersionStrategyTests.cs" />
129129
<Compile Include="GitVersionContextBuilder.cs" />
130-
<Compile Include="VersionCalculation\Strategies\LastTagBaseVersionStrategyTests.cs" />
131130
<Compile Include="VersionCalculation\Strategies\MergeMessageBaseVersionStrategyTests.cs" />
132131
<Compile Include="VersionCalculation\Strategies\VersionInBranchBaseVersionStrategyTests.cs" />
133132
<Compile Include="VersionCalculation\TestBaseVersionCalculator.cs" />

GitVersionCore.Tests/IntegrationTests/HotfixBranchScenarios.cs

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -13,20 +13,20 @@ public void PatchLatestReleaseExample()
1313
// create hotfix
1414
fixture.Repository.CreateBranch("hotfix-1.2.1").Checkout();
1515

16-
fixture.AssertFullSemver("1.2.1-beta.1+0");
17-
fixture.Repository.MakeACommit();
1816
fixture.AssertFullSemver("1.2.1-beta.1+1");
17+
fixture.Repository.MakeACommit();
18+
fixture.AssertFullSemver("1.2.1-beta.1+2");
1919
fixture.Repository.ApplyTag("1.2.1-beta.1");
2020
fixture.AssertFullSemver("1.2.1-beta.1");
2121
fixture.Repository.MakeACommit();
22-
fixture.AssertFullSemver("1.2.1-beta.2+2");
22+
fixture.AssertFullSemver("1.2.1-beta.2+3");
2323

2424
// Merge hotfix branch to master
2525
fixture.Repository.Checkout("master");
2626

2727

2828
fixture.Repository.MergeNoFF("hotfix-1.2.1", Constants.SignatureNow());
29-
fixture.AssertFullSemver("1.2.1+0");
29+
fixture.AssertFullSemver("1.2.1+4");
3030

3131
fixture.Repository.ApplyTag("1.2.1");
3232
fixture.AssertFullSemver("1.2.1");
@@ -36,7 +36,7 @@ public void PatchLatestReleaseExample()
3636
fixture.AssertFullSemver("1.3.0-unstable.1");
3737

3838
fixture.Repository.MergeNoFF("hotfix-1.2.1", Constants.SignatureNow());
39-
fixture.AssertFullSemver("1.3.0-unstable.0");
39+
fixture.AssertFullSemver("1.3.0-unstable.4");
4040
}
4141
}
4242

@@ -73,12 +73,12 @@ public void PatchOlderReleaseExample()
7373
fixture.AssertFullSemver("1.1.1-PullRequest.2+4");
7474
fixture.Repository.Checkout("hotfix-1.1.1");
7575
fixture.Repository.MergeNoFF("feature/fix", Constants.SignatureNow());
76-
fixture.AssertFullSemver("1.1.1-beta.1+1");
76+
fixture.AssertFullSemver("1.1.1-beta.1+4");
7777

7878
// Merge hotfix into support branch to complete hotfix
7979
fixture.Repository.Checkout("support-1.1");
8080
fixture.Repository.MergeNoFF("hotfix-1.1.1", Constants.SignatureNow());
81-
fixture.AssertFullSemver("1.1.1+0");
81+
fixture.AssertFullSemver("1.1.1+5");
8282
fixture.Repository.ApplyTag("1.1.1");
8383
fixture.AssertFullSemver("1.1.1");
8484

GitVersionCore.Tests/IntegrationTests/ReleaseBranchScenarios.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,11 +47,12 @@ public void NoMergeBacksToDevelopInCaseThereAreChangesInReleaseBranch()
4747
// Merge to develop
4848
fixture.Repository.Checkout("develop");
4949
fixture.Repository.MergeNoFF("release/1.0.0");
50+
fixture.AssertFullSemver("1.1.0-unstable.1");
5051

5152
fixture.Repository.MakeACommit();
5253
fixture.Repository.Branches.Remove(releaseBranch);
5354

54-
fixture.AssertFullSemver("1.1.0-unstable.1");
55+
fixture.AssertFullSemver("1.1.0-unstable.2");
5556
}
5657
}
5758

GitVersionCore.Tests/IntegrationTests/SupportBranchScenarios.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ public void SupportIsCalculatedCorrectly()
4646
fixture.AssertFullSemver("1.2.1-beta.1+1");
4747
fixture.Repository.Checkout("support/1.0.0");
4848
fixture.Repository.MergeNoFF("hotfix/1.2.1");
49-
fixture.AssertFullSemver("1.2.1+0");
49+
fixture.AssertFullSemver("1.2.1+2");
5050
}
5151
}
5252

GitVersionCore.Tests/IntegrationTests/UncycloScenarios.cs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -88,8 +88,10 @@ public void MinorReleaseExample()
8888

8989
// Verify develop version
9090
fixture.Repository.Checkout("develop");
91+
fixture.AssertFullSemver("1.3.0-unstable.4");
9192
fixture.Repository.MergeNoFF("release-1.3.0", Constants.SignatureNow());
92-
fixture.AssertFullSemver("1.4.0-unstable.0");
93+
// Not 0 for commit count as we can't know the increment rules of the merged branch
94+
fixture.AssertFullSemver("1.4.0-unstable.2");
9395
}
9496
}
9597
}

GitVersionCore.Tests/Mocks/MockQueryableCommitLog.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,12 +29,12 @@ public CommitSortStrategies SortedBy
2929

3030
public ICommitLog QueryBy(CommitFilter filter)
3131
{
32-
throw new NotImplementedException();
32+
return this;
3333
}
3434

3535
public Commit FindMergeBase(Commit first, Commit second)
3636
{
37-
throw new NotImplementedException();
37+
return null;
3838
}
3939

4040
public Commit FindMergeBase(IEnumerable<Commit> commits, MergeBaseFindingStrategy strategy)

GitVersionCore.Tests/VersionCalculation/BaseVersionCalculatorTests.cs

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
namespace GitVersionCore.Tests.VersionCalculation
22
{
33
using System;
4+
using System.Collections.Generic;
45
using GitVersion;
56
using GitVersion.VersionCalculation;
67
using GitVersion.VersionCalculation.BaseVersionCalculators;
@@ -62,9 +63,9 @@ public V1Strategy(DateTimeOffset? when)
6263
this.when = when == null ? null : new MockCommit { CommitterEx = when.Value.ToSignature() };
6364
}
6465

65-
public override BaseVersion GetVersion(GitVersionContext context)
66+
public override IEnumerable<BaseVersion> GetVersions(GitVersionContext context)
6667
{
67-
return new BaseVersion("Source 1", false, new SemanticVersion(1), when, null);
68+
yield return new BaseVersion("Source 1", false, new SemanticVersion(1), when, null);
6869
}
6970
}
7071

@@ -77,9 +78,9 @@ public V2Strategy(DateTimeOffset? when)
7778
this.when = when == null ? null : new MockCommit { CommitterEx = when.Value.ToSignature() };
7879
}
7980

80-
public override BaseVersion GetVersion(GitVersionContext context)
81+
public override IEnumerable<BaseVersion> GetVersions(GitVersionContext context)
8182
{
82-
return new BaseVersion("Source 2", true, new SemanticVersion(2), when, null);
83+
yield return new BaseVersion("Source 2", true, new SemanticVersion(2), when, null);
8384
}
8485
}
8586
}

GitVersionCore.Tests/VersionCalculation/Strategies/ConfigNextVersionBaseVersionStrategyTests.cs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
namespace GitVersionCore.Tests.VersionCalculation.Strategies
22
{
3+
using System.Linq;
34
using GitVersion;
45
using GitVersion.VersionCalculation.BaseVersionCalculators;
56
using NUnit.Framework;
@@ -18,7 +19,7 @@ public void ShouldNotBeIncremented()
1819
});
1920
var sut = new ConfigNextVersionBaseVersionStrategy();
2021

21-
var baseVersion = sut.GetVersion(contextBuilder.Build());
22+
var baseVersion = sut.GetVersions(contextBuilder.Build()).Single();
2223

2324
baseVersion.ShouldIncrement.ShouldBe(false);
2425
baseVersion.SemanticVersion.ToString().ShouldBe("1.0.0");
@@ -30,7 +31,7 @@ public void ReturnsNullWhenNoNextVersionIsInConfig()
3031
var contextBuilder = new GitVersionContextBuilder();
3132
var sut = new ConfigNextVersionBaseVersionStrategy();
3233

33-
var baseVersion = sut.GetVersion(contextBuilder.Build());
34+
var baseVersion = sut.GetVersions(contextBuilder.Build()).SingleOrDefault();
3435

3536
baseVersion.ShouldBe(null);
3637
}

GitVersionCore.Tests/VersionCalculation/Strategies/LastTagBaseVersionStrategyTests.cs

Lines changed: 0 additions & 37 deletions
This file was deleted.

GitVersionCore.Tests/VersionCalculation/Strategies/MergeMessageBaseVersionStrategyTests.cs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
namespace GitVersionCore.Tests.VersionCalculation.Strategies
22
{
33
using System.Collections.Generic;
4+
using System.Linq;
45
using GitVersion.VersionCalculation.BaseVersionCalculators;
56
using LibGit2Sharp;
67
using NUnit.Framework;
@@ -24,7 +25,7 @@ public void ShouldNotAllowIncrementOfVersion()
2425
}).Build();
2526
var sut = new MergeMessageBaseVersionStrategy();
2627

27-
var baseVersion = sut.GetVersion(context);
28+
var baseVersion = sut.GetVersions(context).Single();
2829

2930
baseVersion.ShouldIncrement.ShouldBe(false);
3031
}
@@ -109,7 +110,7 @@ static void AssertMergeMessage(string message, string expectedVersion, List<Comm
109110
.Build();
110111
var sut = new MergeMessageBaseVersionStrategy();
111112

112-
var baseVersion = sut.GetVersion(context);
113+
var baseVersion = sut.GetVersions(context).SingleOrDefault();
113114

114115
if (expectedVersion == null)
115116
{

GitVersionCore.Tests/VersionCalculation/Strategies/VersionInBranchBaseVersionStrategyTests.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
namespace GitVersionCore.Tests.VersionCalculation.Strategies
22
{
3+
using System.Linq;
34
using GitVersion;
45
using GitVersion.VersionCalculation.BaseVersionCalculators;
56
using LibGit2Sharp;
@@ -25,7 +26,7 @@ public void CanTakeVersionFromBranchName(string branchName, string expectedBaseV
2526
var branch = fixture.Repository.CreateBranch(branchName);
2627
var sut = new VersionInBranchBaseVersionStrategy();
2728

28-
var baseVersion = sut.GetVersion(new GitVersionContext(fixture.Repository, branch, configuration));
29+
var baseVersion = sut.GetVersions(new GitVersionContext(fixture.Repository, branch, configuration)).SingleOrDefault();
2930

3031
if (expectedBaseVersion == null)
3132
baseVersion.ShouldBe(null);

GitVersionCore/LibGitExtensions.cs

Lines changed: 33 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -24,20 +24,43 @@ public static Branch FindBranch(this IRepository repository, string branchName)
2424
return repository.Branches.FirstOrDefault(x => x.Name == "origin/" + branchName);
2525
}
2626

27+
public static SemanticVersion LastVersionTagOnBranch(this Branch branch, IRepository repository, string tagPrefixRegex)
28+
{
29+
var tags = repository.Tags.Select(t => t).ToList();
30+
var until = FindCommitBranchWasBranchedFrom(branch, repository);
31+
32+
return repository.Commits.QueryBy(new CommitFilter
33+
{
34+
Since = branch.Tip,
35+
Until = until
36+
})
37+
.SelectMany(c => tags.Where(t => c.Sha == t.Target.Sha).SelectMany(t =>
38+
{
39+
SemanticVersion semver;
40+
if (SemanticVersion.TryParse(t.Name, tagPrefixRegex, out semver))
41+
return new [] { semver };
42+
return new SemanticVersion[0];
43+
}))
44+
.FirstOrDefault();
45+
}
46+
2747
public static Commit FindCommitBranchWasBranchedFrom(this Branch branch, IRepository repository, params Branch[] excludedBranches)
2848
{
29-
var otherBranches = repository.Branches.Except(excludedBranches).Where(b => IsSameBranch(branch, b)).ToList();
30-
var mergeBases = otherBranches.Select(b =>
49+
using (Logger.IndentLog("Finding branch source"))
3150
{
32-
var otherCommit = b.Tip;
33-
if (b.Tip.Parents.Contains(branch.Tip))
51+
var otherBranches = repository.Branches.Except(excludedBranches).Where(b => IsSameBranch(branch, b)).ToList();
52+
var mergeBases = otherBranches.Select(b =>
3453
{
35-
otherCommit = b.Tip.Parents.First();
36-
}
37-
var mergeBase = repository.Commits.FindMergeBase(otherCommit, branch.Tip);
38-
return mergeBase;
39-
}).Where(b => b != null).ToList();
40-
return mergeBases.OrderByDescending(b => b.Committer.When).FirstOrDefault();
54+
var otherCommit = b.Tip;
55+
if (b.Tip.Parents.Contains(branch.Tip))
56+
{
57+
otherCommit = b.Tip.Parents.First();
58+
}
59+
var mergeBase = repository.Commits.FindMergeBase(otherCommit, branch.Tip);
60+
return mergeBase;
61+
}).Where(b => b != null).ToList();
62+
return mergeBases.OrderByDescending(b => b.Committer.When).FirstOrDefault();
63+
}
4164
}
4265

4366
static bool IsSameBranch(Branch branch, Branch b)
Lines changed: 41 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
namespace GitVersion.VersionCalculation
22
{
3+
using System;
34
using System.Linq;
4-
using BaseVersionCalculators;
5+
using GitVersion.VersionCalculation.BaseVersionCalculators;
56

67
public class BaseVersionCalculator : IBaseVersionCalculator
78
{
@@ -16,8 +17,8 @@ public BaseVersion GetBaseVersion(GitVersionContext context)
1617
{
1718
using (Logger.IndentLog("Calculating base versions"))
1819
{
19-
var baseVersion = strategies
20-
.Select(s => s.GetVersion(context))
20+
var baseVersions = strategies
21+
.SelectMany(s => s.GetVersions(context))
2122
.Where(v =>
2223
{
2324
if (v != null)
@@ -28,20 +29,48 @@ public BaseVersion GetBaseVersion(GitVersionContext context)
2829

2930
return false;
3031
})
31-
.Aggregate((v1, v2) =>
32+
.ToList();
33+
34+
var maxVersion = baseVersions.Aggregate((v1, v2) =>
35+
{
36+
if (v1.SemanticVersion > v2.SemanticVersion)
3237
{
33-
if (v1.SemanticVersion > v2.SemanticVersion)
34-
{
35-
return new BaseVersion(v1.Source, v1.ShouldIncrement, v1.SemanticVersion, v1.BaseVersionSource ?? v2.BaseVersionSource, v1.BranchNameOverride);
36-
}
38+
return new BaseVersion(v1.Source, v1.ShouldIncrement, v1.SemanticVersion, v1.BaseVersionSource ?? v2.BaseVersionSource, v1.BranchNameOverride);
39+
}
40+
return new BaseVersion(v2.Source, v2.ShouldIncrement, v2.SemanticVersion, v2.BaseVersionSource ?? v1.BaseVersionSource, v2.BranchNameOverride);
41+
});
42+
var incrementedMax = MaybeIncrement(context, maxVersion);
43+
var matchingVersionsOnceIncremented = baseVersions.Where(b => b.BaseVersionSource != null && MaybeIncrement(context, b) == incrementedMax).ToList();
44+
BaseVersion baseVersionWithOldestSource;
45+
if (matchingVersionsOnceIncremented.Any())
46+
{
47+
baseVersionWithOldestSource = matchingVersionsOnceIncremented.Aggregate((v1, v2) => v1.BaseVersionSource.Committer.When < v2.BaseVersionSource.Committer.When ? v1 : v2);
48+
Logger.WriteInfo(string.Format(
49+
"Found multiple base versions which will produce the same SemVer ({0}), taking oldest source for commit counting ({1})",
50+
incrementedMax,
51+
baseVersionWithOldestSource.Source));
52+
}
53+
else
54+
{
55+
baseVersionWithOldestSource = maxVersion;
56+
}
57+
58+
if (baseVersionWithOldestSource.BaseVersionSource == null)
59+
throw new Exception("Base version should not be null");
3760

38-
return new BaseVersion(v2.Source, v2.ShouldIncrement, v2.SemanticVersion, v2.BaseVersionSource ?? v1.BaseVersionSource, v2.BranchNameOverride);
39-
});
61+
var calculatedBase = new BaseVersion(
62+
maxVersion.Source, maxVersion.ShouldIncrement, maxVersion.SemanticVersion,
63+
baseVersionWithOldestSource.BaseVersionSource, maxVersion.BranchNameOverride);
4064

41-
Logger.WriteInfo(string.Format("Base version used: {0}", baseVersion));
65+
Logger.WriteInfo(string.Format("Base version used: {0}", calculatedBase));
4266

43-
return baseVersion;
67+
return calculatedBase;
4468
}
4569
}
70+
71+
static SemanticVersion MaybeIncrement(GitVersionContext context, BaseVersion version)
72+
{
73+
return version.ShouldIncrement ? version.SemanticVersion.IncrementVersion(context.Configuration.Increment) : version.SemanticVersion;
74+
}
4675
}
4776
}
Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,15 @@
11
namespace GitVersion.VersionCalculation.BaseVersionCalculators
22
{
3+
using System.Collections.Generic;
4+
35
public class ConfigNextVersionBaseVersionStrategy : BaseVersionStrategy
46
{
5-
public override BaseVersion GetVersion(GitVersionContext context)
7+
public override IEnumerable<BaseVersion> GetVersions(GitVersionContext context)
68
{
79
if (string.IsNullOrEmpty(context.Configuration.NextVersion) || context.IsCurrentCommitTagged)
8-
return null;
10+
yield break;
911
var semanticVersion = SemanticVersion.Parse(context.Configuration.NextVersion, context.Configuration.GitTagPrefix);
10-
return new BaseVersion("NextVersion in GitVersionConfig.yaml", false, semanticVersion, null, null);
12+
yield return new BaseVersion("NextVersion in GitVersionConfig.yaml", false, semanticVersion, null, null);
1113
}
1214
}
1315
}

0 commit comments

Comments
 (0)