diff --git a/src/GitVersionCore.Tests/ExecuteCoreTests.cs b/src/GitVersionCore.Tests/ExecuteCoreTests.cs index 04ad8fc674..3112cdd5f5 100644 --- a/src/GitVersionCore.Tests/ExecuteCoreTests.cs +++ b/src/GitVersionCore.Tests/ExecuteCoreTests.cs @@ -7,6 +7,7 @@ using System; using System.IO; using System.Text; +using LibGit2Sharp; [TestFixture] [Parallelizable(ParallelScope.None)] @@ -40,6 +41,35 @@ public void CacheKeySameAfterReNormalizing() }); } + [Test] + [Category("NoMono")] + [Description("LibGit2Sharp fails here when running under Mono")] + public void CacheKeyForWorktree() + { + var versionAndBranchFinder = new ExecuteCore(fileSystem); + + RepositoryScope(versionAndBranchFinder, (fixture, vv) => + { + var worktreePath = Path.Combine(Directory.GetParent(fixture.RepositoryPath).FullName, Guid.NewGuid().ToString()); + try + { + // create a branch and a new worktree for it + var repo = new Repository(fixture.RepositoryPath); + repo.Worktrees.Add("worktree", worktreePath, false); + + var targetUrl = "https://github.com/GitTools/GitVersion.git"; + var gitPreparer = new GitPreparer(targetUrl, null, new Authentication(), false, worktreePath); + var configFileLocator = new DefaultConfigFileLocator(); + var cacheKey = GitVersionCacheKeyFactory.Create(fileSystem, gitPreparer, null, configFileLocator); + cacheKey.Value.ShouldNotBeEmpty(); + } + finally + { + DirectoryHelper.DeleteDirectory(worktreePath); + } + }); + } + [Test] public void CacheFileExistsOnDisk() { @@ -266,6 +296,47 @@ public void WorkingDirectoryWithoutGit() }); } + [Test] + [Category("NoMono")] + [Description("LibGit2Sharp fails when running under Mono")] + public void GetProjectRootDirectory_WorkingDirectoryWithWorktree() + { + var versionAndBranchFinder = new ExecuteCore(fileSystem); + + RepositoryScope(versionAndBranchFinder, (fixture, vv) => + { + var worktreePath = Path.Combine(Directory.GetParent(fixture.RepositoryPath).FullName, Guid.NewGuid().ToString()); + try + { + // create a branch and a new worktree for it + var repo = new Repository(fixture.RepositoryPath); + repo.Worktrees.Add("worktree", worktreePath, false); + + var targetUrl = "https://github.com/GitTools/GitVersion.git"; + var gitPreparer = new GitPreparer(targetUrl, null, new Authentication(), false, worktreePath); + gitPreparer.GetProjectRootDirectory().TrimEnd('/', '\\').ShouldBe(worktreePath); + } + finally + { + DirectoryHelper.DeleteDirectory(worktreePath); + } + }); + } + + [Test] + public void GetProjectRootDirectory_NoWorktree() + { + var versionAndBranchFinder = new ExecuteCore(fileSystem); + + RepositoryScope(versionAndBranchFinder, (fixture, vv) => + { + var targetUrl = "https://github.com/GitTools/GitVersion.git"; + var gitPreparer = new GitPreparer(targetUrl, null, new Authentication(), false, fixture.RepositoryPath); + var expectedPath = fixture.RepositoryPath.TrimEnd('/', '\\'); + gitPreparer.GetProjectRootDirectory().TrimEnd('/', '\\').ShouldBe(expectedPath); + }); + } + [Test] public void DynamicRepositoriesShouldNotErrorWithFailedToFindGitDirectory() { @@ -277,6 +348,48 @@ public void DynamicRepositoriesShouldNotErrorWithFailedToFindGitDirectory() }); } + [Test] + public void GetDotGitDirectory_NoWorktree() + { + var versionAndBranchFinder = new ExecuteCore(fileSystem); + + RepositoryScope(versionAndBranchFinder, (fixture, vv) => + { + var targetUrl = "https://github.com/GitTools/GitVersion.git"; + var gitPreparer = new GitPreparer(targetUrl, null, new Authentication(), false, fixture.RepositoryPath); + var expectedPath = Path.Combine(fixture.RepositoryPath, ".git"); + gitPreparer.GetDotGitDirectory().ShouldBe(expectedPath); + }); + } + + [Test] + [Category("NoMono")] + [Description("LibGit2Sharp fails when running under Mono")] + public void GetDotGitDirectory_Worktree() + { + var versionAndBranchFinder = new ExecuteCore(fileSystem); + + RepositoryScope(versionAndBranchFinder, (fixture, vv) => + { + var worktreePath = Path.Combine(Directory.GetParent(fixture.RepositoryPath).FullName, Guid.NewGuid().ToString()); + try + { + // create a branch and a new worktree for it + var repo = new Repository(fixture.RepositoryPath); + repo.Worktrees.Add("worktree", worktreePath, false); + + var targetUrl = "https://github.com/GitTools/GitVersion.git"; + var gitPreparer = new GitPreparer(targetUrl, null, new Authentication(), false, worktreePath); + var expectedPath = Path.Combine(fixture.RepositoryPath, ".git"); + gitPreparer.GetDotGitDirectory().ShouldBe(expectedPath); + } + finally + { + DirectoryHelper.DeleteDirectory(worktreePath); + } + }); + } + LogMessages RepositoryScope(ExecuteCore executeCore = null, Action fixtureAction = null) { // Make sure GitVersion doesn't trigger build server mode when we are running the tests diff --git a/src/GitVersionCore/GitPreparer.cs b/src/GitVersionCore/GitPreparer.cs index b9f9d52c97..a734dfd8b5 100644 --- a/src/GitVersionCore/GitPreparer.cs +++ b/src/GitVersionCore/GitPreparer.cs @@ -135,17 +135,14 @@ static bool GitRepoHasMatchingRemote(string possiblePath, string targetUrl) public string GetDotGitDirectory() { - if (IsDynamicGitRepository) - return DynamicGitRepositoryPath; - - var dotGitDirectory = Repository.Discover(targetPath); + var dotGitDirectory = IsDynamicGitRepository ? DynamicGitRepositoryPath : Repository.Discover(targetPath); + dotGitDirectory = dotGitDirectory?.TrimEnd('/', '\\'); if (string.IsNullOrEmpty(dotGitDirectory)) throw new DirectoryNotFoundException("Can't find the .git directory in " + targetPath); - dotGitDirectory = dotGitDirectory.TrimEnd('/', '\\'); - if (string.IsNullOrEmpty(dotGitDirectory)) - throw new DirectoryNotFoundException("Can't find the .git directory in " + targetPath); + if (dotGitDirectory.Contains(Path.Combine(".git", "worktrees"))) + return Directory.GetParent(Directory.GetParent(dotGitDirectory).FullName).FullName; return dotGitDirectory; } @@ -159,10 +156,17 @@ public string GetProjectRootDirectory() return targetPath; } - var dotGetGitDirectory = GetDotGitDirectory(); - var result = Directory.GetParent(dotGetGitDirectory).FullName; - Logger.WriteInfo($"Returning Project Root from DotGitDirectory: {dotGetGitDirectory} - {result}"); - return result; + var dotGitDirectory = Repository.Discover(targetPath); + + if (string.IsNullOrEmpty(dotGitDirectory)) + throw new DirectoryNotFoundException($"Can't find the .git directory in {targetPath}"); + + using (var repo = new Repository(dotGitDirectory)) + { + var result = repo.Info.WorkingDirectory; + Logger.WriteInfo($"Returning Project Root from DotGitDirectory: {dotGitDirectory} - {result}"); + return result; + } } static string CreateDynamicRepository(string targetPath, AuthenticationInfo authentication, string repositoryUrl, string targetBranch, bool noFetch) diff --git a/src/GitVersionCore/GitVersionCacheKeyFactory.cs b/src/GitVersionCore/GitVersionCacheKeyFactory.cs index dfd917ac2d..06670d9d65 100644 --- a/src/GitVersionCore/GitVersionCacheKeyFactory.cs +++ b/src/GitVersionCore/GitVersionCacheKeyFactory.cs @@ -42,7 +42,7 @@ static List CalculateDirectoryContents(string root) if (!Directory.Exists(root)) { - throw new ArgumentException(); + throw new DirectoryNotFoundException($"Root directory does not exist: {root}"); } dirs.Push(root);