Restructure solution layout by module
Some checks failed
Docs CI / lint-and-preview (push) Has been cancelled

This commit is contained in:
root
2025-10-28 15:10:40 +02:00
parent 4e3e575db5
commit 68da90a11a
4103 changed files with 192899 additions and 187024 deletions

View File

@@ -0,0 +1,264 @@
namespace StellaOps.Concelier.Merge.Comparers;
using System;
using StellaOps.Concelier.Normalization.Distro;
public sealed class NevraComparer : IComparer<Nevra>, IComparer<string>
{
public static NevraComparer Instance { get; } = new();
private NevraComparer()
{
}
public int Compare(string? x, string? y)
{
if (ReferenceEquals(x, y))
{
return 0;
}
if (x is null)
{
return -1;
}
if (y is null)
{
return 1;
}
var xParsed = Nevra.TryParse(x, out var xNevra);
var yParsed = Nevra.TryParse(y, out var yNevra);
if (xParsed && yParsed)
{
return Compare(xNevra, yNevra);
}
if (xParsed)
{
return 1;
}
if (yParsed)
{
return -1;
}
return string.Compare(x, y, StringComparison.Ordinal);
}
public int Compare(Nevra? x, Nevra? y)
{
if (ReferenceEquals(x, y))
{
return 0;
}
if (x is null)
{
return -1;
}
if (y is null)
{
return 1;
}
var compare = string.Compare(x.Name, y.Name, StringComparison.Ordinal);
if (compare != 0)
{
return compare;
}
compare = string.Compare(x.Architecture ?? string.Empty, y.Architecture ?? string.Empty, StringComparison.Ordinal);
if (compare != 0)
{
return compare;
}
compare = x.Epoch.CompareTo(y.Epoch);
if (compare != 0)
{
return compare;
}
compare = RpmVersionComparer.Compare(x.Version, y.Version);
if (compare != 0)
{
return compare;
}
compare = RpmVersionComparer.Compare(x.Release, y.Release);
if (compare != 0)
{
return compare;
}
return string.Compare(x.Original, y.Original, StringComparison.Ordinal);
}
}
internal static class RpmVersionComparer
{
public static int Compare(string? left, string? right)
{
left ??= string.Empty;
right ??= string.Empty;
var i = 0;
var j = 0;
while (true)
{
var leftHasTilde = SkipToNextSegment(left, ref i);
var rightHasTilde = SkipToNextSegment(right, ref j);
if (leftHasTilde || rightHasTilde)
{
if (leftHasTilde && rightHasTilde)
{
continue;
}
return leftHasTilde ? -1 : 1;
}
var leftEnd = i >= left.Length;
var rightEnd = j >= right.Length;
if (leftEnd || rightEnd)
{
if (leftEnd && rightEnd)
{
return 0;
}
return leftEnd ? -1 : 1;
}
var leftDigit = char.IsDigit(left[i]);
var rightDigit = char.IsDigit(right[j]);
if (leftDigit && !rightDigit)
{
return 1;
}
if (!leftDigit && rightDigit)
{
return -1;
}
int compare;
if (leftDigit)
{
compare = CompareNumericSegment(left, ref i, right, ref j);
}
else
{
compare = CompareAlphaSegment(left, ref i, right, ref j);
}
if (compare != 0)
{
return compare;
}
}
}
private static bool SkipToNextSegment(string value, ref int index)
{
var sawTilde = false;
while (index < value.Length)
{
var current = value[index];
if (current == '~')
{
sawTilde = true;
index++;
break;
}
if (char.IsLetterOrDigit(current))
{
break;
}
index++;
}
return sawTilde;
}
private static int CompareNumericSegment(string value, ref int index, string other, ref int otherIndex)
{
var start = index;
while (index < value.Length && char.IsDigit(value[index]))
{
index++;
}
var otherStart = otherIndex;
while (otherIndex < other.Length && char.IsDigit(other[otherIndex]))
{
otherIndex++;
}
var trimmedStart = start;
while (trimmedStart < index && value[trimmedStart] == '0')
{
trimmedStart++;
}
var otherTrimmedStart = otherStart;
while (otherTrimmedStart < otherIndex && other[otherTrimmedStart] == '0')
{
otherTrimmedStart++;
}
var length = index - trimmedStart;
var otherLength = otherIndex - otherTrimmedStart;
if (length != otherLength)
{
return length.CompareTo(otherLength);
}
var comparison = value.AsSpan(trimmedStart, length)
.CompareTo(other.AsSpan(otherTrimmedStart, otherLength), StringComparison.Ordinal);
if (comparison != 0)
{
return comparison;
}
return 0;
}
private static int CompareAlphaSegment(string value, ref int index, string other, ref int otherIndex)
{
var start = index;
while (index < value.Length && char.IsLetter(value[index]))
{
index++;
}
var otherStart = otherIndex;
while (otherIndex < other.Length && char.IsLetter(other[otherIndex]))
{
otherIndex++;
}
var length = index - start;
var otherLength = otherIndex - otherStart;
var comparison = value.AsSpan(start, length)
.CompareTo(other.AsSpan(otherStart, otherLength), StringComparison.Ordinal);
if (comparison != 0)
{
return comparison;
}
return 0;
}
}