Skip to content

Commit

Permalink
[Sideloader] Fix edge cases in version sorting causing a crash
Browse files Browse the repository at this point in the history
  • Loading branch information
ManlyMarco committed Jul 27, 2023
1 parent b3f6ec7 commit 71bd7cb
Show file tree
Hide file tree
Showing 2 changed files with 42 additions and 18 deletions.
38 changes: 26 additions & 12 deletions src/Core_Sideloader/Core.Sideloader.ManifestVersionComparer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,17 +13,19 @@ public int Compare(string x, string y)

public static int CompareVersions(string firstVer, string secondVer)
{
firstVer = firstVer?.Trim().TrimStart('v', 'V', 'r') ?? "";
secondVer = secondVer?.Trim().TrimStart('v', 'V', 'r') ?? "";
firstVer = firstVer?.Trim().TrimStart('v', 'V', 'r', 'R', ' ');
if (string.IsNullOrEmpty(firstVer)) firstVer = "0";
secondVer = secondVer?.Trim().TrimStart('v', 'V', 'r', 'R', ' ');
if (string.IsNullOrEmpty(secondVer)) secondVer = "0";

if (firstVer == secondVer) return 0;

var version = new { First = Tokenize(firstVer), Second = Tokenize(secondVer) };
var limit = Math.Max(version.First.Count, version.Second.Count);
for (var i = 0; i < limit; i++)
{
var first = version.First.ElementAtOrDefault(i) ?? string.Empty;
var second = version.Second.ElementAtOrDefault(i) ?? string.Empty;
var first = version.First.ElementAtOrDefault(i) ?? 0;
var second = version.Second.ElementAtOrDefault(i) ?? 0;
try
{
var result = first.CompareTo(second);
Expand All @@ -32,23 +34,35 @@ public static int CompareVersions(string firstVer, string secondVer)
}
catch (ArgumentException)
{
if (first is string s1 && second is string s2)
{
// Handle invalid characters in strings by comparing them byte by byte
var result = string.CompareOrdinal(s1, s2);
if (result != 0)
return result;
}
var s1 = first.ToString();
var s2 = second.ToString();

if (s1 == "0" && s2 != "0")
return -1;

if (s2 == "0" && s1 != "0")
return 1;

// Handle invalid characters in strings by comparing them byte by byte
var result = string.CompareOrdinal(s1, s2);
if (result != 0)
return result;
}
}
return version.First.Count.CompareTo(version.Second.Count);
return 0;
}

private static ICollection<IComparable> Tokenize(string version)
{
var results = new List<IComparable>(2);
foreach (var part in version.Trim().Split('.', ' ', '-', ',', '_'))
{
if (part.Length == 0)
{
results.Add(0);
continue;
}

// Handle mixed digit + letter parts by splitting them (1.0a -> 1 0 a)
var isDigit = char.IsDigit(part[0]);
var current = part[0].ToString();
Expand Down
22 changes: 16 additions & 6 deletions src/Core_Sideloader/Core.Sideloader.cs
Original file line number Diff line number Diff line change
Expand Up @@ -261,13 +261,23 @@ void AddZipmodToLoad(ZipmodInfo zipmodInfo)
// Handle multiple versions/copies of a single zipmod
if (modGroup.Count > 1)
{
// Order by version if available, else use modified dates (less reliable)
// If versions match, prefer mods inside folders or with more descriptive names so modpacks are preferred
var orderedModsQuery = modGroup.All(x => !string.IsNullOrEmpty(x.Manifest.Version))
? modGroup.OrderByDescending(x => x.Manifest.Version, new ManifestVersionComparer()).ThenByDescending(x => x.FileName.Length)
: modGroup.OrderByDescending(x => x.LastWriteTime);
List<ZipmodInfo> orderedMods;
try
{
// Order by version if available, else use modified dates (less reliable)
// If versions match, prefer mods inside folders or with more descriptive names so modpacks are preferred
var orderedModsQuery = modGroup.All(x => !string.IsNullOrEmpty(x.Manifest.Version))
? modGroup.OrderByDescending(x => x.Manifest.Version, new ManifestVersionComparer()).ThenByDescending(x => x.FileName.Length)
: modGroup.OrderByDescending(x => x.LastWriteTime);

orderedMods = orderedModsQuery.ToList();
}
catch (Exception e)
{
Logger.LogError($"Failed to sort versions of [{modGroup[0].Manifest.GUID}]: [{string.Join("] , [", modGroup.Select(x => x.Manifest.Version).ToArray())}] with error: {e}");
orderedMods = modGroup;
}

var orderedMods = orderedModsQuery.ToList();
zipmod = orderedMods[0];

var modList = string.Join(", ", orderedMods.Skip(1).Select(x => '"' + x.RelativeFileName + '"').ToArray());
Expand Down

0 comments on commit 71bd7cb

Please sign in to comment.