Skip to content

Commit

Permalink
WIP
Browse files Browse the repository at this point in the history
WIP
  • Loading branch information
kekyo committed Jul 2, 2023
1 parent e4af1ea commit 946174d
Show file tree
Hide file tree
Showing 14 changed files with 286 additions and 103 deletions.
32 changes: 32 additions & 0 deletions CenterCLR.RelaxVersioner.Core.Tests/AnalyzerTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
////////////////////////////////////////////////////////////////////////////////////////
//
// RelaxVersioner - Git tag/branch based, full-automatic version information inserter.
// Copyright (c) Kouji Matsui (@kozy_kekyo, @kekyo@mastodon.cloud)
//
// Licensed under Apache-v2: https://opensource.org/licenses/Apache-2.0
//
////////////////////////////////////////////////////////////////////////////////////////

using GitReader;
using GitReader.Structures;
using NUnit.Framework;
using System.IO;
using System.Threading.Tasks;

namespace RelaxVersioner;

public sealed class AnalyzerTests
{
[TestCase("NothingAnyTags1", "0.0.4")]
[TestCase("TagInPrimary", "0.10.1")]
[TestCase("TagInSecondary", "0.20.1")]
public async Task LookupVersionLabel(string repositoryName, string expectedString)
{
using var repository = await Repository.Factory.OpenStructureAsync(
Path.Combine(TestsSetUp.BasePath, repositoryName));

var actual = await Analyzer.LookupVersionLabelAsync(repository.Head!, default);

Assert.AreEqual(expectedString, actual.ToString());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<Nullable>enable</Nullable>
<TargetFrameworks>net48;net5.0;net6.0;net7.0</TargetFrameworks>
<NoWarn>$(NoWarn);NU5104</NoWarn>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.5.0" />
<PackageReference Include="NUnit" Version="3.13.3" />
<PackageReference Include="NUnit3TestAdapter" Version="4.4.2" />
<PackageReference Include="Verify.NUnit" Version="19.13.0" />
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\CenterCLR.RelaxVersioner.Core\CenterCLR.RelaxVersioner.Core.csproj" />
</ItemGroup>

<ItemGroup>
<Folder Include="artifacts\" />
</ItemGroup>

<ItemGroup>
<None Update="artifacts\*.zip">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
</ItemGroup>

</Project>
46 changes: 46 additions & 0 deletions CenterCLR.RelaxVersioner.Core.Tests/TestsSetUp.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
////////////////////////////////////////////////////////////////////////////////////////
//
// RelaxVersioner - Git tag/branch based, full-automatic version information inserter.
// Copyright (c) Kouji Matsui (@kozy_kekyo, @kekyo@mastodon.cloud)
//
// Licensed under Apache-v2: https://opensource.org/licenses/Apache-2.0
//
////////////////////////////////////////////////////////////////////////////////////////

using System;
using System.IO;
using System.IO.Compression;
using VerifyTests;

namespace RelaxVersioner;

public sealed class TestsSetUp
{
public static readonly string BasePath =
Path.Combine("tests", $"{DateTime.Now:yyyyMMdd_HHmmss}");

static TestsSetUp()
{
VerifierSettings.DontScrubDateTimes();

if (!Directory.Exists(BasePath))
{
foreach (var path in Directory.EnumerateFiles(
"artifacts", "*.zip", SearchOption.AllDirectories))
{
var fileName = Path.GetFileNameWithoutExtension(path);
var targetBasePath = Path.Combine(BasePath, fileName);

try
{
Directory.CreateDirectory(targetBasePath);
}
catch
{
}

ZipFile.ExtractToDirectory(path, targetBasePath);
}
}
}
}
Binary file not shown.
Binary file not shown.
Binary file not shown.
172 changes: 108 additions & 64 deletions CenterCLR.RelaxVersioner.Core/Analyzer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@
#nullable enable

using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;

Expand All @@ -20,95 +19,140 @@ namespace RelaxVersioner;

internal static class Analyzer
{
private readonly struct TargetCommit
private readonly struct ScheduledCommit
{
public readonly int StartDepth;
public readonly Commit Commit;
public readonly Commit[] Parents;

public TargetCommit(int startDepth, Commit commit)
public ScheduledCommit(
Commit commit, Commit[] parents)
{
this.StartDepth = startDepth;
this.Commit = commit;
this.Parents = parents;
}

public override string ToString() =>
$"StartDepth={this.StartDepth}, {this.Commit}";
public void Deconstruct(
out Commit commit, out Commit[] parents)
{
commit = this.Commit;
parents = this.Parents;
}
}

public static async Task<Version> LookupVersionLabelAsync(
Branch targetBranch, CancellationToken ct)
private static Version IncrementLastVersionComponent(
Version version)
{
var topCommit = await targetBranch.GetHeadCommitAsync(ct);

var reached = new HashSet<Commit>();
var scheduled = new Stack<TargetCommit>();
scheduled.Push(new TargetCommit(0, topCommit));

var mainDepth = 0;
if (version.Revision.HasValue)
{
return new(
version.Major,
version.Minor!.Value,
version.Build!.Value,
version.Revision.Value + 1);
}
else if (version.Build.HasValue)
{
return new(
version.Major,
version.Minor!.Value,
version.Build.Value + 1);
}
else if (version.Minor.HasValue)
{
return new(
version.Major,
version.Minor.Value + 1);
}
else
{
return new(
version.Major + 1);
}
}

while (scheduled.Count >= 1)
private static async Task<Version> LookupVersionLabelAsync(
Commit commit, Dictionary<Commit, Version> reached, CancellationToken ct)
{
var scheduledStack = new Stack<ScheduledCommit>();
var version = Version.Default;

// Trace back to the parent commit repeatedly with the following conditions:
// * If the commit has already been reached, get its version.
// * If there is a recognizable version string in the tag, get its version.
// * If the parent commit does not exist, get the default version.
// * If other than the above, push the commit on the stack for later processing in reverse order.
while (true)
{
// Extract an analysis commit.
var entry = scheduled.Pop();

var currentCommit = entry.Commit;
var currentDepth = entry.StartDepth;
if (reached.TryGetValue(commit, out var v1))
{
version = v1;
break;
}

while (true)
var found = false;
foreach (var tag in commit.Tags)
{
// Rejoined parent branch.
if (!reached.Add(currentCommit))
if (Version.TryParse(tag.Name, out var v2))
{
version = v2;
reached.Add(commit, version);
found = true;
break;
}
}
if (found)
{
break;
}

// If found be applied tags at this commit:
if (currentCommit.Tags.Count >= 1)
{
var filteredTags = currentCommit.Tags.
Select(tag => Version.TryParse(tag.Name, out var version) ? (Version?)version : null).
Where(version => version.HasValue).
Select(version => Utilities.IncrementLastVersionComponent(version!.Value, currentDepth)).
ToArray();

// Found first valid tag.
if (filteredTags.Length >= 1)
{
return filteredTags[0];
}
}

// Found parents.
if (await currentCommit.GetParentCommitsAsync(ct) is { Length: >= 1 } parents)
{
// Dive parent commit.
currentDepth++;
var parents = await commit.GetParentCommitsAsync(ct);
if (parents.Length == 0)
{
reached.Add(commit, version);
break;
}

// Next commit is a primary parent.
currentCommit = parents[0];
scheduledStack.Push(new(commit, parents));
commit = parents[0];
}

// Enqueue analysis scheduling if it has multiple parents.
foreach (var parentCommit in parents.Skip(1))
{
scheduled.Push(new TargetCommit(currentDepth, parentCommit));
}
}
// Bottom of branch.
else
// As long as there are commits stacked on the stack,
// retrieve a commit from the stack, and if there is more than one parent commit for that commit:
// * Recursively get versions from parent commits other than the primary one.
// * Compare the versions obtained and store the largest version.
// * Increment the version and make it the version of the current commit.
while (scheduledStack.Count >= 1)
{
var (c, pcs) = scheduledStack.Pop();
if (pcs.Length >= 2)
{
for (var index = 1; index < pcs.Length; index++)
{
// Save depth if it's on boarding the main branch.
if (mainDepth == 0)
var v = await LookupVersionLabelAsync(pcs[index], reached, ct);
if (v.CompareTo(version) > 0)
{
mainDepth = currentDepth;
version = v;
}

// Goes to next scheduled commit.
break;
}
}

version = IncrementLastVersionComponent(version);
reached.Add(c, version);
}

// Finally got the main branch depth.
return Utilities.IncrementLastVersionComponent(Version.Default, mainDepth);
return version;
}

public static Task<Version> LookupVersionLabelAsync(
Commit commit, CancellationToken ct) =>
LookupVersionLabelAsync(commit, new(), ct);

public static async Task<Version> LookupVersionLabelAsync(
Branch branch, CancellationToken ct)
{
// Get the head commit for the branch.
var headCommit = await branch.GetHeadCommitAsync(ct);

return await LookupVersionLabelAsync(headCommit, new(), ct);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
</PropertyGroup>

<ItemGroup>
<PackageReference Include="GitReader" Version="1.0.0" />
<PackageReference Include="GitReader" Version="1.1.0" />
<PackageReference Include="NamingFormatter" Version="2.2.0" />
<PackageReference Include="Microsoft.NETFramework.ReferenceAssemblies" Version="1.0.3" PrivateAssets="All" />
<PackageReference Include="RelaxVersioner" Version="2.16.0" PrivateAssets="all" />
Expand Down
7 changes: 2 additions & 5 deletions CenterCLR.RelaxVersioner.Core/Processor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,16 +10,16 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.IO;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using System.Xml.Linq;

using GitReader;
using GitReader.Structures;

using RelaxVersioner.Writers;
using System.Threading;

namespace RelaxVersioner;

Expand All @@ -40,9 +40,6 @@ public sealed class ProcessorContext

public sealed class Processor
{
private static readonly Branch[] emptyBranches = Array.Empty<Branch>();
private static readonly Tag[] emptyTags = Array.Empty<Tag>();

private readonly Logger logger;
private readonly Dictionary<string, WriterBase> writers;

Expand Down
12 changes: 12 additions & 0 deletions CenterCLR.RelaxVersioner.Core/Properties/AssemblyInfo.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
////////////////////////////////////////////////////////////////////////////////////////
//
// RelaxVersioner - Git tag/branch based, full-automatic version information inserter.
// Copyright (c) Kouji Matsui (@kozy_kekyo, @kekyo@mastodon.cloud)
//
// Licensed under Apache-v2: https://opensource.org/licenses/Apache-2.0
//
////////////////////////////////////////////////////////////////////////////////////////

using System.Runtime.CompilerServices;

[assembly: InternalsVisibleTo("CenterCLR.RelaxVersioner.Core.Tests")]
Loading

0 comments on commit 946174d

Please sign in to comment.