Skip to content

Commit

Permalink
WIP
Browse files Browse the repository at this point in the history
WIP
  • Loading branch information
kekyo committed Jul 1, 2023
1 parent e4af1ea commit 82b10df
Show file tree
Hide file tree
Showing 14 changed files with 292 additions and 95 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.
170 changes: 114 additions & 56 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,154 @@ namespace RelaxVersioner;

internal static class Analyzer
{
private readonly struct TargetCommit
private static Version IncrementLastVersionComponent(
Version version, int value)
{
public readonly int StartDepth;
public readonly Commit Commit;

public TargetCommit(int startDepth, Commit commit)
if (version.Revision.HasValue)
{
this.StartDepth = startDepth;
this.Commit = commit;
return new(
version.Major,
version.Minor!.Value,
version.Build!.Value,
version.Revision.Value + value);
}
else if (version.Build.HasValue)
{
return new(
version.Major,
version.Minor!.Value,
version.Build.Value + value);
}
else if (version.Minor.HasValue)
{
return new(
version.Major,
version.Minor.Value + value);
}
else
{
return new(
version.Major + value);
}

public override string ToString() =>
$"StartDepth={this.StartDepth}, {this.Commit}";
}

public static async Task<Version> LookupVersionLabelAsync(
Branch targetBranch, CancellationToken ct)
Commit headCommit, CancellationToken ct)
{
var topCommit = await targetBranch.GetHeadCommitAsync(ct);
// Keep a set of commit versions that have been explored.
var reached = new Dictionary<Commit, Version>();

// Schedule queue to hold commits to be analyzed.
var scheduledQueue = new Queue<Commit>();

var reached = new HashSet<Commit>();
var scheduled = new Stack<TargetCommit>();
scheduled.Push(new TargetCommit(0, topCommit));
// Head commit as bootstrap.
scheduledQueue.Enqueue(headCommit);

var mainDepth = 0;
// Final version.
var version = Version.Default;

while (scheduled.Count >= 1)
// A schedule queue exists.
while (scheduledQueue.Count >= 1)
{
// Extract an analysis commit.
var entry = scheduled.Pop();

var currentCommit = entry.Commit;
var currentDepth = entry.StartDepth;
// Remove a commit from the queue.
// Explore from this commit toward the parent.
var commit = scheduledQueue.Dequeue();

// Stack the group of commits passed during the analysis.
var traversedStack = new Stack<Commit>();

// Found candidate version.
var candidateVersion = default(Version)!;

while (true)
{
// Rejoined parent branch.
if (!reached.Add(currentCommit))
// If this commit has been analyzed.
if (reached.TryGetValue(commit, out var v1))
{
// This commit version is finalized.
// The stack contains commits up to one previous commit, so proceed with a pre-depth.
candidateVersion = IncrementLastVersionComponent(v1, 1);
break;
}

// If found be applied tags at this commit:
if (currentCommit.Tags.Count >= 1)
// Save this commit to the stack as passed.
traversedStack.Push(commit);

// If a tag meaning version is applied to this commit:
var found = false;
foreach (var tag in commit.Tags)
{
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)
if (Version.TryParse(tag.Name, out var v2))
{
return filteredTags[0];
candidateVersion = v2;
found = true;
break;
}
}

// Found parents.
if (await currentCommit.GetParentCommitsAsync(ct) is { Length: >= 1 } parents)
if (found)
{
// Dive parent commit.
currentDepth++;
// This commit version is finalized.
break;
}

// Next commit is a primary parent.
currentCommit = parents[0];
// Obtain parent commits.
var parents = await commit.GetParentCommitsAsync(ct);

// Enqueue analysis scheduling if it has multiple parents.
foreach (var parentCommit in parents.Skip(1))
// No parent commitments exist.
if (parents.Length == 0)
{
// The version of this commit is the bottom of the branch.
candidateVersion = Version.Default;
break;
}

// There are multiple parent commits:
if (parents.Length >= 2)
{
// Insert non-primaries into the schedule queue for later analysis.
for (var index = 1; index < parents.Length; index++)
{
scheduled.Push(new TargetCommit(currentDepth, parentCommit));
scheduledQueue.Enqueue(parents[index]);
}
}
// Bottom of branch.
else

// The next commit to be analyzed is the primary parent commit.
commit = parents[0];
}

// Determine the version of the commits stored in the stack.
if (traversedStack.Count >= 1)
{
while (true)
{
// Save depth if it's on boarding the main branch.
if (mainDepth == 0)
commit = traversedStack.Pop();
reached.Add(commit, candidateVersion);

if (traversedStack.Count == 0)
{
mainDepth = currentDepth;
break;
}

// Goes to next scheduled commit.
break;

candidateVersion = IncrementLastVersionComponent(candidateVersion, 1);
}
}

// Acquire the one with the larger obtained version.
if (candidateVersion.CompareTo(version) > 0)
{
version = candidateVersion;
}
}

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

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, 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 82b10df

Please sign in to comment.