Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -63,9 +63,9 @@ public void GitFlowPullRequestBranch()
// Open Pull Request
fixture.BranchTo("pull/2/merge", "pr");
fixture.SequenceDiagram.Activate("pull/2/merge");
fixture.AssertFullSemver("1.3.0-PullRequest.2+1");
fixture.AssertFullSemver("1.3.0-PullRequest0002.1");
fixture.MakeACommit();
fixture.AssertFullSemver("1.3.0-PullRequest.2+2");
fixture.AssertFullSemver("1.3.0-PullRequest0002.2");

// Merge into develop
fixture.Checkout("develop");
Expand Down Expand Up @@ -365,9 +365,9 @@ public void GitHubFlowPullRequestBranch()
// Open Pull Request
fixture.BranchTo("pull/2/merge", "pr");
fixture.SequenceDiagram.Activate("pull/2/merge");
fixture.AssertFullSemver("1.2.1-PullRequest.2+1");
fixture.AssertFullSemver("1.2.1-PullRequest0002.1");
fixture.MakeACommit();
fixture.AssertFullSemver("1.2.1-PullRequest.2+2");
fixture.AssertFullSemver("1.2.1-PullRequest0002.2");

// Merge into master
fixture.Checkout("master");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -103,8 +103,8 @@ public void PatchOlderReleaseExample()
fixture.Repository.MakeACommit();
fixture.AssertFullSemver("1.1.1-fix.1+3");

fixture.Repository.CreatePullRequestRef("feature/fix", "hotfix-1.1.1", normalise: true);
fixture.AssertFullSemver("1.1.1-PullRequest.2+4");
fixture.Repository.CreatePullRequestRef("feature/fix", "hotfix-1.1.1", normalise: true, prNumber: 8);
fixture.AssertFullSemver("1.1.1-PullRequest0008.4");
fixture.Repository.Checkout("hotfix-1.1.1");
fixture.Repository.MergeNoFF("feature/fix", Generate.SignatureNow());
fixture.AssertFullSemver("1.1.1-beta.1+4");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
using GitVersionCore.Tests;
using LibGit2Sharp;
using NUnit.Framework;
using LibGitExtensions = GitTools.LibGitExtensions;

public class MainlineDevelopmentMode
{
Expand All @@ -24,18 +25,20 @@ public void MergedFeatureBranchesToMasterImpliesRelease()

fixture.BranchTo("feature/foo", "foo");
fixture.MakeACommit("2");
fixture.AssertFullSemver(config, "1.0.1-foo.1+1");
fixture.AssertFullSemver(config, "1.0.1-foo.1");
fixture.MakeACommit("2.1");
fixture.AssertFullSemver(config, "1.0.1-foo.2");
fixture.Checkout("master");
fixture.MergeNoFF("feature/foo");

fixture.AssertFullSemver(config, "1.0.1+2");
fixture.AssertFullSemver(config, "1.0.1");

fixture.BranchTo("feature/foo2", "foo2");
fixture.MakeACommit("3 +semver: minor");
fixture.AssertFullSemver(config, "1.1.0-foo2.1+3");
fixture.AssertFullSemver(config, "1.1.0-foo2.1");
fixture.Checkout("master");
fixture.MergeNoFF("feature/foo2");
fixture.AssertFullSemver(config, "1.1.0+4");
fixture.AssertFullSemver(config, "1.1.0");

fixture.BranchTo("feature/foo3", "foo3");
fixture.MakeACommit("4");
Expand All @@ -48,41 +51,82 @@ public void MergedFeatureBranchesToMasterImpliesRelease()
{
AmendPreviousCommit = true
});
fixture.AssertFullSemver(config, "1.2.0+6");
fixture.AssertFullSemver(config, "1.2.0");

fixture.BranchTo("feature/foo4", "foo4");
fixture.MakeACommit("5 +semver: major");
fixture.AssertFullSemver(config, "2.0.0-foo4.1+7");
fixture.AssertFullSemver(config, "2.0.0-foo4.1");
fixture.Checkout("master");
fixture.MergeNoFF("feature/foo4");
fixture.AssertFullSemver(config, "2.0.0+8");
fixture.AssertFullSemver(config, "2.0.0");

// We should evaluate any commits not included in merge commit calculations for direct commit/push or squash to merge commits
fixture.MakeACommit("6 +semver: major");
fixture.AssertFullSemver(config, "3.0.0+9");
fixture.AssertFullSemver(config, "3.0.0");
fixture.MakeACommit("7 +semver: minor");
fixture.AssertFullSemver(config, "3.1.0+10");
fixture.AssertFullSemver(config, "3.1.0");
fixture.MakeACommit("8");
fixture.AssertFullSemver(config, "3.1.1+11");
fixture.AssertFullSemver(config, "3.1.1");

// Finally verify that the merge commits still function properly
fixture.BranchTo("feature/foo5", "foo5");
fixture.MakeACommit("9 +semver: minor");
fixture.AssertFullSemver(config, "3.2.0-foo5.1+12");
fixture.AssertFullSemver(config, "3.2.0-foo5.1");
fixture.Checkout("master");
fixture.MergeNoFF("feature/foo5");
fixture.AssertFullSemver(config, "3.2.0+13");
fixture.AssertFullSemver(config, "3.2.0");

// One more direct commit for good measure
fixture.MakeACommit("10 +semver: minor");
fixture.AssertFullSemver(config, "3.3.0+14");
fixture.AssertFullSemver(config, "3.3.0");
// And we can commit without bumping semver
fixture.MakeACommit("11 +semver: none");
fixture.AssertFullSemver(config, "3.3.0+15");
fixture.AssertFullSemver(config, "3.3.0");
Console.WriteLine(fixture.SequenceDiagram.GetDiagram());
}
}
// Write test which has a forward merge into a feature branch

[Test]
public void VerifyPullRequestsActLikeContinuousDelivery()
{
using (var fixture = new EmptyRepositoryFixture())
{
fixture.Repository.MakeACommit("1");
fixture.MakeATaggedCommit("1.0.0");
fixture.MakeACommit();
fixture.AssertFullSemver(config, "1.0.1");

fixture.BranchTo("feature/foo", "foo");
fixture.MakeACommit();
fixture.MakeACommit();
fixture.Repository.CreatePullRequestRef("feature/foo", "master", normalise: true, prNumber: 8);
fixture.AssertFullSemver(config, "1.0.2-PullRequest0008.3");
}
}

[Test]
[Ignore("Not passing yet")]
public void VerifyForwardMerge()
{
using (var fixture = new EmptyRepositoryFixture())
{
fixture.Repository.MakeACommit("1");
fixture.MakeATaggedCommit("1.0.0");
fixture.MakeACommit(); // 1.0.1

fixture.BranchTo("feature/foo", "foo");
fixture.MakeACommit();
fixture.MakeACommit();
fixture.AssertFullSemver(config, "1.0.2-foo.2");

fixture.Checkout("master");
fixture.MakeACommit();
fixture.AssertFullSemver(config, "1.0.2");
fixture.Checkout("feature/foo");
fixture.MergeNoFF("master");
fixture.AssertFullSemver(config, "1.0.3-foo.3");
}
}
}

static class CommitExtensions
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ public void CanCalculatePullRequestChanges()
fixture.Repository.CreatePullRequestRef("feature/Foo", "master", normalise: true);

fixture.Repository.DumpGraph();
fixture.AssertFullSemver("0.1.1-PullRequest.2+2");
fixture.AssertFullSemver("0.1.1-PullRequest0002.2");
}
}

Expand All @@ -37,7 +37,7 @@ public void CanCalculatePullRequestChangesInheritingConfig()
fixture.Repository.CreatePullRequestRef("feature/Foo", "develop", 44, normalise: true);

fixture.Repository.DumpGraph();
fixture.AssertFullSemver("0.2.0-PullRequest.44+3");
fixture.AssertFullSemver("0.2.0-PullRequest0044.3");
}
}

Expand All @@ -54,7 +54,7 @@ public void CanCalculatePullRequestChangesFromRemoteRepo()
fixture.Repository.CreatePullRequestRef("feature/Foo", "master", normalise: true);

fixture.Repository.DumpGraph();
fixture.AssertFullSemver("0.1.1-PullRequest.2+2");
fixture.AssertFullSemver("0.1.1-PullRequest0002.2");
}
}

Expand All @@ -71,7 +71,7 @@ public void CanCalculatePullRequestChangesInheritingConfigFromRemoteRepo()

fixture.Repository.CreatePullRequestRef("feature/Foo", "develop", normalise: true);

fixture.AssertFullSemver("0.2.0-PullRequest.2+3");
fixture.AssertFullSemver("0.2.0-PullRequest0002.3");
}
}

Expand All @@ -89,7 +89,7 @@ public void CanCalculatePullRequestChangesWhenThereAreMultipleMergeCandidates()

fixture.Repository.CreatePullRequestRef("feature/Foo", "develop", normalise: true);

fixture.AssertFullSemver("0.2.0-PullRequest.2+3");
fixture.AssertFullSemver("0.2.0-PullRequest0002.3");
}
}

Expand All @@ -106,7 +106,7 @@ public void CalculatesCorrectVersionAfterReleaseBranchMergedToMaster()

fixture.Repository.CreatePullRequestRef("release/2.0.0", "master", normalise: true);

fixture.AssertFullSemver("2.0.0-PullRequest.2+0");
fixture.AssertFullSemver("2.0.0-PullRequest0002.0");
}
}
}
36 changes: 23 additions & 13 deletions src/GitVersionCore/OutputVariables/VariableProvider.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@ public static class VariableProvider
{
public static VersionVariables GetVariablesFor(SemanticVersion semanticVersion, EffectiveConfiguration config, bool isCurrentCommitTagged)
{
if (config.VersioningMode == VersioningMode.ContinuousDeployment && !isCurrentCommitTagged)
var isContinuousDeploymentMode = config.VersioningMode == VersioningMode.ContinuousDeployment && !isCurrentCommitTagged;
if (isContinuousDeploymentMode)
{
semanticVersion = new SemanticVersion(semanticVersion);
// Continuous Deployment always requires a pre-release tag unless the commit is tagged
Expand All @@ -21,22 +22,23 @@ public static VersionVariables GetVariablesFor(SemanticVersion semanticVersion,
semanticVersion.PreReleaseTag.Name = config.ContinuousDeploymentFallbackTag;
}
}
}

// Evaluate tag number pattern and append to prerelease tag, preserving build metadata
if (!string.IsNullOrEmpty(config.TagNumberPattern))
// Evaluate tag number pattern and append to prerelease tag, preserving build metadata
var appendTagNumberPattern = !string.IsNullOrEmpty(config.TagNumberPattern) && semanticVersion.PreReleaseTag.HasTag();
if (appendTagNumberPattern)
{
var match = Regex.Match(semanticVersion.BuildMetaData.Branch, config.TagNumberPattern);
var numberGroup = match.Groups["number"];
if (numberGroup.Success)
{
var match = Regex.Match(semanticVersion.BuildMetaData.Branch, config.TagNumberPattern);
var numberGroup = match.Groups["number"];
if (numberGroup.Success)
{
semanticVersion.PreReleaseTag.Name += numberGroup.Value.PadLeft(config.BuildMetaDataPadding, '0');
}
semanticVersion.PreReleaseTag.Name += numberGroup.Value.PadLeft(config.BuildMetaDataPadding, '0');
}
}

// For continuous deployment the commits since tag gets promoted to the pre-release number
semanticVersion.PreReleaseTag.Number = semanticVersion.BuildMetaData.CommitsSinceTag;
semanticVersion.BuildMetaData.CommitsSinceVersionSource = semanticVersion.BuildMetaData.CommitsSinceTag ?? 0;
semanticVersion.BuildMetaData.CommitsSinceTag = null;
if (isContinuousDeploymentMode || appendTagNumberPattern || config.VersioningMode == VersioningMode.Mainline)
{
PromoteNumberOfCommitsToTagNumber(semanticVersion);
}

var semverFormatValues = new SemanticVersionFormatValues(semanticVersion, config);
Expand Down Expand Up @@ -87,5 +89,13 @@ public static VersionVariables GetVariablesFor(SemanticVersion semanticVersion,

return variables;
}

static void PromoteNumberOfCommitsToTagNumber(SemanticVersion semanticVersion)
{
// For continuous deployment the commits since tag gets promoted to the pre-release number
semanticVersion.PreReleaseTag.Number = semanticVersion.BuildMetaData.CommitsSinceTag;
semanticVersion.BuildMetaData.CommitsSinceVersionSource = semanticVersion.BuildMetaData.CommitsSinceTag ?? 0;
semanticVersion.BuildMetaData.CommitsSinceTag = null;
}
}
}
46 changes: 25 additions & 21 deletions src/GitVersionCore/VersionCalculation/NextVersionCalculator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -44,16 +44,20 @@ public SemanticVersion FindVersion(GitVersionContext context)
}

var baseVersion = baseVersionFinder.GetBaseVersion(context);
var semver = context.Configuration.VersioningMode == VersioningMode.Mainline ?
FindMainlineModeVersion(baseVersion, context) :
PerformIncrement(context, baseVersion);
SemanticVersion semver;
if (context.Configuration.VersioningMode == VersioningMode.Mainline)
semver = FindMainlineModeVersion(baseVersion, context);
else
{
semver = PerformIncrement(context, baseVersion);
semver.BuildMetaData = metaDataCalculator.Create(baseVersion.BaseVersionSource, context);
}

if (!semver.PreReleaseTag.HasTag() && !string.IsNullOrEmpty(context.Configuration.Tag))
{
UpdatePreReleaseTag(context, semver, baseVersion.BranchNameOverride);
}

semver.BuildMetaData = metaDataCalculator.Create(baseVersion.BaseVersionSource, context);

if (taggedSemanticVersion != null)
{
Expand All @@ -76,7 +80,7 @@ private static SemanticVersion PerformIncrement(GitVersionContext context, BaseV
return semver;
}

private SemanticVersion FindMainlineModeVersion(BaseVersion baseVersion, GitVersionContext context)
SemanticVersion FindMainlineModeVersion(BaseVersion baseVersion, GitVersionContext context)
{
if (baseVersion.SemanticVersion.PreReleaseTag.HasTag())
{
Expand Down Expand Up @@ -121,18 +125,26 @@ private SemanticVersion FindMainlineModeVersion(BaseVersion baseVersion, GitVers
if (context.CurrentBranch.FriendlyName != "master")
{
var mergedHead = context.CurrentCommit;
var findMergeBase = context.Repository.ObjectDatabase.FindMergeBase(context.CurrentCommit, context.Repository.FindBranch("master").Tip);
var second = context.Repository.FindBranch("master").Tip;
var findMergeBase = context.Repository.ObjectDatabase.FindMergeBase(context.CurrentCommit, second);
Logger.WriteInfo(string.Format("Current branch ({0}) was branch from {1}", context.CurrentBranch.FriendlyName, findMergeBase));

var branchIncrement = FindMessageIncrement(context, findMergeBase, mergedHead, findMergeBase, directCommits);
var branchIncrement = FindMessageIncrement(context, null, mergedHead, findMergeBase, directCommits);
// This will increment for any direct commits on master
mainlineVersion = IncrementForEachCommit(context, directCommits, mainlineVersion);
Logger.WriteInfo(string.Format("Performing {0} increment for current branch ", branchIncrement));
mainlineVersion = mainlineVersion.IncrementVersion(branchIncrement);
mainlineVersion.BuildMetaData = metaDataCalculator.Create(findMergeBase, context);
// Only increment if head is not a merge commit, ensures PR's and forward merges end up correct.
if (mergedHead.Parents.Count() == 1)
{
Logger.WriteInfo(string.Format("Performing {0} increment for current branch ", branchIncrement));
mainlineVersion = mainlineVersion.IncrementVersion(branchIncrement);
}
}
else
{
// If we are on master, make sure no commits get left behind
mainlineVersion = IncrementForEachCommit(context, directCommits, mainlineVersion);
mainlineVersion.BuildMetaData = metaDataCalculator.Create(baseVersion.BaseVersionSource, context);
}

return mainlineVersion;
Expand Down Expand Up @@ -162,7 +174,9 @@ private static VersionField FindMessageIncrement(
IncludeReachableFrom = mergedHead,
ExcludeReachableFrom = findMergeBase
};
var commits = new[] { mergeCommit }.Union(context.Repository.Commits.QueryBy(filter)).ToList();
var commits = mergeCommit == null ?
context.Repository.Commits.QueryBy(filter).ToList() :
new[] { mergeCommit }.Union(context.Repository.Commits.QueryBy(filter)).ToList();
commitLog.RemoveAll(c => commits.Any(c1 => c1.Sha == c.Sha));
return IncrementStrategyFinder.GetIncrementForCommits(context, commits) ?? VersionField.Patch;
}
Expand All @@ -180,22 +194,12 @@ void UpdatePreReleaseTag(GitVersionContext context, SemanticVersion semanticVers
var tagToUse = GetBranchSpecificTag(context.Configuration, context.CurrentBranch.FriendlyName, branchNameOverride);

int? number = null;
if (!string.IsNullOrEmpty(context.Configuration.TagNumberPattern))
{
var match = Regex.Match(context.CurrentBranch.CanonicalName, context.Configuration.TagNumberPattern);
var numberGroup = match.Groups["number"];
if (numberGroup.Success)
{
number = int.Parse(numberGroup.Value);
}
}

var lastTag = context.CurrentBranch
.GetVersionTagsOnBranch(context.Repository, context.Configuration.GitTagPrefix)
.FirstOrDefault(v => v.PreReleaseTag.Name == tagToUse);

if (number == null &&
lastTag != null &&
if (lastTag != null &&
MajorMinorPatchEqual(lastTag, semanticVersion) &&
lastTag.PreReleaseTag.HasTag())
{
Expand Down
2 changes: 1 addition & 1 deletion src/GitVersionExe.Tests/PullRequestInTeamCityTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ public void GivenARemoteWithATagOnMaster_AndAPullRequestWithTwoCommits_AndBuildI
var result = GitVersionHelper.ExecuteIn(fixture.RepositoryPath, isTeamCity: true);

result.ExitCode.ShouldBe(0);
result.OutputVariables.FullSemVer.ShouldBe("1.0.4-PullRequest.5+3");
result.OutputVariables.FullSemVer.ShouldBe("1.0.4-PullRequest0005.3");

// Cleanup repository files
DirectoryHelper.DeleteDirectory(remoteRepositoryPath);
Expand Down