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 NBGV_GitEngine=Disabled option #586

Merged
merged 8 commits into from
Apr 18, 2023
2 changes: 1 addition & 1 deletion src/NerdBank.GitVersioning/Commands/CloudCommand.cs
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ public void SetBuildVariables(string projectDirectory, IEnumerable<string> metad
activeCloudBuild = CloudBuild.SupportedCloudBuilds[matchingIndex];
}

using var context = GitContext.Create(projectDirectory, writable: alwaysUseLibGit2);
using var context = GitContext.Create(projectDirectory, engine: alwaysUseLibGit2 ? GitContext.Engine.ReadWrite : GitContext.Engine.ReadOnly);
var oracle = new VersionOracle(context, cloudBuild: activeCloudBuild);
if (metadata is not null)
{
Expand Down
42 changes: 42 additions & 0 deletions src/NerdBank.GitVersioning/DisabledGit/DisabledGitContext.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
// Copyright (c) .NET Foundation and Contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

#nullable enable

using System.Diagnostics;

namespace Nerdbank.GitVersioning;

[DebuggerDisplay("{" + nameof(DebuggerDisplay) + ",nq}")]
internal class DisabledGitContext : GitContext
{
public DisabledGitContext(string workingTreePath)
: base(workingTreePath, null)
{
this.VersionFile = new DisabledGitVersionFile(this);
}

public override VersionFile VersionFile { get; }

public override string? GitCommitId => null;

public override bool IsHead => false;

public override DateTimeOffset? GitCommitDate => null;

public override string? HeadCanonicalName => null;

private string DebuggerDisplay => $"\"{this.WorkingTreePath}\" (disabled-git)";

public override void ApplyTag(string name) => throw new NotSupportedException();

public override void Stage(string path) => throw new NotSupportedException();

public override string GetShortUniqueCommitId(int minLength) => "nerdbankdisabled";

public override bool TrySelectCommit(string committish) => true;

internal override int CalculateVersionHeight(VersionOptions? committedVersion, VersionOptions? workingVersion) => 0;

internal override Version GetIdAsVersion(VersionOptions? committedVersion, VersionOptions? workingVersion, int versionHeight) => Version0;
}
22 changes: 22 additions & 0 deletions src/NerdBank.GitVersioning/DisabledGit/DisabledGitVersionFile.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
// Copyright (c) .NET Foundation and Contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

#nullable enable

namespace Nerdbank.GitVersioning;

internal class DisabledGitVersionFile : VersionFile
{
public DisabledGitVersionFile(GitContext context)
: base(context)
{
}

protected new DisabledGitContext Context => (DisabledGitContext)base.Context;

protected override VersionOptions? GetVersionCore(out string? actualDirectory)
{
actualDirectory = null;
return null;
}
}
32 changes: 27 additions & 5 deletions src/NerdBank.GitVersioning/GitContext.cs
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,24 @@ protected GitContext(string workingTreePath, string? dotGitPath)
this.DotGitPath = dotGitPath;
}

public enum Engine
{
/// <summary>
/// Uses the faster and platform independent managed git implementation.
/// </summary>
ReadOnly,

/// <summary>
/// Uses the LibGit2 engine.
/// </summary>
ReadWrite,

/// <summary>
/// Uses a stubbed out engine that doesn't compute versions at all.
/// </summary>
Disabled,
}

/// <summary>
/// Gets the absolute path to the base directory of the git working tree.
/// </summary>
Expand Down Expand Up @@ -110,17 +128,21 @@ public string RepoRelativeProjectDirectory
/// </summary>
/// <param name="path">The path to a directory for which version information is required.</param>
/// <param name="committish">The SHA-1 or ref for a git commit.</param>
/// <param name="writable"><see langword="true"/> if mutating the git repository may be required; <see langword="false" /> otherwise.</param>
/// <param name="engine">The git engine to use.</param>
/// <returns>The newly created <see cref="GitContext"/>.</returns>
public static GitContext Create(string path, string? committish = null, bool writable = false)
public static GitContext Create(string path, string? committish = null, Engine engine = Engine.ReadOnly)
{
Requires.NotNull(path, nameof(path));

if (TryFindGitPaths(path, out string? gitDirectory, out string? workingTreeDirectory, out string? workingTreeRelativePath))
{
GitContext result = writable
? new LibGit2.LibGit2Context(workingTreeDirectory, gitDirectory, committish)
: new Managed.ManagedGitContext(workingTreeDirectory, gitDirectory, committish);
GitContext result = engine switch
{
Engine.Disabled => new DisabledGitContext(workingTreeDirectory),
Engine.ReadWrite => new LibGit2.LibGit2Context(workingTreeDirectory, gitDirectory, committish),
Engine.ReadOnly => new Managed.ManagedGitContext(workingTreeDirectory, gitDirectory, committish),
_ => throw new ArgumentException("Unrecognized value.", nameof(engine)),
};
result.RepoRelativeProjectDirectory = workingTreeRelativePath;
return result;
}
Expand Down
2 changes: 1 addition & 1 deletion src/NerdBank.GitVersioning/ReleaseManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -311,7 +311,7 @@ private LibGit2Context GetRepository(string projectDirectory)
{
// open git repo and use default configuration (in order to commit we need a configured user name and email
// which is most likely configured on a user/system level rather than the repo level.
var context = GitContext.Create(projectDirectory, writable: true);
var context = GitContext.Create(projectDirectory, engine: GitContext.Engine.ReadWrite);
if (!context.IsRepository)
{
this.stderr.WriteLine($"No git repository found above directory '{projectDirectory}'.");
Expand Down
15 changes: 9 additions & 6 deletions src/Nerdbank.GitVersioning.Tasks/GetBuildVersion.cs
Original file line number Diff line number Diff line change
Expand Up @@ -219,21 +219,24 @@ protected override bool ExecuteInner()
Requires.Argument(!containsDotDotSlash, nameof(this.ProjectPathRelativeToGitRepoRoot), "Path must not use ..\\");
}

bool useLibGit2 = false;
GitContext.Engine engine = GitContext.Engine.ReadOnly;
if (!string.IsNullOrWhiteSpace(this.GitEngine))
{
useLibGit2 =
this.GitEngine == "Managed" ? false :
this.GitEngine == "LibGit2" ? true :
throw new ArgumentException("GitEngine property must be set to either \"Managed\" or \"LibGit2\" or left empty.");
engine = this.GitEngine switch
{
"Managed" => GitContext.Engine.ReadOnly,
"LibGit2" => GitContext.Engine.ReadWrite,
"Disabled" => GitContext.Engine.Disabled,
_ => throw new ArgumentException("GitEngine property must be set to either \"Disabled\", \"Managed\" or \"LibGit2\" or left empty."),
};
}

ICloudBuild cloudBuild = CloudBuild.Active;
int? overrideBuildNumberOffset = (this.OverrideBuildNumberOffset == int.MaxValue) ? (int?)null : this.OverrideBuildNumberOffset;
string projectDirectory = this.ProjectPathRelativeToGitRepoRoot is object && this.GitRepoRoot is object
? Path.Combine(this.GitRepoRoot, this.ProjectPathRelativeToGitRepoRoot)
: this.ProjectDirectory;
using var context = GitContext.Create(projectDirectory, writable: useLibGit2);
using var context = GitContext.Create(projectDirectory, engine: engine);
var oracle = new VersionOracle(context, cloudBuild, overrideBuildNumberOffset);
if (!string.IsNullOrEmpty(this.DefaultPublicRelease))
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
<NBGV_InnerGlobalProperties Condition=" '$(GitVersionBaseDirectory)' != '' ">$(NBGV_InnerGlobalProperties)GitVersionBaseDirectory=$(GitVersionBaseDirectory);</NBGV_InnerGlobalProperties>
<NBGV_InnerGlobalProperties Condition=" '$(OverrideBuildNumberOffset)' != '' ">$(NBGV_InnerGlobalProperties)OverrideBuildNumberOffset=$(OverrideBuildNumberOffset);</NBGV_InnerGlobalProperties>
<NBGV_InnerGlobalProperties Condition=" '$(NBGV_PrivateP2PAuxTargets)' != '' ">$(NBGV_InnerGlobalProperties)NBGV_PrivateP2PAuxTargets=$(NBGV_PrivateP2PAuxTargets);</NBGV_InnerGlobalProperties>
<NBGV_InnerGlobalProperties Condition=" '$(NBGV_GitEngine)' != '' ">$(NBGV_InnerGlobalProperties)NBGV_GitEngine=$(NBGV_GitEngine);</NBGV_InnerGlobalProperties>
</PropertyGroup>

<!-- Compile a list of global properties that may vary when a project builds but that would never influence the result of the GetBuildVersion task. -->
Expand Down
10 changes: 5 additions & 5 deletions src/nbgv/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -315,7 +315,7 @@ private static async Task<int> OnInstallCommand(string path, string version, str
return (int)ExitCodes.NoGitRepo;
}

using var context = GitContext.Create(searchPath, writable: true);
using var context = GitContext.Create(searchPath, engine: GitContext.Engine.ReadWrite);
if (!context.IsRepository)
{
Console.Error.WriteLine("No git repo found at or above: \"{0}\"", searchPath);
Expand Down Expand Up @@ -417,7 +417,7 @@ private static Task<int> OnGetVersionCommand(string project, string[] metadata,

string searchPath = GetSpecifiedOrCurrentDirectoryPath(project);

using var context = GitContext.Create(searchPath, writable: AlwaysUseLibGit2);
using var context = GitContext.Create(searchPath, engine: AlwaysUseLibGit2 ? GitContext.Engine.ReadWrite : GitContext.Engine.ReadOnly);
if (!context.IsRepository)
{
Console.Error.WriteLine("No git repo found at or above: \"{0}\"", searchPath);
Expand Down Expand Up @@ -500,7 +500,7 @@ private static Task<int> OnSetVersionCommand(string project, string version)
};

string searchPath = GetSpecifiedOrCurrentDirectoryPath(project);
using var context = GitContext.Create(searchPath, writable: true);
using var context = GitContext.Create(searchPath, engine: GitContext.Engine.ReadWrite);
VersionOptions existingOptions = context.VersionFile.GetVersion(out string actualDirectory);
string versionJsonPath;
if (existingOptions is not null)
Expand Down Expand Up @@ -540,7 +540,7 @@ private static Task<int> OnTagCommand(string project, string versionOrRef)

string searchPath = GetSpecifiedOrCurrentDirectoryPath(project);

using var context = (LibGit2Context)GitContext.Create(searchPath, writable: true);
using var context = (LibGit2Context)GitContext.Create(searchPath, engine: GitContext.Engine.ReadWrite);
if (context is null)
{
Console.Error.WriteLine("No git repo found at or above: \"{0}\"", searchPath);
Expand Down Expand Up @@ -639,7 +639,7 @@ private static Task<int> OnGetCommitsCommand(string project, bool quiet, string

string searchPath = GetSpecifiedOrCurrentDirectoryPath(project);

using var context = (LibGit2Context)GitContext.Create(searchPath, writable: true);
using var context = (LibGit2Context)GitContext.Create(searchPath, engine: GitContext.Engine.ReadWrite);
if (!context.IsRepository)
{
Console.Error.WriteLine("No git repo found at or above: \"{0}\"", searchPath);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,15 +28,15 @@ public class GetVersionBenchmarks
[Benchmark(Baseline = true)]
public void GetVersionLibGit2()
{
using var context = GitContext.Create(GetPath(this.ProjectDirectory), writable: true);
using var context = GitContext.Create(GetPath(this.ProjectDirectory), engine: GitContext.Engine.ReadWrite);
var oracle = new VersionOracle(context, cloudBuild: null);
this.Version = oracle.Version;
}

[Benchmark]
public void GetVersionManaged()
{
using var context = GitContext.Create(GetPath(this.ProjectDirectory), writable: false);
using var context = GitContext.Create(GetPath(this.ProjectDirectory), engine: GitContext.Engine.ReadOnly);
var oracle = new VersionOracle(context, cloudBuild: null);
this.Version = oracle.Version;
}
Expand Down
24 changes: 24 additions & 0 deletions test/Nerdbank.GitVersioning.Tests/BuildIntegrationDisabledTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
// Copyright (c) .NET Foundation and Contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

using Nerdbank.GitVersioning;
using Xunit;
using Xunit.Abstractions;

[Trait("Engine", EngineString)]
[Collection("Build")] // msbuild sets current directory in the process, so we can't have it be concurrent with other build tests.
public class BuildIntegrationDisabledTests : BuildIntegrationTests
{
private const string EngineString = "Disabled";

public BuildIntegrationDisabledTests(ITestOutputHelper logger)
: base(logger)
{
}

protected override GitContext CreateGitContext(string path, string committish = null)
=> GitContext.Create(path, committish, GitContext.Engine.Disabled);

protected override void ApplyGlobalProperties(IDictionary<string, string> globalProperties)
=> globalProperties["NBGV_GitEngine"] = EngineString;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
// Copyright (c) .NET Foundation and Contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

using Xunit;
using Xunit.Abstractions;

[Trait("Engine", EngineString)]
[Collection("Build")] // msbuild sets current directory in the process, so we can't have it be concurrent with other build tests.
public class BuildIntegrationInProjectManagedTests : BuildIntegrationManagedTests
{
public BuildIntegrationInProjectManagedTests(ITestOutputHelper logger)
: base(logger)
{
}

/// <inheritdoc/>
protected override void ApplyGlobalProperties(IDictionary<string, string> globalProperties)
{
base.ApplyGlobalProperties(globalProperties);
globalProperties["NBGV_CacheMode"] = "None";
}
}
24 changes: 24 additions & 0 deletions test/Nerdbank.GitVersioning.Tests/BuildIntegrationLibGit2Tests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
// Copyright (c) .NET Foundation and Contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

using Nerdbank.GitVersioning;
using Xunit;
using Xunit.Abstractions;

[Trait("Engine", EngineString)]
[Collection("Build")] // msbuild sets current directory in the process, so we can't have it be concurrent with other build tests.
public class BuildIntegrationLibGit2Tests : SomeGitBuildIntegrationTests
{
private const string EngineString = "LibGit2";

public BuildIntegrationLibGit2Tests(ITestOutputHelper logger)
: base(logger)
{
}

protected override GitContext CreateGitContext(string path, string committish = null)
=> GitContext.Create(path, committish, GitContext.Engine.ReadWrite);

protected override void ApplyGlobalProperties(IDictionary<string, string> globalProperties)
=> globalProperties["NBGV_GitEngine"] = EngineString;
}
24 changes: 24 additions & 0 deletions test/Nerdbank.GitVersioning.Tests/BuildIntegrationManagedTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
// Copyright (c) .NET Foundation and Contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

using Nerdbank.GitVersioning;
using Xunit;
using Xunit.Abstractions;

[Trait("Engine", EngineString)]
[Collection("Build")] // msbuild sets current directory in the process, so we can't have it be concurrent with other build tests.
public class BuildIntegrationManagedTests : SomeGitBuildIntegrationTests
{
protected const string EngineString = "Managed";

public BuildIntegrationManagedTests(ITestOutputHelper logger)
: base(logger)
{
}

protected override GitContext CreateGitContext(string path, string committish = null)
=> GitContext.Create(path, committish, GitContext.Engine.ReadOnly);

protected override void ApplyGlobalProperties(IDictionary<string, string> globalProperties)
=> globalProperties["NBGV_GitEngine"] = EngineString;
}