Skip to content

merge changes from support/v5.x #3373

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 13 commits into from
Feb 16, 2023
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
5 changes: 0 additions & 5 deletions docs/input/docs/reference/requirements.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,11 +28,6 @@ The repository needs to have an existing local `master` or `main` branch.
For some branch strategies (such as [Git Flow][gitflow]), a local `develop`
branch needs to exist.

### Switched branch

The repository should be [switched][git-switch] to a named, existing branch
pointing to the commit being built (i.e. no detached `HEAD`).

### Configuration

If using a `GitVersion.yml` [configuration][configuration] file, that file
Expand Down
5 changes: 5 additions & 0 deletions docs/input/docs/reference/version-increments.md
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,11 @@ If you create a branch with the version number in the branch name, such as
from the branch name as a source. However, GitVersion can't use the [branch
name as a version source for _other branches_][faq-branch-name-source].

### Detached HEAD
If HEAD is in detached state tag will be `-no-branch-`.

Example: `0.0.1--no-branch-.1+4`

### Tagging commit

By tagging a commit, GitVersion will use that tag for the version of that
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Options;
using NUnit.Framework;
using Shouldly;

namespace GitVersion.Core.Tests.IntegrationTests;

Expand Down Expand Up @@ -87,15 +86,14 @@ public void GivenARemoteGitRepositoryAheadOfLocalRepositoryThenChangesShouldPull
}

[Test]
public void GivenARemoteGitRepositoryWhenCheckingOutDetachedHeadUsingExistingImplementationThrowsException()
public void GivenARemoteGitRepositoryWhenCheckingOutDetachedHeadUsingExistingImplementationHandleDetachedBranch()
{
using var fixture = new RemoteRepositoryFixture();
Commands.Checkout(
fixture.LocalRepositoryFixture.Repository,
fixture.LocalRepositoryFixture.Repository.Head.Tip);

Should.Throw<WarningException>(() => fixture.AssertFullSemver("0.1.0+4", repository: fixture.LocalRepositoryFixture.Repository, onlyTrackedBranches: false),
$"It looks like the branch being examined is a detached Head pointing to commit '{fixture.LocalRepositoryFixture.Repository.Head.Tip.Id.ToString(7)}'. Without a proper branch name GitVersion cannot determine the build version.");
fixture.AssertFullSemver("0.0.1--no-branch-.1+5", repository: fixture.LocalRepositoryFixture.Repository, onlyTrackedBranches: false);
}

[Test]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -71,4 +71,31 @@ public void WhenSupportIsBranchedAndTaggedFromAnotherSupportEnsureNewMinorIsUsed

fixture.AssertFullSemver("1.3.1+2");
}

[Test]
public void WhenSupportIsBranchedFromMainWithSpecificTag()
{
using var fixture = new EmptyRepositoryFixture();
fixture.Repository.MakeACommit();
fixture.AssertFullSemver("0.0.1+1");

fixture.Repository.ApplyTag("1.4.0-rc");
fixture.Repository.MakeACommit();
fixture.Repository.CreateBranch("support/1");
Commands.Checkout(fixture.Repository, "support/1");
fixture.AssertFullSemver("1.4.0+1");
}

[Test]
public void WhenSupportIsBranchedFromMainWithSpecificTagOnCommit()
{
using var fixture = new EmptyRepositoryFixture();
fixture.Repository.MakeACommit();
fixture.AssertFullSemver("0.0.1+1");

fixture.Repository.ApplyTag("1.4.0-rc");
fixture.Repository.CreateBranch("support/1");
Commands.Checkout(fixture.Repository, "support/1");
fixture.AssertFullSemver("1.4.0");
}
}
2 changes: 1 addition & 1 deletion src/GitVersion.Core/Core/Abstractions/IRepositoryStore.cs
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ public interface IRepositoryStore

IEnumerable<IBranch> GetSourceBranches(IBranch branch, GitVersionConfiguration configuration, IEnumerable<IBranch> excludedBranches);

SemanticVersion? GetCurrentCommitTaggedVersion(ICommit? commit, string? tagPrefix);
SemanticVersion? GetCurrentCommitTaggedVersion(ICommit? commit, string? tagPrefix, bool handleDetachedBranch);

IEnumerable<SemanticVersion> GetVersionTagsOnBranch(IBranch branch, string? tagPrefixRegex);
IEnumerable<(ITag Tag, SemanticVersion Semver, ICommit Commit)> GetValidVersionTags(string? tagPrefixRegex, DateTimeOffset? olderThan = null);
Expand Down
2 changes: 1 addition & 1 deletion src/GitVersion.Core/Core/GitVersionContextFactory.cs
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ public GitVersionContext Create(GitVersionOptions gitVersionOptions)
currentBranch = branchForCommit ?? currentBranch;
}

var currentCommitTaggedVersion = this.repositoryStore.GetCurrentCommitTaggedVersion(currentCommit, configuration.LabelPrefix);
var currentCommitTaggedVersion = this.repositoryStore.GetCurrentCommitTaggedVersion(currentCommit, configuration.LabelPrefix, handleDetachedBranch: currentBranch.IsDetachedHead);
var numberOfUncommittedChanges = this.repositoryStore.GetNumberOfUncommittedChanges();

return new GitVersionContext(currentBranch, currentCommit, configuration, currentCommitTaggedVersion, numberOfUncommittedChanges);
Expand Down
16 changes: 12 additions & 4 deletions src/GitVersion.Core/Core/RepositoryStore.cs
Original file line number Diff line number Diff line change
Expand Up @@ -219,9 +219,9 @@ public IEnumerable<BranchCommit> FindCommitBranchesWasBranchedFrom(IBranch branc
}
}

public SemanticVersion? GetCurrentCommitTaggedVersion(ICommit? commit, string? tagPrefix)
public SemanticVersion? GetCurrentCommitTaggedVersion(ICommit? commit, string? tagPrefix, bool handleDetachedBranch)
=> this.repository.Tags
.SelectMany(t => GetCurrentCommitSemanticVersions(commit, tagPrefix, t))
.SelectMany(t => GetCurrentCommitSemanticVersions(commit, tagPrefix, t, handleDetachedBranch))
.Max();

public IEnumerable<SemanticVersion> GetVersionTagsOnBranch(IBranch branch, string? tagPrefixRegex)
Expand Down Expand Up @@ -290,12 +290,20 @@ public bool IsCommitOnBranch(ICommit? baseVersionSource, IBranch branch, ICommit
private static bool IsReleaseBranch(INamedReference branch, IEnumerable<KeyValuePair<string, BranchConfiguration>> releaseBranchConfig)
=> releaseBranchConfig.Any(c => c.Value?.Regex != null && Regex.IsMatch(branch.Name.Friendly, c.Value.Regex));

private static IEnumerable<SemanticVersion> GetCurrentCommitSemanticVersions(ICommit? commit, string? tagPrefix, ITag tag)
private IEnumerable<SemanticVersion> GetCurrentCommitSemanticVersions(ICommit? commit, string? tagPrefix, ITag tag, bool handleDetachedBranch)
{
if (commit == null)
return Array.Empty<SemanticVersion>();

var targetCommit = tag.PeeledTargetCommit();
if (targetCommit == null)
return Array.Empty<SemanticVersion>();

var commitToCompare = handleDetachedBranch ? FindMergeBase(commit, targetCommit) : commit;

var tagName = tag.Name.Friendly;

return targetCommit != null && Equals(targetCommit, commit) && SemanticVersion.TryParse(tagName, tagPrefix, out var version)
return Equals(targetCommit, commitToCompare) && SemanticVersion.TryParse(tagName, tagPrefix, out var version)
? new[] { version }
: Array.Empty<SemanticVersion>();
}
Expand Down
2 changes: 2 additions & 0 deletions src/GitVersion.Core/Extensions/StringExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -102,4 +102,6 @@ public static bool IsEquivalentTo(this string self, string? other) =>

/// <inheritdoc cref="string.IsNullOrWhiteSpace"/>
public static bool IsNullOrWhiteSpace([NotNullWhen(false)] this string? value) => string.IsNullOrWhiteSpace(value);

public static bool IsEmpty([NotNullWhen(false)] this string? value) => string.Empty.Equals(value);
}
5 changes: 3 additions & 2 deletions src/GitVersion.Core/PublicAPI.Shipped.txt
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,7 @@ GitVersion.Common.IRepositoryStore.FindMergeBase(GitVersion.ICommit! commit, Git
GitVersion.Common.IRepositoryStore.GetBranchesContainingCommit(GitVersion.ICommit? commit, System.Collections.Generic.IEnumerable<GitVersion.IBranch!>? branches = null, bool onlyTrackedBranches = false) -> System.Collections.Generic.IEnumerable<GitVersion.IBranch!>!
GitVersion.Common.IRepositoryStore.GetCommitLog(GitVersion.ICommit? baseVersionSource, GitVersion.ICommit? currentCommit) -> System.Collections.Generic.IEnumerable<GitVersion.ICommit!>!
GitVersion.Common.IRepositoryStore.GetCurrentCommit(GitVersion.IBranch! currentBranch, string? commitId) -> GitVersion.ICommit?
GitVersion.Common.IRepositoryStore.GetCurrentCommitTaggedVersion(GitVersion.ICommit? commit, string? tagPrefix) -> GitVersion.SemanticVersion?
GitVersion.Common.IRepositoryStore.GetCurrentCommitTaggedVersion(GitVersion.ICommit? commit, string? tagPrefix, bool handleDetachedBranch) -> GitVersion.SemanticVersion?
GitVersion.Common.IRepositoryStore.GetMainlineBranches(GitVersion.ICommit! commit, GitVersion.Configuration.GitVersionConfiguration! configuration) -> System.Collections.Generic.IDictionary<string!, System.Collections.Generic.List<GitVersion.IBranch!>!>!
GitVersion.Common.IRepositoryStore.GetMainlineCommitLog(GitVersion.ICommit? baseVersionSource, GitVersion.ICommit? mainlineTip) -> System.Collections.Generic.IEnumerable<GitVersion.ICommit!>!
GitVersion.Common.IRepositoryStore.GetMergeBaseCommits(GitVersion.ICommit? mergeCommit, GitVersion.ICommit? mergedHead, GitVersion.ICommit? findMergeBase) -> System.Collections.Generic.IEnumerable<GitVersion.ICommit!>!
Expand Down Expand Up @@ -823,7 +823,7 @@ GitVersion.RepositoryStore.FindMergeBase(GitVersion.ICommit! commit, GitVersion.
GitVersion.RepositoryStore.GetBranchesContainingCommit(GitVersion.ICommit? commit, System.Collections.Generic.IEnumerable<GitVersion.IBranch!>? branches = null, bool onlyTrackedBranches = false) -> System.Collections.Generic.IEnumerable<GitVersion.IBranch!>!
GitVersion.RepositoryStore.GetCommitLog(GitVersion.ICommit? baseVersionSource, GitVersion.ICommit? currentCommit) -> System.Collections.Generic.IEnumerable<GitVersion.ICommit!>!
GitVersion.RepositoryStore.GetCurrentCommit(GitVersion.IBranch! currentBranch, string? commitId) -> GitVersion.ICommit?
GitVersion.RepositoryStore.GetCurrentCommitTaggedVersion(GitVersion.ICommit? commit, string? tagPrefix) -> GitVersion.SemanticVersion?
GitVersion.RepositoryStore.GetCurrentCommitTaggedVersion(GitVersion.ICommit? commit, string? tagPrefix, bool handleDetachedBranch) -> GitVersion.SemanticVersion?
GitVersion.RepositoryStore.GetMainlineBranches(GitVersion.ICommit! commit, GitVersion.Configuration.GitVersionConfiguration! configuration) -> System.Collections.Generic.IDictionary<string!, System.Collections.Generic.List<GitVersion.IBranch!>!>!
GitVersion.RepositoryStore.GetMainlineCommitLog(GitVersion.ICommit? baseVersionSource, GitVersion.ICommit? mainlineTip) -> System.Collections.Generic.IEnumerable<GitVersion.ICommit!>!
GitVersion.RepositoryStore.GetMergeBaseCommits(GitVersion.ICommit? mergeCommit, GitVersion.ICommit? mergedHead, GitVersion.ICommit? findMergeBase) -> System.Collections.Generic.IEnumerable<GitVersion.ICommit!>!
Expand Down Expand Up @@ -1285,6 +1285,7 @@ static GitVersion.Extensions.StringExtensions.IsHelp(this string! singleArgument
static GitVersion.Extensions.StringExtensions.IsInit(this string! singleArgument) -> bool
static GitVersion.Extensions.StringExtensions.IsNullOrEmpty(this string? value) -> bool
static GitVersion.Extensions.StringExtensions.IsNullOrWhiteSpace(this string? value) -> bool
static GitVersion.Extensions.StringExtensions.IsEmpty(this string? value) -> bool
static GitVersion.Extensions.StringExtensions.IsSwitch(this string? value, string! switchName) -> bool
static GitVersion.Extensions.StringExtensions.IsSwitchArgument(this string? value) -> bool
static GitVersion.Extensions.StringExtensions.IsTrue(this string? value) -> bool
Expand Down
39 changes: 19 additions & 20 deletions src/GitVersion.Core/VersionCalculation/NextVersionCalculator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -42,10 +42,6 @@ public virtual NextVersion FindVersion()
{
this.log.Info($"Current commit is tagged with version {Context.CurrentCommitTaggedVersion}, " + "version calculation is for metadata only.");
}
else
{
EnsureHeadIsNotDetached(Context);
}

// TODO: It is totally unimportant that the current commit has been tagged or not IMO. We can make a double check actually if the result
// is the same or make it configurable but each run should be deterministic.Even if the development process goes on the tagged commit
Expand Down Expand Up @@ -87,8 +83,12 @@ public virtual NextVersion FindVersion()
var hasPreReleaseTag = semver.HasPreReleaseTagWithLabel;
var tag = nextVersion.Configuration.Label;
var branchConfigHasPreReleaseTagConfigured = !tag.IsNullOrEmpty();
var preReleaseTagDoesNotMatchConfiguration = hasPreReleaseTag && branchConfigHasPreReleaseTagConfigured && semver.PreReleaseTag?.Name != tag;
if (semver.PreReleaseTag?.HasTag() != true && branchConfigHasPreReleaseTagConfigured || preReleaseTagDoesNotMatchConfiguration)
var branchConfigIsMainlineAndHasEmptyPreReleaseTagConfigured = nextVersion.Configuration.IsMainline && tag.IsEmpty();
var preReleaseTagDoesNotMatchConfiguration = hasPreReleaseTag
&& (branchConfigHasPreReleaseTagConfigured || branchConfigIsMainlineAndHasEmptyPreReleaseTagConfigured)
&& semver.PreReleaseTag?.Name != tag;
var preReleaseTagOnlyInBranchConfig = !hasPreReleaseTag && branchConfigHasPreReleaseTagConfigured;
if (preReleaseTagOnlyInBranchConfig || preReleaseTagDoesNotMatchConfiguration)
{
UpdatePreReleaseTag(new(nextVersion.Branch, nextVersion.Configuration), semver, nextVersion.BaseVersion.BranchNameOverride);
}
Expand All @@ -104,6 +104,12 @@ public virtual NextVersion FindVersion()
{
// set the commit count on the tagged ver
taggedSemanticVersion.BuildMetaData.CommitsSinceVersionSource = semver.BuildMetaData?.CommitsSinceVersionSource;

// set the updated prerelease tag when it doesn't match with prerelease tag defined in branch configuration
if (preReleaseTagDoesNotMatchConfiguration)
{
taggedSemanticVersion.PreReleaseTag = semver.PreReleaseTag;
}
}
}

Expand All @@ -114,6 +120,12 @@ private void UpdatePreReleaseTag(EffectiveBranchConfiguration configuration, Sem
{
var tagToUse = configuration.Value.GetBranchSpecificTag(this.log, Context.CurrentBranch.Name.Friendly, branchNameOverride);

if (configuration.Value.IsMainline && tagToUse.IsEmpty())
{
semanticVersion.PreReleaseTag = new SemanticVersionPreReleaseTag(tagToUse, null);
return;
}

long? number = null;

// TODO: Please update the pre release-tag in the IVersionStrategy implementation.
Expand All @@ -131,19 +143,6 @@ private void UpdatePreReleaseTag(EffectiveBranchConfiguration configuration, Sem
semanticVersion.PreReleaseTag = new SemanticVersionPreReleaseTag(tagToUse, number);
}

private static void EnsureHeadIsNotDetached(GitVersionContext context)
{
if (context.CurrentBranch.IsDetachedHead != true)
{
return;
}

var message = string.Format(
"It looks like the branch being examined is a detached Head pointing to commit '{0}'. " + "Without a proper branch name GitVersion cannot determine the build version.",
context.CurrentCommit?.Id.ToString(7));
throw new WarningException(message);
}

private static bool MajorMinorPatchEqual(SemanticVersion lastTag, SemanticVersion baseVersion) => lastTag.Major == baseVersion.Major && lastTag.Minor == baseVersion.Minor && lastTag.Patch == baseVersion.Patch;

private NextVersion Calculate(IBranch branch, GitVersionConfiguration configuration)
Expand Down Expand Up @@ -248,7 +247,7 @@ private IEnumerable<NextVersion> GetNextVersions(IBranch branch, GitVersionConfi

if (configuration.VersioningMode == VersioningMode.Mainline)
{
if (!(incrementedVersion.PreReleaseTag?.HasTag() != true))
if (incrementedVersion.PreReleaseTag?.HasTag() == true)
{
continue;
}
Expand Down