Skip to content

Commit d9d3f0a

Browse files
committed
Initial prototype of mainline development working
1 parent e1f3576 commit d9d3f0a

File tree

6 files changed

+149
-11
lines changed

6 files changed

+149
-11
lines changed

src/GitVersionCore.Tests/GitVersionCore.Tests.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,7 @@
113113
<Compile Include="ConfigProviderTests.cs" />
114114
<Compile Include="GitVersionContextTests.cs" />
115115
<Compile Include="Helpers\DirectoryHelper.cs" />
116+
<Compile Include="IntegrationTests\MainlineDevelopmentMode.cs" />
116117
<Compile Include="Mocks\MockThreadSleep.cs" />
117118
<Compile Include="OperationWithExponentialBackoffTests.cs" />
118119
<Compile Include="Init\InitScenarios.cs" />
Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
using System;
2+
using System.Diagnostics;
3+
using GitTools;
4+
using GitTools.Testing;
5+
using GitVersion;
6+
using GitVersionCore.Tests;
7+
using NUnit.Framework;
8+
using Shouldly;
9+
10+
public class MainlineDevelopmentMode
11+
{
12+
private Config config = new Config
13+
{
14+
Branches =
15+
{
16+
{
17+
"master", new BranchConfig
18+
{
19+
VersioningMode = VersioningMode.Mainline
20+
}
21+
}
22+
}
23+
};
24+
25+
26+
[Test]
27+
public void CannotSetMainlineDevelopmentAtAGlobalLevel()
28+
{
29+
using (var fixture = new EmptyRepositoryFixture())
30+
{
31+
Should.Throw<NotSupportedException>(() =>
32+
fixture.AssertFullSemver(new Config
33+
{
34+
VersioningMode = VersioningMode.Mainline
35+
}, ""));
36+
}
37+
}
38+
39+
[Test]
40+
public void MergedFeatureBranchesToMasterImpliesRelease()
41+
{
42+
using (var fixture = new EmptyRepositoryFixture())
43+
{
44+
fixture.Repository.MakeACommit("1");
45+
fixture.MakeACommit();
46+
47+
fixture.BranchTo("feature/foo");
48+
fixture.Repository.MakeACommit("2");
49+
fixture.Checkout("master");
50+
fixture.MergeNoFF("feature/foo");
51+
52+
fixture.AssertFullSemver(config, "0.1.1+3");
53+
54+
fixture.BranchTo("feature/foo2");
55+
fixture.Repository.MakeACommit("3 +semver: minor");
56+
fixture.Checkout("master");
57+
fixture.MergeNoFF("feature/foo2");
58+
fixture.AssertFullSemver(config, "0.2.0+5");
59+
60+
fixture.BranchTo("feature/foo3");
61+
fixture.Repository.MakeACommit("4 +semver: minor");
62+
fixture.Checkout("master");
63+
fixture.MergeNoFF("feature/foo3");
64+
fixture.AssertFullSemver(config, "0.3.0+7");
65+
66+
fixture.BranchTo("feature/foo4");
67+
fixture.Repository.MakeACommit("5 +semver: major");
68+
fixture.Checkout("master");
69+
fixture.MergeNoFF("feature/foo4");
70+
fixture.AssertFullSemver(config, "1.0.0+9");
71+
}
72+
}
73+
74+
// Write test which has a forward merge into a feature branch
75+
}

src/GitVersionCore/IncrementStrategyFinder.cs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,11 @@ public static class IncrementStrategyFinder
6161
commits = commits.Where(c => c.Parents.Count() > 1);
6262
}
6363

64+
return GetIncrementForCommits(context, commits);
65+
}
66+
67+
public static VersionField? GetIncrementForCommits(GitVersionContext context, IEnumerable<Commit> commits)
68+
{
6469
var majorRegex = CreateRegex(context.Configuration.MajorVersionBumpMessage ?? DefaultMajorPattern);
6570
var minorRegex = CreateRegex(context.Configuration.MinorVersionBumpMessage ?? DefaultMinorPattern);
6671
var patchRegex = CreateRegex(context.Configuration.PatchVersionBumpMessage ?? DefaultPatchPattern);
@@ -78,7 +83,7 @@ public static class IncrementStrategyFinder
7883

7984
return null;
8085
}
81-
86+
8287
private static IEnumerable<Commit> GetIntermediateCommits(IRepository repo, Commit baseCommit, Commit headCommit)
8388
{
8489
if (baseCommit == null) yield break;

src/GitVersionCore/LibGitExtensions.cs

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -85,15 +85,16 @@ public static Commit FindMergeBase(this Branch branch, Branch otherBranch, IRepo
8585
{
8686
// Otherbranch tip is a forward merge
8787
var commitToFindCommonBase = otherBranch.Tip;
88-
if (otherBranch.Tip.Parents.Contains(branch.Tip))
88+
var commit = branch.Tip;
89+
if (otherBranch.Tip.Parents.Contains(commit))
8990
{
9091
commitToFindCommonBase = otherBranch.Tip.Parents.First();
9192
}
9293

93-
var findMergeBase = repository.ObjectDatabase.FindMergeBase(branch.Tip, commitToFindCommonBase);
94+
var findMergeBase = repository.ObjectDatabase.FindMergeBase(commit, commitToFindCommonBase);
9495
if (findMergeBase != null)
9596
{
96-
Logger.WriteInfo(string.Format("Found merge base of {0} against {1}", findMergeBase.Sha, otherBranch.FriendlyName));
97+
Logger.WriteInfo(string.Format("Found merge base of {0}", findMergeBase.Sha));
9798
// We do not want to include merge base commits which got forward merged into the other branch
9899
bool mergeBaseWasFowardMerge;
99100
do
@@ -106,7 +107,7 @@ public static Commit FindMergeBase(this Branch branch, Branch otherBranch, IRepo
106107
if (mergeBaseWasFowardMerge)
107108
{
108109
var second = commitToFindCommonBase.Parents.First();
109-
var mergeBase = repository.ObjectDatabase.FindMergeBase(branch.Tip, second);
110+
var mergeBase = repository.ObjectDatabase.FindMergeBase(commit, second);
110111
if (mergeBase == findMergeBase)
111112
{
112113
break;

src/GitVersionCore/VersionCalculation/NextVersionCalculator.cs

Lines changed: 60 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
11
namespace GitVersion.VersionCalculation
22
{
3+
using System;
34
using System.Linq;
45
using System.Text.RegularExpressions;
56
using BaseVersionCalculators;
7+
using LibGit2Sharp;
68

79
public class NextVersionCalculator
810
{
@@ -41,12 +43,19 @@ public SemanticVersion FindVersion(GitVersionContext context)
4143

4244
var baseVersion = baseVersionFinder.GetBaseVersion(context);
4345
var semver = baseVersion.SemanticVersion;
44-
var increment = IncrementStrategyFinder.DetermineIncrementedField(context, baseVersion);
45-
if (increment != null)
46+
if (context.Configuration.VersioningMode == VersioningMode.Mainline)
4647
{
47-
semver = semver.IncrementVersion(increment.Value);
48+
semver = FindMainlineModeVersion(baseVersion, context);
49+
}
50+
else
51+
{
52+
var increment = IncrementStrategyFinder.DetermineIncrementedField(context, baseVersion);
53+
if (increment != null)
54+
{
55+
semver = semver.IncrementVersion(increment.Value);
56+
}
57+
else Logger.WriteInfo("Skipping version increment");
4858
}
49-
else Logger.WriteInfo("Skipping version increment");
5059

5160
if (!semver.PreReleaseTag.HasTag() && !string.IsNullOrEmpty(context.Configuration.Tag))
5261
{
@@ -64,6 +73,52 @@ public SemanticVersion FindVersion(GitVersionContext context)
6473
return taggedSemanticVersion ?? semver;
6574
}
6675

76+
private SemanticVersion FindMainlineModeVersion(BaseVersion baseVersion, GitVersionContext context)
77+
{
78+
if (baseVersion.SemanticVersion.PreReleaseTag.HasTag())
79+
{
80+
throw new NotSupportedException("Mainline development mode doesn't yet support pre-release tags on master");
81+
}
82+
Logger.WriteInfo("Using mainline development mode to calculate current version");
83+
var commitLog = context.Repository.Commits.QueryBy(new CommitFilter
84+
{
85+
IncludeReachableFrom = context.CurrentBranch,
86+
ExcludeReachableFrom = baseVersion.BaseVersionSource,
87+
SortBy = CommitSortStrategies.Reverse
88+
}).ToList();
89+
var mergeCommits = commitLog
90+
.Where(l => l.Parents.Count() > 1)
91+
.ToList();
92+
return mergeCommits
93+
.Select(mc =>
94+
{
95+
var mergedHead = GetMergedHead(mc);
96+
var findMergeBase = context.Repository.ObjectDatabase.FindMergeBase(mc.Parents.First(), mergedHead);
97+
var filter = new CommitFilter
98+
{
99+
IncludeReachableFrom = mergedHead,
100+
ExcludeReachableFrom = findMergeBase
101+
};
102+
var mergedCommits = context.Repository.Commits.QueryBy(filter).ToList();
103+
return new
104+
{
105+
MergeCommit = mc,
106+
MergeHead = mergedHead,
107+
MergeBase = findMergeBase,
108+
Increment = IncrementStrategyFinder.GetIncrementForCommits(context, mergedCommits)
109+
};
110+
})
111+
.Aggregate(baseVersion.SemanticVersion, (v, i) => v.IncrementVersion(i.Increment ?? VersionField.Patch));
112+
}
113+
114+
private Commit GetMergedHead(Commit mergeCommit)
115+
{
116+
var parents = mergeCommit.Parents.Skip(1).ToList();
117+
if (parents.Count > 1)
118+
throw new NotSupportedException("Mainline development does not support more than one merge source in a single commit yet");
119+
return parents.Single();
120+
}
121+
67122
void UpdatePreReleaseTag(GitVersionContext context, SemanticVersion semanticVersion, string branchNameOverride)
68123
{
69124
var tagToUse = GetBranchSpecificTag(context.Configuration, context.CurrentBranch.FriendlyName, branchNameOverride);
@@ -78,7 +133,7 @@ void UpdatePreReleaseTag(GitVersionContext context, SemanticVersion semanticVers
78133
number = int.Parse(numberGroup.Value);
79134
}
80135
}
81-
136+
82137
var lastTag = context.CurrentBranch
83138
.GetVersionTagsOnBranch(context.Repository, context.Configuration.GitTagPrefix)
84139
.FirstOrDefault(v => v.PreReleaseTag.Name == tagToUse);

src/GitVersionCore/VersioningModes/VersioningMode.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
public enum VersioningMode
44
{
55
ContinuousDelivery,
6-
ContinuousDeployment
6+
ContinuousDeployment,
7+
Mainline
78
}
89
}

0 commit comments

Comments
 (0)