diff --git a/src/GitVersionCore.Tests/GitVersionExecutorTests.cs b/src/GitVersionCore.Tests/GitVersionExecutorTests.cs index 8ec5c70ee5..4fdffc44b5 100644 --- a/src/GitVersionCore.Tests/GitVersionExecutorTests.cs +++ b/src/GitVersionCore.Tests/GitVersionExecutorTests.cs @@ -76,7 +76,7 @@ public void CacheKeySameAfterReNormalizing() } [Test] - public void GitPreparerShouldFailWhenTargetPathNotInitialized() + public void GitPreparerShouldNotFailWhenTargetPathNotInitialized() { RepositoryScope((fixture, vv) => { @@ -88,10 +88,6 @@ public void GitPreparerShouldFailWhenTargetPathNotInitialized() TargetPath = null }; var options = Options.Create(arguments); - Should.Throw(() => new GitPreparer(log, environment, options)); - - arguments.TargetPath = fixture.RepositoryPath; - Should.NotThrow(() => new GitPreparer(log, environment, options)); }); } @@ -413,7 +409,7 @@ public void GetProjectRootDirectoryWorkingDirectoryWithWorktree() var gitPreparer = new GitPreparer(log, environment, Options.Create(arguments)); - gitPreparer.GetProjectRootDirectory().TrimEnd('/', '\\').ShouldBe(worktreePath); + gitPreparer.GetProjectRootDirectoryInternal().TrimEnd('/', '\\').ShouldBe(worktreePath); } finally { @@ -437,7 +433,7 @@ public void GetProjectRootDirectoryNoWorktree() var gitPreparer = new GitPreparer(log, environment, Options.Create(arguments)); var expectedPath = fixture.RepositoryPath.TrimEnd('/', '\\'); - gitPreparer.GetProjectRootDirectory().TrimEnd('/', '\\').ShouldBe(expectedPath); + gitPreparer.GetProjectRootDirectoryInternal().TrimEnd('/', '\\').ShouldBe(expectedPath); }); } diff --git a/src/GitVersionCore/Cache/GitVersionCacheKeyFactory.cs b/src/GitVersionCore/Cache/GitVersionCacheKeyFactory.cs index 7f5b7d0781..d2ad8b5b56 100644 --- a/src/GitVersionCore/Cache/GitVersionCacheKeyFactory.cs +++ b/src/GitVersionCore/Cache/GitVersionCacheKeyFactory.cs @@ -6,6 +6,7 @@ using System.Text; using GitVersion.Configuration; using GitVersion.Logging; +using GitVersion.Extensions; namespace GitVersion.Cache { @@ -124,7 +125,8 @@ private static List CalculateDirectoryContents(ILog log, string root) private static string GetRepositorySnapshotHash(IGitPreparer gitPreparer) { - var repositorySnapshot = gitPreparer.WithRepository(repo => { + var repositorySnapshot = gitPreparer.GetDotGitDirectory().WithRepository(repo => + { var head = repo.Head; if (head.Tip == null) { diff --git a/src/GitVersionCore/Configuration/ConfigFileLocator.cs b/src/GitVersionCore/Configuration/ConfigFileLocator.cs index 7b87ca966c..f128f38f93 100644 --- a/src/GitVersionCore/Configuration/ConfigFileLocator.cs +++ b/src/GitVersionCore/Configuration/ConfigFileLocator.cs @@ -23,7 +23,7 @@ protected ConfigFileLocator(IFileSystem fileSystem, ILog log) public string SelectConfigFilePath(IGitPreparer gitPreparer) { - var workingDirectory = gitPreparer.WorkingDirectory; + var workingDirectory = gitPreparer.GetWorkingDirectory(); var projectRootDirectory = gitPreparer.GetProjectRootDirectory(); if (HasConfigFileAt(workingDirectory)) @@ -50,14 +50,14 @@ public Config ReadConfig(string workingDirectory) public void Verify(IGitPreparer gitPreparer) { - if (!string.IsNullOrWhiteSpace(gitPreparer.TargetUrl)) + if (!string.IsNullOrWhiteSpace(gitPreparer.GetTargetUrl())) { // Assuming this is a dynamic repository. At this stage it's unsure whether we have // any .git info so we need to skip verification return; } - var workingDirectory = gitPreparer.WorkingDirectory; + var workingDirectory = gitPreparer.GetWorkingDirectory(); var projectRootDirectory = gitPreparer.GetProjectRootDirectory(); Verify(workingDirectory, projectRootDirectory); diff --git a/src/GitVersionCore/Configuration/ConfigFileLocatorFactory.cs b/src/GitVersionCore/Configuration/ConfigFileLocatorFactory.cs index 8e4de34465..8e4648fe3c 100644 --- a/src/GitVersionCore/Configuration/ConfigFileLocatorFactory.cs +++ b/src/GitVersionCore/Configuration/ConfigFileLocatorFactory.cs @@ -14,7 +14,7 @@ public ConfigFileLocatorFactory(IFileSystem fileSystem, ILog log, IOptions options; + public NamedConfigFileLocator(IFileSystem fileSystem, ILog log, IOptions options) : base(fileSystem, log) { - var filePath = options.Value.ConfigFile; - if (string.IsNullOrEmpty(filePath)) throw new ArgumentNullException(nameof(filePath), "Empty file path provided!"); - FilePath = filePath; + this.options = options ?? throw new ArgumentNullException(nameof(options)); } - public string FilePath { get; } + public string FilePath => options.Value.ConfigFile; public override bool HasConfigFileAt(string workingDirectory) => FileSystem.Exists(Path.Combine(workingDirectory, FilePath)); diff --git a/src/GitVersionCore/Extensions/LibGitExtensions.cs b/src/GitVersionCore/Extensions/LibGitExtensions.cs index ff8ff670f9..5fced05576 100644 --- a/src/GitVersionCore/Extensions/LibGitExtensions.cs +++ b/src/GitVersionCore/Extensions/LibGitExtensions.cs @@ -11,6 +11,12 @@ namespace GitVersion.Extensions { public static class LibGitExtensions { + public static TResult WithRepository(this string dotGitDirectory, Func action) + { + using var repo = new Repository(dotGitDirectory); + return action(repo); + } + public static DateTimeOffset When(this Commit commit) { return commit.Committer.When; diff --git a/src/GitVersionCore/GitPreparer.cs b/src/GitVersionCore/GitPreparer.cs index 1254ee3218..c25128b6f7 100644 --- a/src/GitVersionCore/GitPreparer.cs +++ b/src/GitVersionCore/GitPreparer.cs @@ -12,36 +12,43 @@ public class GitPreparer : IGitPreparer { private readonly ILog log; private readonly IEnvironment environment; - private readonly string dynamicRepositoryLocation; - private readonly Arguments arguments; + private readonly IOptions options; private const string DefaultRemoteName = "origin"; - private string dynamicGitRepositoryPath; + private string dotGitDirectory; + private string projectRootDirectory; + + public string GetTargetUrl() => options.Value.TargetUrl; + + public string GetWorkingDirectory() => options.Value.TargetPath.TrimEnd('/', '\\'); + + public string GetDotGitDirectory() => dotGitDirectory ??= GetDotGitDirectoryInternal(); + + public string GetProjectRootDirectory() => projectRootDirectory ??= GetProjectRootDirectoryInternal(); + + private bool IsDynamicGitRepository => !string.IsNullOrWhiteSpace(DynamicGitRepositoryPath); + private string DynamicGitRepositoryPath; public GitPreparer(ILog log, IEnvironment environment, IOptions options) { this.log = log ?? throw new ArgumentNullException(nameof(log)); - this.environment = environment; - arguments = options.Value; - - TargetUrl = arguments.TargetUrl; - WorkingDirectory = arguments.TargetPath.TrimEnd('/', '\\'); - - dynamicRepositoryLocation = arguments.DynamicRepositoryLocation; + this.environment = environment ?? throw new ArgumentNullException(nameof(environment)); + this.options = options ?? throw new ArgumentNullException(nameof(options)); } public void Prepare(bool normalizeGitDirectory, string currentBranch, bool shouldCleanUpRemotes = false) { + var arguments = options.Value; var authentication = new AuthenticationInfo { Username = arguments.Authentication?.Username, Password = arguments.Authentication?.Password }; - if (!string.IsNullOrWhiteSpace(TargetUrl)) + if (!string.IsNullOrWhiteSpace(GetTargetUrl())) { - var tempRepositoryPath = CalculateTemporaryRepositoryPath(TargetUrl, dynamicRepositoryLocation); + var tempRepositoryPath = CalculateTemporaryRepositoryPath(GetTargetUrl(), arguments.DynamicRepositoryLocation); - dynamicGitRepositoryPath = CreateDynamicRepository(tempRepositoryPath, authentication, TargetUrl, currentBranch); + DynamicGitRepositoryPath = CreateDynamicRepository(tempRepositoryPath, authentication, GetTargetUrl(), currentBranch); } else { @@ -52,44 +59,37 @@ public void Prepare(bool normalizeGitDirectory, string currentBranch, bool shoul CleanupDuplicateOrigin(); } - NormalizeGitDirectory(authentication, currentBranch, GetDotGitDirectory(), IsDynamicGitRepository()); + NormalizeGitDirectory(authentication, currentBranch, GetDotGitDirectoryInternal(), IsDynamicGitRepository); } } } - public TResult WithRepository(Func action) + private string GetDotGitDirectoryInternal() { - using IRepository repo = new Repository(GetDotGitDirectory()); - return action(repo); - } - - public string GetDotGitDirectory() - { - var dotGitDirectory = IsDynamicGitRepository() ? dynamicGitRepositoryPath : Repository.Discover(WorkingDirectory); - - dotGitDirectory = dotGitDirectory?.TrimEnd('/', '\\'); - if (string.IsNullOrEmpty(dotGitDirectory)) - throw new DirectoryNotFoundException("Can't find the .git directory in " + WorkingDirectory); + var gitDirectory = IsDynamicGitRepository ? DynamicGitRepositoryPath : Repository.Discover(GetWorkingDirectory()); - if (dotGitDirectory.Contains(Path.Combine(".git", "worktrees"))) - return Directory.GetParent(Directory.GetParent(dotGitDirectory).FullName).FullName; + gitDirectory = gitDirectory?.TrimEnd('/', '\\'); + if (string.IsNullOrEmpty(gitDirectory)) + throw new DirectoryNotFoundException("Can't find the .git directory in " + gitDirectory); - return dotGitDirectory; + return gitDirectory.Contains(Path.Combine(".git", "worktrees")) + ? Directory.GetParent(Directory.GetParent(gitDirectory).FullName).FullName + : gitDirectory; } - public string GetProjectRootDirectory() + public string GetProjectRootDirectoryInternal() { - log.Info($"IsDynamicGitRepository: {IsDynamicGitRepository()}"); - if (IsDynamicGitRepository()) + log.Info($"IsDynamicGitRepository: {IsDynamicGitRepository}"); + if (IsDynamicGitRepository) { - log.Info($"Returning Project Root as {WorkingDirectory}"); - return WorkingDirectory; + log.Info($"Returning Project Root as {GetWorkingDirectory()}"); + return GetWorkingDirectory(); } - var dotGitDirectory = Repository.Discover(WorkingDirectory); + var dotGitDirectory = Repository.Discover(GetWorkingDirectory()); if (string.IsNullOrEmpty(dotGitDirectory)) - throw new DirectoryNotFoundException($"Can't find the .git directory in {WorkingDirectory}"); + throw new DirectoryNotFoundException($"Can't find the .git directory in {dotGitDirectory}"); using var repo = new Repository(dotGitDirectory); var result = repo.Info.WorkingDirectory; @@ -97,17 +97,11 @@ public string GetProjectRootDirectory() return result; } - public string TargetUrl { get; } - - public string WorkingDirectory { get; } - - private bool IsDynamicGitRepository() => !string.IsNullOrWhiteSpace(dynamicGitRepositoryPath); - private void CleanupDuplicateOrigin() { var remoteToKeep = DefaultRemoteName; - using var repo = new Repository(GetDotGitDirectory()); + using var repo = new Repository(GetDotGitDirectoryInternal()); // check that we have a remote that matches defaultRemoteName if not take the first remote if (!repo.Network.Remotes.Any(remote => remote.Name.Equals(DefaultRemoteName, StringComparison.InvariantCultureIgnoreCase))) @@ -193,7 +187,7 @@ private void NormalizeGitDirectory(AuthenticationInfo auth, string targetBranch, using (log.IndentLog($"Normalizing git directory for branch '{targetBranch}'")) { // Normalize (download branches) before using the branch - GitRepositoryHelper.NormalizeGitDirectory(log, environment, gitDirectory, auth, arguments.NoFetch, targetBranch, isDynamicRepository); + GitRepositoryHelper.NormalizeGitDirectory(log, environment, gitDirectory, auth, options.Value.NoFetch, targetBranch, isDynamicRepository); } } diff --git a/src/GitVersionCore/GitVersionCalculator.cs b/src/GitVersionCore/GitVersionCalculator.cs index 5116440529..ed992d6b61 100644 --- a/src/GitVersionCore/GitVersionCalculator.cs +++ b/src/GitVersionCore/GitVersionCalculator.cs @@ -4,6 +4,7 @@ using GitVersion.Cache; using GitVersion.Logging; using Microsoft.Extensions.Options; +using GitVersion.Extensions; namespace GitVersion { @@ -18,7 +19,7 @@ public class GitVersionCalculator : IGitVersionCalculator private readonly IGitVersionFinder gitVersionFinder; private readonly IGitPreparer gitPreparer; private readonly IVariableProvider variableProvider; - private readonly Arguments arguments; + private readonly IOptions options; public GitVersionCalculator(IFileSystem fileSystem, ILog log, IConfigFileLocator configFileLocator, IConfigProvider configProvider, @@ -34,11 +35,12 @@ public GitVersionCalculator(IFileSystem fileSystem, ILog log, IConfigFileLocator this.gitVersionFinder = gitVersionFinder ?? throw new ArgumentNullException(nameof(gitVersionFinder)); this.gitPreparer = gitPreparer ?? throw new ArgumentNullException(nameof(gitPreparer)); this.variableProvider = variableProvider ?? throw new ArgumentNullException(nameof(variableProvider)); - this.arguments = options.Value; + this.options = options ?? throw new ArgumentNullException(nameof(options)); } public VersionVariables CalculateVersionVariables() { + var arguments = options.Value; var buildServer = buildServerResolver.Resolve(); // Normalize if we are running on build server @@ -119,7 +121,7 @@ private VersionVariables ExecuteInternal(string targetBranch, string commitId, C { var configuration = configProvider.Provide(overrideConfig: overrideConfig); - return gitPreparer.WithRepository(repo => + return gitPreparer.GetDotGitDirectory().WithRepository(repo => { var gitVersionContext = new GitVersionContext(repo, log, targetBranch, configuration, commitId: commitId); var semanticVersion = gitVersionFinder.FindVersion(gitVersionContext); diff --git a/src/GitVersionCore/IGitPreparer.cs b/src/GitVersionCore/IGitPreparer.cs index 690a4f692f..30db2be4f8 100644 --- a/src/GitVersionCore/IGitPreparer.cs +++ b/src/GitVersionCore/IGitPreparer.cs @@ -1,15 +1,11 @@ -using System; -using LibGit2Sharp; - namespace GitVersion { public interface IGitPreparer { void Prepare(bool normalizeGitDirectory, string currentBranch, bool shouldCleanUpRemotes = false); - TResult WithRepository(Func action); - string GetDotGitDirectory(); string GetProjectRootDirectory(); - string TargetUrl { get; } - string WorkingDirectory { get; } + string GetDotGitDirectory(); + string GetTargetUrl(); + string GetWorkingDirectory(); } } diff --git a/src/GitVersionExe/ExecCommand.cs b/src/GitVersionExe/ExecCommand.cs index 301c670a7d..dc55e4b38f 100644 --- a/src/GitVersionExe/ExecCommand.cs +++ b/src/GitVersionExe/ExecCommand.cs @@ -21,16 +21,16 @@ public class ExecCommand : IExecCommand private readonly IBuildServerResolver buildServerResolver; private readonly ILog log; private readonly IGitVersionCalculator gitVersionCalculator; - private readonly Arguments arguments; + private readonly IOptions options; public static readonly string BuildTool = GetMsBuildToolPath(); - public ExecCommand(IFileSystem fileSystem, IBuildServerResolver buildServerResolver, ILog log, IGitVersionCalculator gitVersionCalculator, IOptions arguments) + public ExecCommand(IFileSystem fileSystem, IBuildServerResolver buildServerResolver, ILog log, IGitVersionCalculator gitVersionCalculator, IOptions options) { this.fileSystem = fileSystem ?? throw new ArgumentNullException(nameof(fileSystem)); this.buildServerResolver = buildServerResolver ?? throw new ArgumentNullException(nameof(buildServerResolver)); this.log = log ?? throw new ArgumentNullException(nameof(log)); this.gitVersionCalculator = gitVersionCalculator ?? throw new ArgumentNullException(nameof(gitVersionCalculator)); - this.arguments = arguments.Value; + this.options = options ?? throw new ArgumentNullException(nameof(options)); } public void Execute() @@ -39,6 +39,8 @@ public void Execute() var variables = gitVersionCalculator.CalculateVersionVariables(); + var arguments = options.Value; + switch (arguments.Output) { case OutputType.BuildServer: diff --git a/src/GitVersionExe/GitVersionApp.cs b/src/GitVersionExe/GitVersionApp.cs index c7dfb10c8d..241f99d74b 100644 --- a/src/GitVersionExe/GitVersionApp.cs +++ b/src/GitVersionExe/GitVersionApp.cs @@ -11,20 +11,22 @@ internal class GitVersionApp : IHostedService { private readonly IHostApplicationLifetime applicationLifetime; private readonly IGitVersionExecutor gitVersionExecutor; - private readonly Arguments arguments; + private readonly ILog log; + private readonly IOptions options; public GitVersionApp(IHostApplicationLifetime applicationLifetime, IGitVersionExecutor gitVersionExecutor, ILog log, IOptions options) { - this.arguments = options.Value; + this.options = options ?? throw new ArgumentNullException(nameof(options)); this.applicationLifetime = applicationLifetime ?? throw new ArgumentNullException(nameof(applicationLifetime)); this.gitVersionExecutor = gitVersionExecutor ?? throw new ArgumentNullException(nameof(gitVersionExecutor)); - - log.Verbosity = arguments.Verbosity; + this.log = log ?? throw new ArgumentNullException(nameof(log)); } public Task StartAsync(CancellationToken cancellationToken) { try { + var arguments = options.Value; + log.Verbosity = arguments.Verbosity; gitVersionExecutor.Execute(arguments); } catch (Exception exception)