Skip to content
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

Add HEAD support #3241

Closed
5 changes: 5 additions & 0 deletions docs/input/docs/reference/configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -552,6 +552,11 @@ Example of invalid `Strict`, but valid `Loose`
1.2.3.4
```

### handle-detached-branch
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since you're targeting main, this is going to be rolled into v6. To target v5, you need to rebase and retarget against support/5.x, but I would like to avoid the introduction of new configuration properties. As such, I don't think we need any new configuration properties to add support for detached HEAD?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For me it's ok to go for v6. Are you proposing to change the beaviour and always handle detached branches? Will I remove the handle-detached-branch option and every changes correlated?


Avoid to strickly request to refer to a branch. If detached, the `no-branch`
reference will be used.

[1145]: https://github.com/GitTools/GitVersion/issues/1145
[1366]: https://github.com/GitTools/GitVersion/issues/1366
[2506]: https://github.com/GitTools/GitVersion/pull/2506#issuecomment-754754037
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -109,3 +109,4 @@ increment: Inherit
commit-date-format: yyyy-MM-dd
merge-message-formats: {}
update-build-number: true
handle-detached-branch: false
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ private GitFlowConfigurationBuilder()
CommitDateFormat = "yyyy-MM-dd",
UpdateBuildNumber = true,
SemanticVersionFormat = SemanticVersionFormat.Strict,
HandleDetachedBranch = false,
TagPreReleaseWeight = 60000,
Increment = IncrementStrategy.Inherit
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ private GitHubFlowConfigurationBuilder()
CommitDateFormat = "yyyy-MM-dd",
UpdateBuildNumber = true,
SemanticVersionFormat = SemanticVersionFormat.Strict,
HandleDetachedBranch = false,
TagPreReleaseWeight = 60000,
Increment = IncrementStrategy.Inherit
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ internal abstract class TestConfigurationBuilderBase<TConfigurationBuilder>
private string? commitDateFormat;
private bool? updateBuildNumber;
private SemanticVersionFormat semanticVersionFormat = SemanticVersionFormat.Strict;
private bool? handleDetachedBranch;
private Dictionary<string, string>? mergeMessageFormats;
protected readonly Dictionary<string, TestBranchConfigurationBuilder> branchConfigurationBuilders = new();

Expand Down Expand Up @@ -164,6 +165,12 @@ public virtual TConfigurationBuilder WithSemanticVersionFormat(SemanticVersionFo
return (TConfigurationBuilder)this;
}

public virtual TConfigurationBuilder WithHandleDetachedBranch(bool? value)
{
this.handleDetachedBranch = value;
return (TConfigurationBuilder)this;
}

public virtual TConfigurationBuilder WithMergeMessageFormats(Dictionary<string, string> value)
{
this.mergeMessageFormats = value;
Expand Down Expand Up @@ -214,6 +221,7 @@ public virtual TConfigurationBuilder WithConfiguration(GitVersionConfiguration v
WithCommitDateFormat(value.CommitDateFormat);
WithUpdateBuildNumber(value.UpdateBuildNumber);
WithSemanticVersionFormat(value.SemanticVersionFormat);
WithHandleDetachedBranch(value.HandleDetachedBranch);
WithMergeMessageFormats(value.MergeMessageFormats);
foreach (var (name, branchConfiguration) in value.Branches)
{
Expand Down Expand Up @@ -246,6 +254,7 @@ public virtual GitVersionConfiguration Build()
CommitDateFormat = this.commitDateFormat,
UpdateBuildNumber = this.updateBuildNumber,
SemanticVersionFormat = this.semanticVersionFormat,
HandleDetachedBranch = this.handleDetachedBranch,
MergeMessageFormats = this.mergeMessageFormats ?? new()
};
Dictionary<string, BranchConfiguration> branches = new();
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using GitTools.Testing;
using GitVersion.BuildAgents;
using GitVersion.Configuration;
using GitVersion.Core.Tests.Helpers;
using LibGit2Sharp;
using Microsoft.Extensions.DependencyInjection;
Expand Down Expand Up @@ -98,6 +99,24 @@ public void GivenARemoteGitRepositoryWhenCheckingOutDetachedHeadUsingExistingImp
$"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.");
}

[Test]
[TestCase(true)]
[TestCase(false)]
public void GivenARemoteGitRepositoryWhenCheckingOutDetachedHeadUsingExistingImplementationHandleDetachedBranch(bool handleDetachedBranch)
{
using var fixture = new RemoteRepositoryFixture();
Commands.Checkout(
fixture.LocalRepositoryFixture.Repository,
fixture.LocalRepositoryFixture.Repository.Head.Tip);
simonetognolo marked this conversation as resolved.
Show resolved Hide resolved

var configuration = new GitVersionConfiguration { HandleDetachedBranch = handleDetachedBranch };
if (handleDetachedBranch)
fixture.AssertFullSemver("0.0.1--no-branch-.1+5", configuration: configuration, repository: fixture.LocalRepositoryFixture.Repository, onlyTrackedBranches: false);
else
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.");
}

[Test]
[Ignore("Needs more investigations.")]
public void GivenARemoteGitRepositoryWhenCheckingOutDetachedHeadUsingTrackingBranchOnlyBehaviourShouldReturnVersion014Plus5()
Expand Down
2 changes: 2 additions & 0 deletions src/GitVersion.Core/Configuration/ConfigurationBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ private static void ApplyOverrides(GitVersionConfiguration targetConfig, GitVers
targetConfig.MergeMessageFormats = overrideConfiguration.MergeMessageFormats.Any() ? overrideConfiguration.MergeMessageFormats : targetConfig.MergeMessageFormats;
targetConfig.UpdateBuildNumber = overrideConfiguration.UpdateBuildNumber ?? targetConfig.UpdateBuildNumber;
targetConfig.SemanticVersionFormat = overrideConfiguration.SemanticVersionFormat;
targetConfig.HandleDetachedBranch = overrideConfiguration.HandleDetachedBranch ?? targetConfig.HandleDetachedBranch;

if (overrideConfiguration.Ignore is { IsEmpty: false })
{
Expand Down Expand Up @@ -187,6 +188,7 @@ private static GitVersionConfiguration CreateDefaultConfiguration()
CommitDateFormat = "yyyy-MM-dd",
UpdateBuildNumber = true,
SemanticVersionFormat = SemanticVersionFormat.Strict,
HandleDetachedBranch = false,
TagPreReleaseWeight = DefaultTagPreReleaseWeight,
Increment = IncrementStrategy.Inherit
};
Expand Down
3 changes: 3 additions & 0 deletions src/GitVersion.Core/Configuration/GitVersionConfiguration.cs
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,9 @@ public string? NextVersion
[YamlMember(Alias = "semver-format")]
public SemanticVersionFormat SemanticVersionFormat { get; set; } = SemanticVersionFormat.Strict;

[YamlMember(Alias = "handle-detached-branch")]
public bool? HandleDetachedBranch { get; set; }

public override string ToString()
{
var stringBuilder = new StringBuilder();
Expand Down
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, GitVersionConfiguration configuration);

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.TagPrefix);
var currentCommitTaggedVersion = this.repositoryStore.GetCurrentCommitTaggedVersion(currentCommit, configuration);
var numberOfUncommittedChanges = this.repositoryStore.GetNumberOfUncommittedChanges();

return new GitVersionContext(currentBranch, currentCommit, configuration, currentCommitTaggedVersion, numberOfUncommittedChanges);
Expand Down
28 changes: 16 additions & 12 deletions src/GitVersion.Core/Core/RepositoryStore.cs
Original file line number Diff line number Diff line change
Expand Up @@ -146,17 +146,16 @@ public IEnumerable<IBranch> GetSourceBranches(IBranch branch, GitVersionConfigur
var referenceLookup = this.repository.Refs.ToLookup(r => r.TargetIdentifier);

var returnedBranches = new HashSet<IBranch>();
if (referenceLookup.Any())
if (!referenceLookup.Any())
yield break;
foreach (var branchCommit in FindCommitBranchesWasBranchedFrom(branch, configuration, excludedBranches))
{
foreach (var branchCommit in FindCommitBranchesWasBranchedFrom(branch, configuration, excludedBranches))
foreach (var _ in referenceLookup[branchCommit.Commit.Sha]
.Where(r => r.Name.Friendly == branchCommit.Branch.Name.Friendly))
{
foreach (var _ in referenceLookup[branchCommit.Commit.Sha]
.Where(r => r.Name.Friendly == branchCommit.Branch.Name.Friendly))
if (returnedBranches.Add(branchCommit.Branch))
{
if (returnedBranches.Add(branchCommit.Branch))
{
yield return branchCommit.Branch;
}
yield return branchCommit.Branch;
}
}
}
Expand Down Expand Up @@ -219,9 +218,9 @@ public IEnumerable<BranchCommit> FindCommitBranchesWasBranchedFrom(IBranch branc
}
}

public SemanticVersion? GetCurrentCommitTaggedVersion(ICommit? commit, string? tagPrefix)
public SemanticVersion? GetCurrentCommitTaggedVersion(ICommit? commit, GitVersionConfiguration configuration)
=> this.repository.Tags
.SelectMany(t => GetCurrentCommitSemanticVersions(commit, tagPrefix, t))
.SelectMany(t => GetCurrentCommitSemanticVersions(commit, configuration.TagPrefix, t, configuration.HandleDetachedBranch ?? false))
.Max();

public IEnumerable<SemanticVersion> GetVersionTagsOnBranch(IBranch branch, string? tagPrefixRegex)
Expand Down Expand Up @@ -290,12 +289,17 @@ 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)
{
var targetCommit = tag.PeeledTargetCommit();
if (targetCommit == null)
return Array.Empty<SemanticVersion>();

var commitToCompare = handleDetachedBranch ? FindMergeBase(commit, targetCommit) : commit;
simonetognolo marked this conversation as resolved.
Show resolved Hide resolved

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
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,7 @@ private void UpdatePreReleaseTag(EffectiveBranchConfiguration configuration, Sem

private static void EnsureHeadIsNotDetached(GitVersionContext context)
{
if (context.CurrentBranch.IsDetachedHead != true)
if (context.CurrentBranch.IsDetachedHead != true || (context.Configuration.HandleDetachedBranch ?? false))
{
return;
}
Expand Down