Skip to content

Commit

Permalink
Implement with LibGit2Sharp
Browse files Browse the repository at this point in the history
  • Loading branch information
bording committed Dec 22, 2023
1 parent d51ebef commit 43e7b4f
Show file tree
Hide file tree
Showing 5 changed files with 35 additions and 121 deletions.
15 changes: 0 additions & 15 deletions MinVer.Lib/Commit.cs

This file was deleted.

58 changes: 19 additions & 39 deletions MinVer.Lib/Git.cs
Original file line number Diff line number Diff line change
@@ -1,52 +1,32 @@
using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using System.IO;
using LibGit2Sharp;

namespace MinVer.Lib;

internal static class Git
{
public static bool IsWorkingDirectory(string directory, ILogger log) => GitCommand.TryRun("status --short", directory, log, out _);

public static bool TryGetHead(string directory, [NotNullWhen(returnValue: true)] out Commit? head, ILogger log)
public static bool TryGetRepository(string directory, [NotNullWhen(returnValue: true)] out Repository? repository)
{
head = null;

if (!GitCommand.TryRun("log --pretty=format:\"%H %P\"", directory, log, out var output))
{
return false;
}

var lines = output.Split(new[] { '\r', '\n', }, StringSplitOptions.RemoveEmptyEntries);

if (lines.Length == 0)
{
return false;
}

var commits = new Dictionary<string, Commit>();
var valid = false;
repository = null;

foreach (var shas in lines
.Select(line => line.Split(new[] { ' ', }, StringSplitOptions.RemoveEmptyEntries)))
while (!valid && directory is not null)
{
commits.GetOrAdd(shas[0], () => new Commit(shas[0]))
.Parents.AddRange(shas.Skip(1).Select(parentSha => commits.GetOrAdd(parentSha, () => new Commit(parentSha))));
var repoPath = Path.Combine(directory, ".git");
valid = Repository.IsValid(repoPath);

if (valid)
{
repository = new Repository(repoPath);
return true;
}
else
{
directory = Path.GetDirectoryName(directory);
}
}

head = commits.Values.First();

return true;
return false;
}

public static IEnumerable<(string Name, string Sha)> GetTags(string directory, ILogger log) =>
GitCommand.TryRun("show-ref --tags --dereference", directory, log, out var output)
? output
.Split(new[] { '\r', '\n', }, StringSplitOptions.RemoveEmptyEntries)
.Select(line => line.Split([' ',], 2))
.Select(tokens => (tokens[1][10..].RemoveFromEnd("^{}"), tokens[0]))
: Enumerable.Empty<(string, string)>();

private static string RemoveFromEnd(this string text, string value) =>
text.EndsWith(value, StringComparison.OrdinalIgnoreCase) ? text[..^value.Length] : text;
}
55 changes: 0 additions & 55 deletions MinVer.Lib/GitCommand.cs

This file was deleted.

1 change: 1 addition & 0 deletions MinVer.Lib/MinVer.Lib.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
</PropertyGroup>

<ItemGroup>
<PackageReference Include="LibGit2Sharp" Version="0.28.0" />
<PackageReference Include="Microsoft.SourceLink.GitHub" Version="1.1.1" PrivateAssets="All" />
<PackageReference Include="NuGet.Versioning" Version="6.8.0" />
</ItemGroup>
Expand Down
27 changes: 15 additions & 12 deletions MinVer.Lib/Versioner.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using LibGit2Sharp;

namespace MinVer.Lib;

Expand Down Expand Up @@ -33,7 +34,7 @@ public static Version GetVersion(string workDir, string tagPrefix, MajorMinor mi

private static (Version Version, int? Height) GetVersion(string workDir, string tagPrefix, List<string> defaultPreReleaseIdentifiers, ILogger log)
{
if (!Git.IsWorkingDirectory(workDir, log))
if (!Git.TryGetRepository(workDir, out var repository))
{
var version = new Version(defaultPreReleaseIdentifiers);

Expand All @@ -42,7 +43,7 @@ private static (Version Version, int? Height) GetVersion(string workDir, string
return (version, default);
}

if (!Git.TryGetHead(workDir, out var head, log))
if (repository.Info.IsHeadUnborn)
{
var version = new Version(defaultPreReleaseIdentifiers);

Expand All @@ -51,12 +52,14 @@ private static (Version Version, int? Height) GetVersion(string workDir, string
return (version, default);
}

var tags = Git.GetTags(workDir, log);
var tags = repository.Tags;

var orderedCandidates = GetCandidates(head, tags, tagPrefix, defaultPreReleaseIdentifiers, log)
var orderedCandidates = GetCandidates(repository.Head.Commits.First(), tags, tagPrefix, defaultPreReleaseIdentifiers, log)
.OrderBy(candidate => candidate.Version)
.ThenByDescending(candidate => candidate.Index).ToList();

repository.Dispose();

var tagWidth = log.IsDebugEnabled ? orderedCandidates.Max(candidate => candidate.Tag.Length) : 0;
var versionWidth = log.IsDebugEnabled ? orderedCandidates.Max(candidate => candidate.Version.ToString().Length) : 0;
var heightWidth = log.IsDebugEnabled ? orderedCandidates.Max(candidate => candidate.Height).ToString(CultureInfo.CurrentCulture).Length : 0;
Expand All @@ -77,19 +80,19 @@ private static (Version Version, int? Height) GetVersion(string workDir, string
return (selectedCandidate.Version, selectedCandidate.Height);
}

private static List<Candidate> GetCandidates(Commit head, IEnumerable<(string Name, string Sha)> tags, string tagPrefix, List<string> defaultPreReleaseIdentifiers, ILogger log)
private static List<Candidate> GetCandidates(Commit head, TagCollection tags, string tagPrefix, List<string> defaultPreReleaseIdentifiers, ILogger log)
{
var tagsAndVersions = new List<(string Name, string Sha, Version Version)>();

foreach (var (name, sha) in tags)
foreach (var tag in tags)
{
if (Version.TryParse(name, out var version, tagPrefix))
if (Version.TryParse(tag.FriendlyName, out var version, tagPrefix))
{
tagsAndVersions.Add((name, sha, version));
tagsAndVersions.Add((tag.FriendlyName, tag.PeeledTarget.Sha, version));
}
else
{
_ = log.IsDebugEnabled && log.Debug($"Ignoring non-version tag {{ Name: {name}, Sha: {sha} }}.");
_ = log.IsDebugEnabled && log.Debug($"Ignoring non-version tag {{ Name: {tag.FriendlyName}, Sha: {tag.PeeledTarget.Sha} }}.");
}
}

Expand Down Expand Up @@ -143,14 +146,14 @@ .. tagsAndVersions

if (log.IsTraceEnabled)
{
_ = log.Trace($"Commit {item.Commit} has {item.Commit.Parents.Count} parent(s):");
_ = log.Trace($"Commit {item.Commit} has {item.Commit.Parents.Count()} parent(s):");
foreach (var parent in item.Commit.Parents)
{
_ = log.Trace($"- {parent}");
}
}

foreach (var parent in ((IEnumerable<Commit>)item.Commit.Parents).Reverse())
foreach (var parent in item.Commit.Parents.Reverse())
{
itemsToCheck.Push((parent, item.Height + 1, item.Commit));
}
Expand All @@ -175,6 +178,6 @@ private sealed class Candidate(Commit commit, int height, string tag, Version ve
public override string ToString() => this.ToString(0, 0, 0);

public string ToString(int tagWidth, int versionWidth, int heightWidth) =>
$"{{ {nameof(this.Commit)}: {this.Commit.ShortSha}, {nameof(this.Tag)}: {$"'{this.Tag}',".PadRight(tagWidth + 3)} {nameof(this.Version)}: {$"{this.Version},".PadRight(versionWidth + 1)} {nameof(this.Height)}: {this.Height.ToString(CultureInfo.CurrentCulture).PadLeft(heightWidth)} }}";
$"{{ {nameof(this.Commit)}: {this.Commit.Sha[..Math.Min(7, this.Commit.Sha.Length)]}, {nameof(this.Tag)}: {$"'{this.Tag}',".PadRight(tagWidth + 3)} {nameof(this.Version)}: {$"{this.Version},".PadRight(versionWidth + 1)} {nameof(this.Height)}: {this.Height.ToString(CultureInfo.CurrentCulture).PadLeft(heightWidth)} }}";
}
}

0 comments on commit 43e7b4f

Please sign in to comment.