diff --git a/Source/AppScaffolding/LibationScaffolding.cs b/Source/AppScaffolding/LibationScaffolding.cs index 033e657b..15fdb3a0 100644 --- a/Source/AppScaffolding/LibationScaffolding.cs +++ b/Source/AppScaffolding/LibationScaffolding.cs @@ -349,7 +349,7 @@ public static class LibationScaffolding private static void wireUpSystemEvents(Configuration configuration) { - LibraryCommands.LibrarySizeChanged += (object? _, List libraryBooks) + LibraryCommands.LibrarySizeChanged += (_, libraryBooks) => SearchEngineCommands.FullReIndex(libraryBooks); LibraryCommands.BookUserDefinedItemCommitted += (_, books) @@ -423,26 +423,38 @@ public static class LibationScaffolding var releaseIndex = JObject.Parse(System.Text.Encoding.ASCII.GetString(bts)); string? regexPattern; + string? releaseIdString = null; try { - regexPattern = releaseIndex.Value(InteropFactory.Create().ReleaseIdString); + releaseIdString = InteropFactory.Create().ReleaseIdString; + regexPattern = releaseIndex.Value(releaseIdString); } catch { regexPattern = null; } + if (string.IsNullOrEmpty(regexPattern) && Configuration.IsLinux) + { + var baseId = ReleaseIdentifier.ToString(); + regexPattern = releaseIndex.Value($"{baseId}_RPM") + ?? releaseIndex.Value($"{baseId}_DEB"); + releaseIdString ??= $"{baseId}_RPM"; + } if (string.IsNullOrEmpty(regexPattern)) regexPattern = releaseIndex.Value(ReleaseIdentifier.ToString()); if (string.IsNullOrEmpty(regexPattern)) { - Log.Logger.Warning("Release index has no entry for this platform (ReleaseIdentifier: {ReleaseId}). Version check inconclusive.", ReleaseIdentifier); + Log.Logger.Warning("Release index has no entry for this platform (ReleaseIdentifier: {ReleaseId}, ReleaseIdString: {ReleaseIdString}). Version check inconclusive.", ReleaseIdentifier, releaseIdString); return (null, null, null, false); } var regex = new System.Text.RegularExpressions.Regex(regexPattern, System.Text.RegularExpressions.RegexOptions.IgnoreCase); var zip = latestRelease?.Assets?.FirstOrDefault(a => regex.IsMatch(a.Name)); + if (zip is not null && !string.IsNullOrEmpty(releaseIdString)) + Log.Logger.Information("Update asset matched using {ReleaseIdString}: {AssetName}", releaseIdString, zip.Name); + return (releaseVersion, latestRelease, zip, true); } } @@ -499,7 +511,7 @@ internal static class Migrations class FilterState_6_6_9 { public bool UseDefault { get; set; } - public List Filters { get; set; } = new(); + public List Filters { get; set; } = []; } public static void migrate_to_v12_0_1(Configuration config) @@ -520,7 +532,7 @@ internal static class Migrations if (JArray.Parse(File.ReadAllText(jsonFileV1)) is not JArray v1Cache || v1Cache.Count == 0) return; - Dictionary cache = new(); + Dictionary cache = []; //Convert to c# objects to speed up searching by ID inside the iterator var allItems @@ -612,10 +624,12 @@ internal static class Migrations if (JsonConvert.DeserializeObject(File.ReadAllText(QuickFilters.JsonFile)) is FilterState_6_6_9 inMemState) { - // Copy old structure to new. - QuickFilters.InMemoryState = new(); - QuickFilters.InMemoryState.UseDefault = inMemState.UseDefault; - foreach (var oldFilter in inMemState.Filters) + // Copy old structure to new. + QuickFilters.InMemoryState = new() + { + UseDefault = inMemState.UseDefault + }; + foreach (var oldFilter in inMemState.Filters) QuickFilters.InMemoryState.Filters.Add(new QuickFilters.NamedFilter(oldFilter, null)); return; diff --git a/Source/LoadByOS/LinuxConfigApp/LinuxInterop.cs b/Source/LoadByOS/LinuxConfigApp/LinuxInterop.cs index f8921468..c261481b 100644 --- a/Source/LoadByOS/LinuxConfigApp/LinuxInterop.cs +++ b/Source/LoadByOS/LinuxConfigApp/LinuxInterop.cs @@ -27,7 +27,7 @@ internal class LinuxInterop : IInteropFunctions public void SetFolderIcon(byte[] imageJpegBytes, string directory) => throw new PlatformNotSupportedException(); public void DeleteFolderIcon(string directory) => throw new PlatformNotSupportedException(); - public string ReleaseIdString => LibationScaffolding.ReleaseIdentifier.ToString() + (File.Exists("/usr/bin/apt") || File.Exists("/bin/apt") ? "_DEB" : "_RPM"); + public string ReleaseIdString => LibationScaffolding.ReleaseIdentifier.ToString() + LinuxPackageFormatSuffix(); //only run the auto upgrader if the current app was installed from the //.deb or .rpm package. Try to detect this by checking if the symlink exists. @@ -73,31 +73,44 @@ internal class LinuxInterop : IInteropFunctions private static bool TryResolvePackageManager(string upgradeBundle, out string pkgExe, out string[] pkgArgs) { - if (TryFirstExisting(out pkgExe, "/usr/bin/dnf5", "/bin/dnf5")) + var isRpmBundle = string.Equals(Path.GetExtension(upgradeBundle), ".rpm", StringComparison.OrdinalIgnoreCase); + var isDebBundle = string.Equals(Path.GetExtension(upgradeBundle), ".deb", StringComparison.OrdinalIgnoreCase); + + if (isRpmBundle || (!isDebBundle && UsesRpmPackageFormat())) { - pkgArgs = new[] { "install", "-y", upgradeBundle }; - return true; + if (TryFirstExisting(out pkgExe, "/usr/bin/dnf5", "/bin/dnf5") + || TryFirstExisting(out pkgExe, "/usr/bin/dnf", "/bin/dnf") + || TryFirstExisting(out pkgExe, "/usr/bin/yum", "/bin/yum")) + { + pkgArgs = new[] { "install", "-y", upgradeBundle }; + return true; + } } - if (TryFirstExisting(out pkgExe, "/usr/bin/dnf", "/bin/dnf")) + + if (isDebBundle || UsesDebPackageFormat()) { - pkgArgs = new[] { "install", "-y", upgradeBundle }; - return true; - } - if (TryFirstExisting(out pkgExe, "/usr/bin/yum", "/bin/yum")) - { - pkgArgs = new[] { "install", "-y", upgradeBundle }; - return true; - } - if (TryFirstExisting(out pkgExe, "/usr/bin/apt", "/bin/apt")) - { - pkgArgs = new[] { "install", "-y", "-o", "Dpkg::Options::=--force-confdef", "-o", "Dpkg::Options::=--force-confold", upgradeBundle }; - return true; + if (TryFirstExisting(out pkgExe, "/usr/bin/apt", "/bin/apt")) + { + pkgArgs = new[] { "install", "-y", "-o", "Dpkg::Options::=--force-confdef", "-o", "Dpkg::Options::=--force-confold", upgradeBundle }; + return true; + } } + pkgExe = ""; pkgArgs = Array.Empty(); return false; } + // RHEL/Fedora can have apt installed for .deb files; prefer native RPM managers when present. + internal static string LinuxPackageFormatSuffix() + => UsesRpmPackageFormat() ? "_RPM" : UsesDebPackageFormat() ? "_DEB" : "_RPM"; + + private static bool UsesRpmPackageFormat() + => TryFirstExisting(out _, "/usr/bin/dnf5", "/bin/dnf5", "/usr/bin/dnf", "/bin/dnf", "/usr/bin/yum", "/bin/yum"); + + private static bool UsesDebPackageFormat() + => TryFirstExisting(out _, "/usr/bin/apt", "/bin/apt"); + private static bool TryFirstExisting(out string path, params string[] candidates) { foreach (var c in candidates) @@ -150,7 +163,7 @@ internal class LinuxInterop : IInteropFunctions console[2], "/bin/sh", Path.Combine(Configuration.ProcessDirectory, runasroot), //script file - "Installing libation.deb", //command title + "Installing Libation package", //command title command, // command to execute vis /bin/sh $"Please run '{command}' manually" // error message to display in the terminal }