From 17c8d8ba796081e31148d06fa4bbdf68501034fb Mon Sep 17 00:00:00 2001 From: Max Date: Thu, 19 Dec 2024 20:02:41 -0600 Subject: [PATCH 1/9] Allow skipping minor updates of a package --- .../IInstallationOptions.cs | 1 + .../IPackage.cs | 6 ++++++ .../InstallationOptions.cs | 2 ++ .../UpgradablePackagesLoader.cs | 1 + .../Packages/Classes/InstallationOptions.cs | 5 ++++- .../Packages/InvalidImportedPackage.cs | 5 +++++ .../Packages/Package.cs | 17 +++++++++++++++++ .../SerializableInstallationOptions.cs | 2 ++ .../Pages/DialogPages/InstallOptions.xaml | 16 +++++++++++++--- .../Pages/DialogPages/InstallOptions.xaml.cs | 3 +++ 10 files changed, 54 insertions(+), 4 deletions(-) diff --git a/src/UniGetUI.PAckageEngine.Interfaces/IInstallationOptions.cs b/src/UniGetUI.PAckageEngine.Interfaces/IInstallationOptions.cs index 26bebb766..733d9b4b3 100644 --- a/src/UniGetUI.PAckageEngine.Interfaces/IInstallationOptions.cs +++ b/src/UniGetUI.PAckageEngine.Interfaces/IInstallationOptions.cs @@ -10,6 +10,7 @@ public interface IInstallationOptions public bool InteractiveInstallation { get; set; } public bool RunAsAdministrator { get; set; } public string Version { get; set; } + public bool SkipMinorUpdates { get; set; } public Architecture? Architecture { get; set; } public PackageScope? InstallationScope { get; set; } public List CustomParameters { get; set; } diff --git a/src/UniGetUI.PAckageEngine.Interfaces/IPackage.cs b/src/UniGetUI.PAckageEngine.Interfaces/IPackage.cs index 5f73d00fc..df394d533 100644 --- a/src/UniGetUI.PAckageEngine.Interfaces/IPackage.cs +++ b/src/UniGetUI.PAckageEngine.Interfaces/IPackage.cs @@ -142,6 +142,12 @@ public interface IPackage : INotifyPropertyChanged, IEquatable /// public bool NewerVersionIsInstalled(); + /// + /// Checks whether a new update of this package is a minor update or not (0.0.x) + /// + /// False if the update is a major update or the update doesn't exist, true if it's a minor update + public bool IsUpdateMinor(); + public SerializablePackage_v1 AsSerializable(); public SerializableIncompatiblePackage_v1 AsSerializable_Incompatible(); diff --git a/src/UniGetUI.PackageEngine.Package/InstallationOptions.cs b/src/UniGetUI.PackageEngine.Package/InstallationOptions.cs index f18f6fc53..f209f754e 100644 --- a/src/UniGetUI.PackageEngine.Package/InstallationOptions.cs +++ b/src/UniGetUI.PackageEngine.Package/InstallationOptions.cs @@ -96,6 +96,7 @@ public void FromSerialized(SerializableInstallationOptions_v1 options) RunAsAdministrator = options.RunAsAdministrator; CustomInstallLocation = options.CustomInstallLocation; Version = options.Version; + SkipMinorUpdates = options.SkipMinorUpdates; PreRelease = options.PreRelease; if (options.Architecture != "" && CommonTranslations.InvertedArchNames.ContainsKey(options.Architecture)) Architecture = CommonTranslations.InvertedArchNames[options.Architecture]; @@ -117,6 +118,7 @@ public SerializableInstallationOptions_v1 Serialized() options.CustomInstallLocation = CustomInstallLocation; options.PreRelease = PreRelease; options.Version = Version; + options.SkipMinorUpdates = SkipMinorUpdates; if (Architecture != null) options.Architecture = CommonTranslations.ArchNames[Architecture.Value]; if (InstallationScope != null) diff --git a/src/UniGetUI.PackageEngine.PackageLoader/UpgradablePackagesLoader.cs b/src/UniGetUI.PackageEngine.PackageLoader/UpgradablePackagesLoader.cs index 5f57e67e8..40337ea48 100644 --- a/src/UniGetUI.PackageEngine.PackageLoader/UpgradablePackagesLoader.cs +++ b/src/UniGetUI.PackageEngine.PackageLoader/UpgradablePackagesLoader.cs @@ -29,6 +29,7 @@ protected override async Task IsPackageValid(IPackage package) IgnoredPackages[package.Id] = package; return false; } + if (package.AsSerializable().InstallationOptions.SkipMinorUpdates && package.IsUpdateMinor()) return false; if (package.NewerVersionIsInstalled()) return false; return true; } diff --git a/src/UniGetUI.PackageEngine.PackageManagerClasses/Packages/Classes/InstallationOptions.cs b/src/UniGetUI.PackageEngine.PackageManagerClasses/Packages/Classes/InstallationOptions.cs index 9d190fece..309b592e6 100644 --- a/src/UniGetUI.PackageEngine.PackageManagerClasses/Packages/Classes/InstallationOptions.cs +++ b/src/UniGetUI.PackageEngine.PackageManagerClasses/Packages/Classes/InstallationOptions.cs @@ -22,6 +22,7 @@ public class InstallationOptions : IInstallationOptions public bool InteractiveInstallation { get; set; } public bool RunAsAdministrator { get; set; } public string Version { get; set; } = ""; + public bool SkipMinorUpdates { get; set; } public Architecture? Architecture { get; set; } public PackageScope? InstallationScope { get; set; } public List CustomParameters { get; set; } = []; @@ -113,6 +114,7 @@ public void FromSerializable(SerializableInstallationOptions_v1 options) RunAsAdministrator = options.RunAsAdministrator; CustomInstallLocation = options.CustomInstallLocation; Version = options.Version; + SkipMinorUpdates = options.SkipMinorUpdates; PreRelease = options.PreRelease; if (options.Architecture != "" && CommonTranslations.InvertedArchNames.TryGetValue(options.Architecture, out var name)) @@ -148,7 +150,8 @@ public SerializableInstallationOptions_v1 AsSerializable() RunAsAdministrator = RunAsAdministrator, CustomInstallLocation = CustomInstallLocation, PreRelease = PreRelease, - Version = Version + Version = Version, + SkipMinorUpdates = SkipMinorUpdates }; if (Architecture is not null) { diff --git a/src/UniGetUI.PackageEngine.PackageManagerClasses/Packages/InvalidImportedPackage.cs b/src/UniGetUI.PackageEngine.PackageManagerClasses/Packages/InvalidImportedPackage.cs index 4b8982203..a5c6ea305 100644 --- a/src/UniGetUI.PackageEngine.PackageManagerClasses/Packages/InvalidImportedPackage.cs +++ b/src/UniGetUI.PackageEngine.PackageManagerClasses/Packages/InvalidImportedPackage.cs @@ -166,6 +166,11 @@ public bool NewerVersionIsInstalled() return false; } + public bool IsUpdateMinor() + { + return false; + } + public async Task RemoveFromIgnoredUpdatesAsync() { return; diff --git a/src/UniGetUI.PackageEngine.PackageManagerClasses/Packages/Package.cs b/src/UniGetUI.PackageEngine.PackageManagerClasses/Packages/Package.cs index b8fd0f5f7..97301019e 100644 --- a/src/UniGetUI.PackageEngine.PackageManagerClasses/Packages/Package.cs +++ b/src/UniGetUI.PackageEngine.PackageManagerClasses/Packages/Package.cs @@ -284,6 +284,23 @@ public virtual bool NewerVersionIsInstalled() return PackageCacher.NewerVersionIsInstalled(this); } + public virtual bool IsUpdateMinor() + { + if (!IsUpgradable) return false; + string[] VersionSplit = Version.Split("."); + string[] NewVersionSplit = NewVersion.Split("."); + + // When in doubt, return false + if (VersionSplit.Length < 3 || NewVersionSplit.Length < 3) return false; + + if ( + VersionSplit[0] != NewVersionSplit[0] || + VersionSplit[1] != NewVersionSplit[1] + ) return false; // Major update + + return VersionSplit[2].CompareTo(NewVersionSplit[2]) < 0; + } + public virtual SerializablePackage_v1 AsSerializable() { return new SerializablePackage_v1 diff --git a/src/UniGetUI.PackageEngine.Serializable/SerializableInstallationOptions.cs b/src/UniGetUI.PackageEngine.Serializable/SerializableInstallationOptions.cs index 3100a3b9f..fac30f6c1 100644 --- a/src/UniGetUI.PackageEngine.Serializable/SerializableInstallationOptions.cs +++ b/src/UniGetUI.PackageEngine.Serializable/SerializableInstallationOptions.cs @@ -11,6 +11,7 @@ public class SerializableInstallationOptions_v1 public bool PreRelease { get; set; } public string CustomInstallLocation { get; set; } = ""; public string Version { get; set; } = ""; + public bool SkipMinorUpdates { get; set; } public SerializableInstallationOptions_v1 Copy() { @@ -25,6 +26,7 @@ public SerializableInstallationOptions_v1 Copy() PreRelease = PreRelease, RunAsAdministrator = RunAsAdministrator, Version = Version, + SkipMinorUpdates = SkipMinorUpdates, }; } } diff --git a/src/UniGetUI/Pages/DialogPages/InstallOptions.xaml b/src/UniGetUI/Pages/DialogPages/InstallOptions.xaml index 41a4b4d67..1b3231958 100644 --- a/src/UniGetUI/Pages/DialogPages/InstallOptions.xaml +++ b/src/UniGetUI/Pages/DialogPages/InstallOptions.xaml @@ -63,9 +63,19 @@ - - - + + + + + + + + + + + + + diff --git a/src/UniGetUI/Pages/DialogPages/InstallOptions.xaml.cs b/src/UniGetUI/Pages/DialogPages/InstallOptions.xaml.cs index 026372b97..b3ed95278 100644 --- a/src/UniGetUI/Pages/DialogPages/InstallOptions.xaml.cs +++ b/src/UniGetUI/Pages/DialogPages/InstallOptions.xaml.cs @@ -83,6 +83,8 @@ public InstallOptionsPage(IPackage package, OperationType operation, Serializabl } } + SkipMinorUpdatesCheckbox.IsChecked = Options.SkipMinorUpdates; + if (Package.Manager.Capabilities.SupportsCustomVersions) { _ = LoadVersions(); @@ -186,6 +188,7 @@ public async Task GetUpdatedOptions() { Options.Version = ""; } + Options.SkipMinorUpdates = SkipMinorUpdatesCheckbox?.IsChecked ?? false; if (IgnoreUpdatesCheckbox?.IsChecked ?? false) { From 6e8f1861585fd7e2ebe5dc2ea9ced4fde354a0c7 Mon Sep 17 00:00:00 2001 From: Max Date: Thu, 19 Dec 2024 20:11:10 -0600 Subject: [PATCH 2/9] Fix vcpkg installation option files not being saved correctly --- .../Packages/Classes/InstallationOptions.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/UniGetUI.PackageEngine.PackageManagerClasses/Packages/Classes/InstallationOptions.cs b/src/UniGetUI.PackageEngine.PackageManagerClasses/Packages/Classes/InstallationOptions.cs index 309b592e6..95f316cc5 100644 --- a/src/UniGetUI.PackageEngine.PackageManagerClasses/Packages/Classes/InstallationOptions.cs +++ b/src/UniGetUI.PackageEngine.PackageManagerClasses/Packages/Classes/InstallationOptions.cs @@ -169,7 +169,8 @@ public SerializableInstallationOptions_v1 AsSerializable() private FileInfo GetPackageOptionsFile() { - string optionsFileName = Package.Manager.Name + "." + Package.Id + ".json"; + string optionsFileName = Package.Manager.Name + "." + Package.Id.Split(":")[0] + ".json"; + Logger.Warn(optionsFileName); return new FileInfo(Path.Join(CoreData.UniGetUIInstallationOptionsDirectory, optionsFileName)); } From a6dafeff23ff12b749f3c1198bff271bcfc9839b Mon Sep 17 00:00:00 2001 From: mrixner <100489307+mrixner@users.noreply.github.com> Date: Thu, 19 Dec 2024 20:13:11 -0600 Subject: [PATCH 3/9] Remove debugging `Logger.Warn` --- .../Packages/Classes/InstallationOptions.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/UniGetUI.PackageEngine.PackageManagerClasses/Packages/Classes/InstallationOptions.cs b/src/UniGetUI.PackageEngine.PackageManagerClasses/Packages/Classes/InstallationOptions.cs index 95f316cc5..29ef400c5 100644 --- a/src/UniGetUI.PackageEngine.PackageManagerClasses/Packages/Classes/InstallationOptions.cs +++ b/src/UniGetUI.PackageEngine.PackageManagerClasses/Packages/Classes/InstallationOptions.cs @@ -170,7 +170,6 @@ public SerializableInstallationOptions_v1 AsSerializable() private FileInfo GetPackageOptionsFile() { string optionsFileName = Package.Manager.Name + "." + Package.Id.Split(":")[0] + ".json"; - Logger.Warn(optionsFileName); return new FileInfo(Path.Join(CoreData.UniGetUIInstallationOptionsDirectory, optionsFileName)); } From 126141e5c27efa41898e57fa13e7c2daae761a2f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mart=C3=AD=20Climent?= Date: Tue, 7 Jan 2025 23:28:23 +0100 Subject: [PATCH 4/9] Make Yaml deserializer ignore non-existing fields --- src/UniGetUI/Pages/SoftwarePages/PackageBundlesPage.cs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/UniGetUI/Pages/SoftwarePages/PackageBundlesPage.cs b/src/UniGetUI/Pages/SoftwarePages/PackageBundlesPage.cs index c675a5075..de2ab74b4 100644 --- a/src/UniGetUI/Pages/SoftwarePages/PackageBundlesPage.cs +++ b/src/UniGetUI/Pages/SoftwarePages/PackageBundlesPage.cs @@ -18,6 +18,7 @@ using UniGetUI.PackageEngine.Operations; using UniGetUI.PackageEngine.PackageClasses; using UniGetUI.Pages.DialogPages; +using YamlDotNet.Serialization; namespace UniGetUI.Interface.SoftwarePages { @@ -604,8 +605,9 @@ public async Task AddFromBundle(string content, BundleFormatType format) } else if (format is BundleFormatType.YAML) { - YamlDotNet.Serialization.IDeserializer deserializer = - new YamlDotNet.Serialization.DeserializerBuilder() + IDeserializer deserializer = + new DeserializerBuilder() + .IgnoreUnmatchedProperties() .Build(); DeserializedData = await Task.Run(() => deserializer.Deserialize(content)); } From 3321291f1c5cf913573088dab204bf7454b9de50 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mart=C3=AD=20Climent?= Date: Tue, 7 Jan 2025 23:29:33 +0100 Subject: [PATCH 5/9] iterate export_version value to 2.1 --- src/UniGetUI/Pages/SoftwarePages/PackageBundlesPage.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/UniGetUI/Pages/SoftwarePages/PackageBundlesPage.cs b/src/UniGetUI/Pages/SoftwarePages/PackageBundlesPage.cs index de2ab74b4..91b3f77ce 100644 --- a/src/UniGetUI/Pages/SoftwarePages/PackageBundlesPage.cs +++ b/src/UniGetUI/Pages/SoftwarePages/PackageBundlesPage.cs @@ -546,7 +546,7 @@ public async Task SaveFile() public static async Task CreateBundle(IEnumerable unsorted_packages, BundleFormatType formatType = BundleFormatType.JSON) { SerializableBundle_v1 exportable = new(); - exportable.export_version = 2.0; + exportable.export_version = 2.1; List packages = unsorted_packages.ToList(); packages.Sort(Comparison); @@ -596,7 +596,6 @@ int Comparison(IPackage x, IPackage y) public async Task AddFromBundle(string content, BundleFormatType format) { - // Deserialize data SerializableBundle_v1? DeserializedData; if (format is BundleFormatType.JSON) From ca120b11e2f77aa5661a2b352f8a715e87d45350 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mart=C3=AD=20Climent?= Date: Tue, 7 Jan 2025 23:39:22 +0100 Subject: [PATCH 6/9] Add a warning on the log if the file versions do not match --- .../SerializableBundle_v1.cs | 5 +++++ .../Pages/SoftwarePages/PackageBundlesPage.cs | 13 ++++++++++--- 2 files changed, 15 insertions(+), 3 deletions(-) diff --git a/src/UniGetUI.PackageEngine.Serializable/SerializableBundle_v1.cs b/src/UniGetUI.PackageEngine.Serializable/SerializableBundle_v1.cs index a928fabce..8c7ef3404 100644 --- a/src/UniGetUI.PackageEngine.Serializable/SerializableBundle_v1.cs +++ b/src/UniGetUI.PackageEngine.Serializable/SerializableBundle_v1.cs @@ -1,5 +1,10 @@ namespace UniGetUI.PackageEngine.Classes.Serializable { + public class SerializableBundle_Data + { + public const double ExpectedVersion = 2.1; + } + public class SerializableBundle_v1 { public double export_version { get; set; } = -1; diff --git a/src/UniGetUI/Pages/SoftwarePages/PackageBundlesPage.cs b/src/UniGetUI/Pages/SoftwarePages/PackageBundlesPage.cs index 91b3f77ce..fe9a3daf7 100644 --- a/src/UniGetUI/Pages/SoftwarePages/PackageBundlesPage.cs +++ b/src/UniGetUI/Pages/SoftwarePages/PackageBundlesPage.cs @@ -459,11 +459,17 @@ public async Task OpenFromFile(string? file = null) string fileContent = await File.ReadAllTextAsync(file); - await AddFromBundle(fileContent, formatType); + double open_version = await AddFromBundle(fileContent, formatType); HasUnsavedChanges = false; DialogHelper.HideLoadingDialog(); + if ((int)(open_version*10) != (int)(SerializableBundle_Data.ExpectedVersion*10)) + { // Check only up to first decimal digit + Logger.Warn($"The loaded bundle \"{file}\" is based on schema version {open_version}, " + + $"while this UniGetUI build expects version {SerializableBundle_Data.ExpectedVersion}." + + $"\nThis should not be a problem if packages show up, but be careful"); + } } catch (Exception ex) { @@ -574,7 +580,7 @@ int Comparison(IPackage x, IPackage y) else if (formatType == BundleFormatType.YAML) { - YamlDotNet.Serialization.ISerializer serializer = new YamlDotNet.Serialization.SerializerBuilder() + ISerializer serializer = new SerializerBuilder() .Build(); ExportableData = serializer.Serialize(exportable); } @@ -594,7 +600,7 @@ int Comparison(IPackage x, IPackage y) return ExportableData; } - public async Task AddFromBundle(string content, BundleFormatType format) + public async Task AddFromBundle(string content, BundleFormatType format) { // Deserialize data SerializableBundle_v1? DeserializedData; @@ -641,6 +647,7 @@ public async Task AddFromBundle(string content, BundleFormatType format) await PEInterface.PackageBundlesLoader.AddPackagesAsync(packages); + return DeserializedData.export_version; } public static IPackage PackageFromSerializable(SerializablePackage_v1 raw_package) From 946e761d218b89546a2ffc985bceefea21107100 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mart=C3=AD=20Climent?= Date: Tue, 7 Jan 2025 23:40:32 +0100 Subject: [PATCH 7/9] update comment --- src/UniGetUI/Pages/SoftwarePages/PackageBundlesPage.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/UniGetUI/Pages/SoftwarePages/PackageBundlesPage.cs b/src/UniGetUI/Pages/SoftwarePages/PackageBundlesPage.cs index fe9a3daf7..891770f63 100644 --- a/src/UniGetUI/Pages/SoftwarePages/PackageBundlesPage.cs +++ b/src/UniGetUI/Pages/SoftwarePages/PackageBundlesPage.cs @@ -465,7 +465,7 @@ public async Task OpenFromFile(string? file = null) DialogHelper.HideLoadingDialog(); if ((int)(open_version*10) != (int)(SerializableBundle_Data.ExpectedVersion*10)) - { // Check only up to first decimal digit + { // Check only up to first decimal digit, prevent floating point precision error. Logger.Warn($"The loaded bundle \"{file}\" is based on schema version {open_version}, " + $"while this UniGetUI build expects version {SerializableBundle_Data.ExpectedVersion}." + $"\nThis should not be a problem if packages show up, but be careful"); From de20f1ceec4e7944de68e8f4de1099a042242c4e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mart=C3=AD=20Climent?= Date: Tue, 7 Jan 2025 23:48:10 +0100 Subject: [PATCH 8/9] Do not serialize the entire package for this. Call InstallationOptions.FromPackage, that will leverage internal caches --- .../UpgradablePackagesLoader.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/UniGetUI.PackageEngine.PackageLoader/UpgradablePackagesLoader.cs b/src/UniGetUI.PackageEngine.PackageLoader/UpgradablePackagesLoader.cs index ca5ba0ee1..7cf1630f8 100644 --- a/src/UniGetUI.PackageEngine.PackageLoader/UpgradablePackagesLoader.cs +++ b/src/UniGetUI.PackageEngine.PackageLoader/UpgradablePackagesLoader.cs @@ -3,6 +3,7 @@ using UniGetUI.Core.SettingsEngine; using UniGetUI.Interface.Enums; using UniGetUI.PackageEngine.Interfaces; +using UniGetUI.PackageEngine.PackageClasses; namespace UniGetUI.PackageEngine.PackageLoader { @@ -31,7 +32,7 @@ protected override async Task IsPackageValid(IPackage package) IgnoredPackages[package.Id] = package; return false; } - if (package.AsSerializable().InstallationOptions.SkipMinorUpdates && package.IsUpdateMinor()) return false; + if (InstallationOptions.FromPackage(package).SkipMinorUpdates && package.IsUpdateMinor()) return false; if (package.NewerVersionIsInstalled()) return false; return true; } From 33ff6f800aa76693d79c50ea271c0139b285d1de Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mart=C3=AD=20Climent?= Date: Tue, 7 Jan 2025 23:48:30 +0100 Subject: [PATCH 9/9] Make method async --- .../UpgradablePackagesLoader.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/UniGetUI.PackageEngine.PackageLoader/UpgradablePackagesLoader.cs b/src/UniGetUI.PackageEngine.PackageLoader/UpgradablePackagesLoader.cs index 7cf1630f8..8ed71743e 100644 --- a/src/UniGetUI.PackageEngine.PackageLoader/UpgradablePackagesLoader.cs +++ b/src/UniGetUI.PackageEngine.PackageLoader/UpgradablePackagesLoader.cs @@ -32,7 +32,7 @@ protected override async Task IsPackageValid(IPackage package) IgnoredPackages[package.Id] = package; return false; } - if (InstallationOptions.FromPackage(package).SkipMinorUpdates && package.IsUpdateMinor()) return false; + if ((await InstallationOptions.FromPackageAsync(package)).SkipMinorUpdates && package.IsUpdateMinor()) return false; if (package.NewerVersionIsInstalled()) return false; return true; }