Skip to content

Commit 8c59b05

Browse files
authored
Merge pull request marticliment#3333 from marticliment/float-versions-to-structs
2 parents 735d2b3 + 272a6fd commit 8c59b05

File tree

31 files changed

+176
-119
lines changed

31 files changed

+176
-119
lines changed

src/UniGetUI.Core.IconStore/IconCacheEngine.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -318,7 +318,7 @@ private static bool ValidateByVersion(CacheableIcon icon, string versionPath)
318318
{
319319
try
320320
{
321-
return File.Exists(versionPath) && CoreTools.GetVersionStringAsFloat(File.ReadAllText(versionPath)) >= CoreTools.GetVersionStringAsFloat(icon.Version);
321+
return File.Exists(versionPath) && CoreTools.VersionStringToStruct(File.ReadAllText(versionPath)) >= CoreTools.VersionStringToStruct(icon.Version);
322322
}
323323
catch (Exception e)
324324
{

src/UniGetUI.Core.Tools.Tests/ToolsTests.cs

Lines changed: 17 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -114,19 +114,24 @@ public async Task TestFileSizeLoader(string uri, long expectedSize)
114114
}
115115

116116
[Theory]
117-
[InlineData("1000.0", 1000.0, 0.0)]
118-
[InlineData("2.4", 2.4, 0.001)]
119-
[InlineData("33a.12-beta", 33.12, 0.0)]
120-
[InlineData("0", 0.0, 0.0)]
121-
[InlineData("", -1, 0.0)]
122-
[InlineData("dfgfdsgdfg", -1, 0.0)]
123-
[InlineData("-12", 12.0, 0.0)]
124-
[InlineData("4.0.0.1.0", 4.001, 0.01)]
125-
[InlineData("2024.30.04.1223", 2024.30041223, 0.0)]
126-
[InlineData("0.0", 0.0, 0.0)]
127-
public void TestGetVersionStringAsFloat(string version, double expected, double tolerance)
117+
[InlineData("1000.0", 1000, 0, 0, 0)]
118+
[InlineData("2.4", 2, 4, 0, 0)]
119+
[InlineData("33a.12-beta5", 33, 12, 5, 0)]
120+
[InlineData("0", 0,0,0,0)]
121+
[InlineData("", 0,0,0,0)]
122+
[InlineData("dfgfdsgdfg", 0,0,0,0)]
123+
[InlineData("-12", 12,0,0,0)]
124+
[InlineData("4.0.0.1.0", 4,0,0,10)]
125+
[InlineData("4.0.0.1.05", 4,0,0,105)]
126+
[InlineData("2024.30.04.1223", 2024, 30, 4, 1223)]
127+
[InlineData("0.0", 0,0,0,0)]
128+
public void TestGetVersionStringAsFloat(string version, int i1, int i2, int i3, int i4)
128129
{
129-
Assert.Equal(expected, CoreTools.GetVersionStringAsFloat(version), tolerance);
130+
CoreTools.Version v = CoreTools.VersionStringToStruct(version);
131+
Assert.Equal(i1, v.Major);
132+
Assert.Equal(i2, v.Minor);
133+
Assert.Equal(i3, v.Patch);
134+
Assert.Equal(i4, v.Remainder);
130135
}
131136

132137
[Theory]

src/UniGetUI.Core.Tools/Tools.cs

Lines changed: 80 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -315,53 +315,104 @@ public static async Task<long> GetFileSizeAsyncAsLong(Uri? url)
315315
return 0;
316316
}
317317

318+
319+
public struct Version: IComparable
320+
{
321+
public static readonly Version Null = new(-1, -1, -1, -1);
322+
323+
public readonly int Major;
324+
public readonly int Minor;
325+
public readonly int Patch;
326+
public readonly int Remainder;
327+
328+
public Version(int major, int minor = 0, int patch = 0, int remainder = 0)
329+
{
330+
Major = major;
331+
Minor = minor;
332+
Patch = patch;
333+
Remainder = remainder;
334+
}
335+
336+
public int CompareTo(object? other_)
337+
{
338+
if (other_ is not Version other) return 0;
339+
340+
int major = Major.CompareTo(other.Major);
341+
if (major != 0) return major;
342+
343+
int minor = Minor.CompareTo(other.Minor);
344+
if (minor != 0) return minor;
345+
346+
int patch = Patch.CompareTo(other.Patch);
347+
if (patch != 0) return patch;
348+
349+
return Remainder.CompareTo(other.Remainder);
350+
}
351+
352+
public static bool operator ==(Version left, Version right)
353+
=> left.CompareTo(right) == 0;
354+
355+
public static bool operator !=(Version left, Version right)
356+
=> left.CompareTo(right) != 0;
357+
358+
public static bool operator >=(Version left, Version right)
359+
=> left.CompareTo(right) >= 0;
360+
361+
public static bool operator <=(Version left, Version right)
362+
=> left.CompareTo(right) <= 0;
363+
364+
public static bool operator >(Version left, Version right)
365+
=> left.CompareTo(right) > 0;
366+
367+
public static bool operator <(Version left, Version right)
368+
=> left.CompareTo(right) < 0;
369+
370+
public bool Equals(Version other)
371+
=> Major == other.Major && Minor == other.Minor && Patch == other.Patch && Remainder == other.Remainder;
372+
373+
public override bool Equals(object? obj)
374+
=> obj is Version other && Equals(other);
375+
376+
public override int GetHashCode()
377+
=> HashCode.Combine(Major, Minor, Patch, Remainder);
378+
}
379+
318380
/// <summary>
319381
/// Converts a string into a double floating-point number.
320382
/// </summary>
321383
/// <param name="Version">Any string</param>
322384
/// <returns>The best approximation of the string as a Version</returns>
323-
public static double GetVersionStringAsFloat(string Version)
385+
public static Version VersionStringToStruct(string Version)
324386
{
325387
try
326388
{
327-
string _ver = "";
328-
bool _dotAdded = false;
329-
foreach (char _char in Version)
389+
char[] separators = ['.', '-', '/', '#'];
390+
string[] versionItems = ["", "", "", ""];
391+
392+
int dotCount = 0;
393+
bool first = true;
394+
395+
foreach (char c in Version)
330396
{
331-
if (char.IsDigit(_char))
332-
{
333-
_ver += _char;
334-
}
335-
else if (_char == '.')
336-
{
337-
if (!_dotAdded)
338-
{
339-
_ver += _char;
340-
_dotAdded = true;
341-
}
342-
}
397+
if (char.IsDigit(c)) versionItems[dotCount] += c;
398+
else if (!first && separators.Contains(c)) if (dotCount < 3) dotCount++;
399+
first = false;
343400
}
344401

345-
double res = -1;
346-
if (_ver is not "" and not ".")
402+
int[] numbers = { 0, 0, 0, 0 };
403+
for (int i = 0; i < 4; i++)
347404
{
348-
try
349-
{
350-
double val = double.Parse(_ver, CultureInfo.InvariantCulture);
351-
return val;
352-
}
353-
catch
354-
{
355-
// ignored
356-
}
405+
if (int.TryParse(versionItems[i], out int val))
406+
numbers[i] = val;
357407
}
358408

359-
return res;
409+
var ver = new Version(numbers[0], numbers[1], numbers[2], numbers[3]);
410+
return ver;
360411
}
361412
catch
362413
{
363414
Logger.Warn($"Failed to parse version {Version} to float");
364-
return -1;
415+
return CoreTools.Version.Null;
365416
}
366417
}
367418

src/UniGetUI.Interface.BackgroundApi/BackgroundApi.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -201,7 +201,7 @@ public void BuildV1WidgetsApi()
201201
continue; // Do not show already processed packages on queue
202202

203203
string icon = $"http://localhost:7058/widgets/v2/get_icon_for_package?packageId={HttpUtility.UrlEncode(package.Id)}&packageSource={HttpUtility.UrlEncode(package.Source.Name)}&token={ApiTokenHolder.Token}";
204-
packages.Append($"{package.Name.Replace('|', '-')}|{package.Id}|{package.Version}|{package.NewVersion}|{package.Source.AsString_DisplayName}|{package.Manager.Name}|{icon}&&");
204+
packages.Append($"{package.Name.Replace('|', '-')}|{package.Id}|{package.VersionString}|{package.NewVersionString}|{package.Source.AsString_DisplayName}|{package.Manager.Name}|{icon}&&");
205205
}
206206

207207
string pkgs_ = packages.ToString();

src/UniGetUI.PAckageEngine.Interfaces/IPackage.cs

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
using System.ComponentModel;
2+
using UniGetUI.Core.Tools;
23
using UniGetUI.Interface.Enums;
34
using UniGetUI.PackageEngine.Classes.Serializable;
45
using UniGetUI.PackageEngine.Structs;
@@ -12,12 +13,12 @@ public interface IPackage : INotifyPropertyChanged, IEquatable<IPackage>
1213
public bool IsChecked { get; set; }
1314
public string Name { get; }
1415
public string Id { get; }
15-
public string Version { get; }
16-
public double VersionAsFloat { get; }
17-
public double NewVersionAsFloat { get; }
16+
public string VersionString { get; }
17+
public CoreTools.Version NormalizedVersion { get; }
18+
public CoreTools.Version NormalizedNewVersion { get; }
1819
public IManagerSource Source { get; }
1920
public IPackageManager Manager { get; }
20-
public string NewVersion { get; }
21+
public string NewVersionString { get; }
2122
public bool IsUpgradable { get; }
2223
public ref OverridenInstallationOptions OverridenOptions { get; }
2324
public string AutomationName { get; }

src/UniGetUI.PackageEngine.Managers.Cargo/Cargo.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,7 @@ protected override IReadOnlyList<Package> FindPackages_UnSafe(string query)
103103
var package = Packages[i];
104104
try
105105
{
106-
var versionInfo = CratesIOClient.GetManifestVersion(package.Id, package.Version);
106+
var versionInfo = CratesIOClient.GetManifestVersion(package.Id, package.VersionString);
107107
if (versionInfo.bin_names?.Length > 0)
108108
{
109109
BinPackages.Add(package);

src/UniGetUI.PackageEngine.Managers.Cargo/Helpers/CargoPkgDetailsHelper.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ protected override void GetDetails_UnSafe(IPackageDetails details)
3838
var categories = manifest.categories?.Select(c => c.category);
3939
details.Tags = [.. keywords, .. categories];
4040

41-
var versionData = manifest.versions.Where((v) => v.num == details.Package.Version).First();
41+
var versionData = manifest.versions.Where((v) => v.num == details.Package.VersionString).First();
4242

4343
details.Author = versionData.published_by?.name;
4444
details.License = versionData.license;

src/UniGetUI.PackageEngine.Managers.Cargo/Helpers/CargoPkgOperationHelper.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ internal sealed class CargoPkgOperationHelper(Cargo cargo) : PackagePkgOperation
88
{
99
protected override IReadOnlyList<string> _getOperationParameters(IPackage package, IInstallationOptions options, OperationType operation)
1010
{
11-
var version = options.Version == string.Empty ? package.Version : options.Version;
11+
var version = options.Version == string.Empty ? package.VersionString : options.Version;
1212
List<string> parameters = operation switch
1313
{
1414
OperationType.Install => [Manager.Properties.InstallVerb, "--version", version, package.Id],

src/UniGetUI.PackageEngine.Managers.Chocolatey/Chocolatey.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ namespace UniGetUI.PackageEngine.Managers.ChocolateyManager
1919
public class Chocolatey : BaseNuGet
2020
{
2121
public static new string[] FALSE_PACKAGE_IDS = ["Directory", "", "Did", "Features?", "Validation", "-", "being", "It", "Error", "L'accs", "Maximum", "This", "Output is package name ", "operable", "Invalid"];
22-
public static new string[] FALSE_PACKAGE_VERSIONS = ["", "Did", "Features?", "Validation", "-", "being", "It", "Error", "L'accs", "Maximum", "This", "packages", "current version", "installed version", "is", "program", "validations", "argument", "no"];
22+
public static new string[] FALSE_PACKAGE_VERSIONS = ["", "of", "Did", "Features?", "Validation", "-", "being", "It", "Error", "L'accs", "Maximum", "This", "packages", "current version", "installed version", "is", "program", "validations", "argument", "no"];
2323

2424
public Chocolatey()
2525
{

src/UniGetUI.PackageEngine.Managers.Generic.NuGet/BaseNuGet.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ public sealed override void Initialize()
3434
private struct SearchResult
3535
{
3636
public string version;
37-
public double version_float;
37+
public CoreTools.Version version_float;
3838
public string id;
3939
}
4040

@@ -82,7 +82,7 @@ protected sealed override IReadOnlyList<Package> FindPackages_UnSafe(string quer
8282

8383
string id = Regex.Match(match.Value, "Id='([^<>']+)'").Groups[1].Value;
8484
string version = Regex.Match(match.Value, "Version='([^<>']+)'").Groups[1].Value;
85-
double float_version = CoreTools.GetVersionStringAsFloat(version);
85+
var float_version = CoreTools.VersionStringToStruct(version);
8686
// Match title = Regex.Match(match.Value, "<title[ \\\"\\=A-Za-z0-9]+>([^<>]+)<\\/title>");
8787

8888
if (AlreadyProcessedPackages.TryGetValue(id, out var value) && value.version_float >= float_version)

src/UniGetUI.PackageEngine.Managers.Generic.NuGet/BaseNuGetDetailsHelper.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -136,7 +136,7 @@ protected override void GetDetails_UnSafe(IPackageDetails details)
136136
}
137137

138138
// Logger.Debug($"A native icon with Url={possibleIconUrl.Groups[1].Value} was found");
139-
return new CacheableIcon(new Uri(possibleIconUrl.Groups[1].Value), package.Version);
139+
return new CacheableIcon(new Uri(possibleIconUrl.Groups[1].Value), package.VersionString);
140140
}
141141

142142
protected override IReadOnlyList<Uri> GetScreenshots_UnSafe(IPackage package)

src/UniGetUI.PackageEngine.Managers.Generic.NuGet/Internal/NuGetManifestLoader.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ internal static class NuGetManifestLoader
1515
/// <returns>A Uri object</returns>
1616
public static Uri GetManifestUrl(IPackage package)
1717
{
18-
return new Uri($"{package.Source.Url}/Packages(Id='{package.Id}',Version='{package.Version}')");
18+
return new Uri($"{package.Source.Url}/Packages(Id='{package.Id}',Version='{package.VersionString}')");
1919
}
2020

2121
/// <summary>
@@ -25,7 +25,7 @@ public static Uri GetManifestUrl(IPackage package)
2525
/// <returns>A Uri object</returns>
2626
public static Uri GetNuPkgUrl(IPackage package)
2727
{
28-
return new Uri($"{package.Source.Url}/package/{package.Id}/{package.Version}");
28+
return new Uri($"{package.Source.Url}/package/{package.Id}/{package.VersionString}");
2929
}
3030

3131
/// <summary>
@@ -49,7 +49,7 @@ public static Uri GetNuPkgUrl(IPackage package)
4949
{
5050
client.DefaultRequestHeaders.UserAgent.ParseAdd(CoreData.UserAgentString);
5151
HttpResponseMessage response = client.GetAsync(PackageManifestUrl).GetAwaiter().GetResult();
52-
if (!response.IsSuccessStatusCode && package.Version.EndsWith(".0"))
52+
if (!response.IsSuccessStatusCode && package.VersionString.EndsWith(".0"))
5353
{
5454
response = client.GetAsync(new Uri(PackageManifestUrl.ToString().Replace(".0')", "')"))).GetAwaiter().GetResult();
5555
}

src/UniGetUI.PackageEngine.Managers.Npm/Helpers/NpmPkgDetailsHelper.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ protected override void GetDetails_UnSafe(IPackageDetails details)
5151

5252
details.Publisher = (contents?["maintainers"] as JsonArray)?[0]?.ToString();
5353
details.Author = contents?["author"]?.ToString();
54-
details.UpdateDate = contents?["time"]?[contents?["dist-tags"]?["latest"]?.ToString() ?? details.Package.Version]?.ToString();
54+
details.UpdateDate = contents?["time"]?[contents?["dist-tags"]?["latest"]?.ToString() ?? details.Package.VersionString]?.ToString();
5555

5656
if (Uri.TryCreate(contents?["dist"]?["tarball"]?.ToString() ?? "", UriKind.RelativeOrAbsolute, out var installerUrl))
5757
details.InstallerUrl = installerUrl;

src/UniGetUI.PackageEngine.Managers.Npm/Helpers/NpmPkgOperationHelper.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,8 @@ public NpmPkgOperationHelper(Npm manager) : base(manager) { }
1010
protected override IReadOnlyList<string> _getOperationParameters(IPackage package, IInstallationOptions options, OperationType operation)
1111
{
1212
List<string> parameters = operation switch {
13-
OperationType.Install => [Manager.Properties.InstallVerb, $"{package.Id}@{(options.Version == string.Empty? package.Version: options.Version)}"],
14-
OperationType.Update => [Manager.Properties.UpdateVerb, $"{package.Id}@{package.NewVersion}"],
13+
OperationType.Install => [Manager.Properties.InstallVerb, $"{package.Id}@{(options.Version == string.Empty? package.VersionString: options.Version)}"],
14+
OperationType.Update => [Manager.Properties.UpdateVerb, $"{package.Id}@{package.NewVersionString}"],
1515
OperationType.Uninstall => [Manager.Properties.UninstallVerb, package.Id],
1616
_ => throw new InvalidDataException("Invalid package operation")
1717
};

src/UniGetUI.PackageEngine.Managers.Scoop/Scoop.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -185,9 +185,9 @@ protected override IReadOnlyList<Package> GetAvailableUpdates_UnSafe()
185185
Dictionary<string, IPackage> InstalledPackages = [];
186186
foreach (IPackage InstalledPackage in GetInstalledPackages())
187187
{
188-
if (!InstalledPackages.ContainsKey(InstalledPackage.Id + "." + InstalledPackage.Version))
188+
if (!InstalledPackages.ContainsKey(InstalledPackage.Id + "." + InstalledPackage.VersionString))
189189
{
190-
InstalledPackages.Add(InstalledPackage.Id + "." + InstalledPackage.Version, InstalledPackage);
190+
InstalledPackages.Add(InstalledPackage.Id + "." + InstalledPackage.VersionString, InstalledPackage);
191191
}
192192
}
193193

src/UniGetUI.PackageEngine.Managers.WinGet/Helpers/WinGetPkgOperationHelper.cs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -43,9 +43,9 @@ protected override IReadOnlyList<string> _getOperationParameters(IPackage packag
4343
_ => []
4444
});
4545

46-
if (operation is OperationType.Uninstall && package.Version != "Unknown" && package.OverridenOptions.WinGet_SpecifyVersion is not false)
46+
if (operation is OperationType.Uninstall && package.VersionString != "Unknown" && package.OverridenOptions.WinGet_SpecifyVersion is not false)
4747
{
48-
parameters.AddRange(["--version", $"\"{package.Version}\""]);
48+
parameters.AddRange(["--version", $"\"{package.VersionString}\""]);
4949
}
5050
else if (operation is OperationType.Install && options.Version != "")
5151
{
@@ -192,11 +192,11 @@ protected override OperationVeredict _getOperationResult(
192192

193193
private static void MarkUpgradeAsDone(IPackage package)
194194
{
195-
Settings.SetDictionaryItem<string, string>("WinGetAlreadyUpgradedPackages", package.Id, package.NewVersion);
195+
Settings.SetDictionaryItem<string, string>("WinGetAlreadyUpgradedPackages", package.Id, package.NewVersionString);
196196
}
197197

198198
public static bool UpdateAlreadyInstalled(IPackage package)
199199
{
200-
return Settings.GetDictionaryItem<string, string>("WinGetAlreadyUpgradedPackages", package.Id) == package.NewVersion;
200+
return Settings.GetDictionaryItem<string, string>("WinGetAlreadyUpgradedPackages", package.Id) == package.NewVersionString;
201201
}
202202
}

src/UniGetUI.PackageEngine.Operations/PackageOperations.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -218,7 +218,7 @@ protected override void Initialize()
218218
Package.Manager.Name + "\nInstallation options: " + Options.ToString();
219219

220220
Metadata.Title = CoreTools.Translate("{package} Update", new Dictionary<string, object?> { { "package", Package.Name } });
221-
Metadata.Status = CoreTools.Translate("{0} is being updated to version {1}", Package.Name, Package.NewVersion);
221+
Metadata.Status = CoreTools.Translate("{0} is being updated to version {1}", Package.Name, Package.NewVersionString);
222222
Metadata.SuccessTitle = CoreTools.Translate("Update succeeded");
223223
Metadata.SuccessMessage = CoreTools.Translate("{package} was updated successfully", new Dictionary<string, object?> { { "package", Package.Name } });
224224
Metadata.FailureTitle = CoreTools.Translate("Update failed", new Dictionary<string, object?> { { "package", Package.Name } });

src/UniGetUI.PackageEngine.PackageLoader/UpgradablePackagesLoader.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,8 @@ public UpgradablePackagesLoader(IReadOnlyList<IPackageManager> managers)
3131

3232
protected override async Task<bool> IsPackageValid(IPackage package)
3333
{
34-
if (package.Version == package.NewVersion) return false;
35-
if (await package.HasUpdatesIgnoredAsync(package.NewVersion))
34+
if (package.VersionString == package.NewVersionString) return false;
35+
if (await package.HasUpdatesIgnoredAsync(package.NewVersionString))
3636
{
3737
IgnoredPackages[package.Id] = package;
3838
return false;

src/UniGetUI.PackageEngine.PackageManagerClasses/Manager/Helpers/BasePkgDetailsHelper.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ public IReadOnlyList<string> GetVersions(IPackage package)
7272
string? iconUrl = IconDatabase.Instance.GetIconUrlForId(package.GetIconId());
7373
if (iconUrl is not null)
7474
{
75-
return new CacheableIcon(new Uri(iconUrl), package.Version);
75+
return new CacheableIcon(new Uri(iconUrl), package.VersionString);
7676
}
7777

7878
return null;

0 commit comments

Comments
 (0)