diff --git a/src/GitVersionCore.Tests/GitVersionExecutorTests.cs b/src/GitVersionCore.Tests/GitVersionExecutorTests.cs index 4fdffc44b5..c767900bcc 100644 --- a/src/GitVersionCore.Tests/GitVersionExecutorTests.cs +++ b/src/GitVersionCore.Tests/GitVersionExecutorTests.cs @@ -1,5 +1,6 @@ using System; using System.IO; +using System.Linq; using System.Text; using GitTools.Testing; using GitVersion; @@ -507,6 +508,33 @@ public void GetDotGitDirectoryWorktree() }); } + [Test] + [Category("NoMono")] + [Description("LibGit2Sharp fails when running under Mono")] + public void CalculateVersionFromWorktreeHead() + { + using var fixture = new EmptyRepositoryFixture(); + var repoDir = new DirectoryInfo(fixture.RepositoryPath); + var worktreePath = Path.Combine(repoDir.Parent.FullName, $"{repoDir.Name}-v1"); + + fixture.Repository.MakeATaggedCommit("v1.0.0"); + var branchV1 = fixture.Repository.CreateBranch("support/1.0"); + + fixture.Repository.MakeATaggedCommit("v2.0.0"); + + fixture.Repository.Worktrees.Add(branchV1.CanonicalName, "1.0", worktreePath, false); + using var worktreeFixture = new LocalRepositoryFixture(new Repository(worktreePath)); + + var arguments = new Arguments { TargetPath = worktreePath }; + + var calculator = GetGitVersionCalculator(arguments); + var version = calculator.CalculateVersionVariables(); + + version.SemVer.ShouldBe("1.0.0"); + var commits = worktreeFixture.Repository.Head.Commits; + version.Sha.ShouldBe(commits.First().Sha); + } + private void RepositoryScope(Action fixtureAction = null) { // Make sure GitVersion doesn't trigger build server mode when we are running the tests diff --git a/src/GitVersionCore.Tests/IntegrationTests/WorktreeScenarios.cs b/src/GitVersionCore.Tests/IntegrationTests/WorktreeScenarios.cs new file mode 100644 index 0000000000..2e61926fc0 --- /dev/null +++ b/src/GitVersionCore.Tests/IntegrationTests/WorktreeScenarios.cs @@ -0,0 +1,32 @@ +using GitTools.Testing; +using LibGit2Sharp; +using NUnit.Framework; +using System.IO; + +namespace GitVersionCore.Tests.IntegrationTests +{ + + [TestFixture] + public class WorktreeScenarios : TestBase + { + + [Test] + public void UseWorktreeRepositoryForVersion() + { + using var fixture = new EmptyRepositoryFixture(); + var repoDir = new DirectoryInfo(fixture.RepositoryPath); + var worktreePath = Path.Combine(repoDir.Parent.FullName, $"{repoDir.Name}-v1"); + + fixture.Repository.MakeATaggedCommit("v1.0.0"); + var branchV1 = fixture.Repository.CreateBranch("support/1.0"); + + fixture.Repository.MakeATaggedCommit("v2.0.0"); + fixture.AssertFullSemver("2.0.0"); + + fixture.Repository.Worktrees.Add(branchV1.CanonicalName, "1.0", worktreePath, false); + using var worktreeFixture = new LocalRepositoryFixture(new Repository(worktreePath)); + worktreeFixture.AssertFullSemver("1.0.0"); + } + + } +} diff --git a/src/GitVersionCore/GitPreparer.cs b/src/GitVersionCore/GitPreparer.cs index c25128b6f7..a2064ea165 100644 --- a/src/GitVersionCore/GitPreparer.cs +++ b/src/GitVersionCore/GitPreparer.cs @@ -26,7 +26,7 @@ public class GitPreparer : IGitPreparer public string GetProjectRootDirectory() => projectRootDirectory ??= GetProjectRootDirectoryInternal(); - private bool IsDynamicGitRepository => !string.IsNullOrWhiteSpace(DynamicGitRepositoryPath); + public bool IsDynamicGitRepository => !string.IsNullOrWhiteSpace(DynamicGitRepositoryPath); private string DynamicGitRepositoryPath; public GitPreparer(ILog log, IEnvironment environment, IOptions options) diff --git a/src/GitVersionCore/GitVersionCalculator.cs b/src/GitVersionCore/GitVersionCalculator.cs index 8e2f12866c..e65b078ce9 100644 --- a/src/GitVersionCore/GitVersionCalculator.cs +++ b/src/GitVersionCore/GitVersionCalculator.cs @@ -106,7 +106,11 @@ private VersionVariables ExecuteInternal(string targetBranch, string commitId, C { var configuration = configProvider.Provide(overrideConfig: overrideConfig); - return gitPreparer.GetDotGitDirectory().WithRepository(repo => + var path = gitPreparer.IsDynamicGitRepository + ? gitPreparer.GetDotGitDirectory() + : gitPreparer.GetProjectRootDirectory(); + + return path.WithRepository(repo => { var gitVersionContext = new GitVersionContext(repo, log, targetBranch, configuration, commitId: commitId); var semanticVersion = gitVersionFinder.FindVersion(gitVersionContext); diff --git a/src/GitVersionCore/GitVersionContext.cs b/src/GitVersionCore/GitVersionContext.cs index 364ed7bf8f..caf27c7f83 100644 --- a/src/GitVersionCore/GitVersionContext.cs +++ b/src/GitVersionCore/GitVersionContext.cs @@ -175,10 +175,12 @@ private static Branch GetTargetBranch(IRepository repository, string targetBranc { // In the case where HEAD is not the desired branch, try to find the branch with matching name desiredBranch = repository?.Branches? - .SingleOrDefault(b => + .Where(b => b.CanonicalName == targetBranch || b.FriendlyName == targetBranch || - b.NameWithoutRemote() == targetBranch); + b.NameWithoutRemote() == targetBranch) + .OrderBy(b => b.IsRemote) + .FirstOrDefault(); // Failsafe in case the specified branch is invalid desiredBranch ??= repository.Head; diff --git a/src/GitVersionCore/IGitPreparer.cs b/src/GitVersionCore/IGitPreparer.cs index 30db2be4f8..c3daacbd44 100644 --- a/src/GitVersionCore/IGitPreparer.cs +++ b/src/GitVersionCore/IGitPreparer.cs @@ -7,5 +7,6 @@ public interface IGitPreparer string GetDotGitDirectory(); string GetTargetUrl(); string GetWorkingDirectory(); + bool IsDynamicGitRepository { get; } } }