From 42c4e504829c2a06e98ba0ba2efbbd4d272fa3dc Mon Sep 17 00:00:00 2001 From: Kenneth Skovhede Date: Mon, 25 Nov 2024 17:27:50 +0100 Subject: [PATCH] Fixed issues with update detection. This fixes a case where the update checker keeps an old reference to the previous updated version, despite running a newer version. It also removes some use of `Assembly.GetExecutingAssembly().GetName().Version` with the information from `UpdaterManager.SelfVersion.Version` as that should follow the update info. This fixes #5698 This fixes #5252 --- Duplicati/Library/AutoUpdater/Program.cs | 4 ++-- .../Library/RestAPI/Database/Connection.cs | 11 ++++++++--- Duplicati/Library/RestAPI/UpdatePollThread.cs | 12 +++++++++++- Duplicati/Server/Program.cs | 18 ++++++++++++++++++ Duplicati/Server/WebServerLoader.cs | 2 +- .../WebserverCore/Endpoints/V1/Changelog.cs | 3 ++- .../Services/SystemInfoProvider.cs | 3 ++- 7 files changed, 44 insertions(+), 9 deletions(-) diff --git a/Duplicati/Library/AutoUpdater/Program.cs b/Duplicati/Library/AutoUpdater/Program.cs index 8610ba18d..35cacac7e 100644 --- a/Duplicati/Library/AutoUpdater/Program.cs +++ b/Duplicati/Library/AutoUpdater/Program.cs @@ -68,7 +68,7 @@ namespace Duplicati.Library.AutoUpdater var update = UpdaterManager.CheckForUpdate(); if (update == null || update.Version == UpdaterManager.SelfVersion.Version) { - Console.WriteLine("You are running the latest version: {0} ({1})", UpdaterManager.SelfVersion.Displayname, System.Reflection.Assembly.GetExecutingAssembly().GetName().Version); + Console.WriteLine("You are running the latest version: {0} ({1})", UpdaterManager.SelfVersion.Displayname, UpdaterManager.SelfVersion.Version); return 0; } @@ -117,7 +117,7 @@ namespace Duplicati.Library.AutoUpdater Console.WriteLine(); Console.WriteLine("Updates are downloaded from: {0}", string.Join(";", AutoUpdateSettings.URLs)); Console.WriteLine("Machine settings are installed in: {0}", UpdaterManager.UPDATEDIR); - Console.WriteLine("This version is \"{0}\" ({1}) and is installed in: {2}", UpdaterManager.SelfVersion.Displayname, System.Reflection.Assembly.GetExecutingAssembly().GetName().Version, UpdaterManager.INSTALLATIONDIR); + Console.WriteLine("This version is \"{0}\" ({1}) and is installed in: {2}", UpdaterManager.SelfVersion.Displayname, UpdaterManager.SelfVersion.Version, UpdaterManager.INSTALLATIONDIR); Console.WriteLine(); } } diff --git a/Duplicati/Library/RestAPI/Database/Connection.cs b/Duplicati/Library/RestAPI/Database/Connection.cs index 91603f0d6..0d060502b 100644 --- a/Duplicati/Library/RestAPI/Database/Connection.cs +++ b/Duplicati/Library/RestAPI/Database/Connection.cs @@ -28,6 +28,7 @@ using Duplicati.Library.RestAPI; using Duplicati.Library.Encryption; using Duplicati.Library.DynamicLoader; using Duplicati.Library.Main; +using Duplicati.Library.AutoUpdater; namespace Duplicati.Server.Database { @@ -146,7 +147,7 @@ namespace Duplicati.Server.Database var scheduleId = GetScheduleIDsFromTags(new string[] { "ID=" + backup.ID }); return new Serializable.ImportExportStructure() { - CreatedByVersion = System.Reflection.Assembly.GetExecutingAssembly().GetName().Version.ToString(), + CreatedByVersion = UpdaterManager.SelfVersion.Version, Backup = (Database.Backup)backup, Schedule = (Database.Schedule)(scheduleId.Any() ? GetSchedule(scheduleId.First()) : null), DisplayNames = SpecialFolders.GetSourceNames(backup) @@ -876,8 +877,12 @@ namespace Duplicati.Server.Database FIXMEGlobal.DataConnection.ApplicationSettings.UnackedWarning = notifications.Any(x => x.ID != id && x.Type == Duplicati.Server.Serialization.NotificationType.Warning); } - FIXMEGlobal.NotificationUpdateService.IncrementLastNotificationUpdateId(); - FIXMEGlobal.StatusEventNotifyer.SignalNewEvent(); + // Guard against dismissing notifications before the provider is initialized + if (FIXMEGlobal.Provider != null) + { + FIXMEGlobal.NotificationUpdateService.IncrementLastNotificationUpdateId(); + FIXMEGlobal.StatusEventNotifyer.SignalNewEvent(); + } return true; } diff --git a/Duplicati/Library/RestAPI/UpdatePollThread.cs b/Duplicati/Library/RestAPI/UpdatePollThread.cs index 6f0ce0ac7..5ccc53be2 100644 --- a/Duplicati/Library/RestAPI/UpdatePollThread.cs +++ b/Duplicati/Library/RestAPI/UpdatePollThread.cs @@ -22,6 +22,7 @@ using System; using System.Linq; using System.Threading; +using Duplicati.Library.AutoUpdater; using Duplicati.Server.Database; using Duplicati.Server.Serialization; @@ -161,8 +162,17 @@ namespace Duplicati.Server connection.ApplicationSettings.UpdatedVersion = null; } + // If the update is the same or older than the current version, we discard it + // NOTE: This check is also inside the UpdaterManager.CheckForUpdate method, + // but we may have a stale version recorded, so we force-clear it here + if (connection.ApplicationSettings.UpdatedVersion != null) + { + if (UpdaterManager.TryParseVersion(connection.ApplicationSettings.UpdatedVersion.Version) <= UpdaterManager.TryParseVersion(UpdaterManager.SelfVersion.Version)) + connection.ApplicationSettings.UpdatedVersion = null; + } + var updatedinfo = connection.ApplicationSettings.UpdatedVersion; - if (updatedinfo != null && Duplicati.Library.AutoUpdater.UpdaterManager.TryParseVersion(updatedinfo.Version) > System.Reflection.Assembly.GetExecutingAssembly().GetName().Version) + if (updatedinfo != null && UpdaterManager.TryParseVersion(updatedinfo.Version) > UpdaterManager.TryParseVersion(UpdaterManager.SelfVersion.Version)) { var package = updatedinfo.FindPackage(); diff --git a/Duplicati/Server/Program.cs b/Duplicati/Server/Program.cs index db83e67ed..b64b84f56 100644 --- a/Duplicati/Server/Program.cs +++ b/Duplicati/Server/Program.cs @@ -25,6 +25,7 @@ using System.Globalization; using System.Linq; using System.Threading; using System.Threading.Tasks; +using Duplicati.Library.AutoUpdater; using Duplicati.Library.Common.IO; using Duplicati.Library.Crashlog; using Duplicati.Library.Encryption; @@ -555,6 +556,23 @@ namespace Duplicati.Server { throw new UserInformationException(Strings.Program.InvalidTimezone(commandlineOptions[WebServerLoader.OPTION_WEBSERVICE_TIMEZONE]), "InvalidTimeZone", ex); } + + // The database has recorded a new version + if (DataConnection.ApplicationSettings.UpdatedVersion != null) + { + // Check if the running version is newer than the recorded version + if (UpdaterManager.TryParseVersion(DataConnection.ApplicationSettings.UpdatedVersion.Version) <= UpdaterManager.TryParseVersion(UpdaterManager.SelfVersion.Version)) + { + // Clean up lingering update notifications + var updateNotifications = DataConnection.GetNotifications().Where(x => x.Action == "update:new").ToList(); + foreach (var n in updateNotifications) + DataConnection.DismissNotification(n.ID); + + // Clear up the recorded version + DataConnection.ApplicationSettings.UpdatedVersion = null; + } + } + } private static void CreateApplicationInstance(bool writeToConsoleOnExceptionw) diff --git a/Duplicati/Server/WebServerLoader.cs b/Duplicati/Server/WebServerLoader.cs index 27546436a..fafa364b1 100644 --- a/Duplicati/Server/WebServerLoader.cs +++ b/Duplicati/Server/WebServerLoader.cs @@ -241,7 +241,7 @@ public static class WebServerLoader -1, listenInterface, connection.ApplicationSettings.UseHTTPS ? connection.ApplicationSettings.ServerSSLCertificate : null, - string.Format("{0} v{1}", Library.AutoUpdater.AutoUpdateSettings.AppName, System.Reflection.Assembly.GetExecutingAssembly().GetName().Version), + string.Format("{0} v{1}", Library.AutoUpdater.AutoUpdateSettings.AppName, Library.AutoUpdater.UpdaterManager.SelfVersion.Version), (connection.ApplicationSettings.AllowedHostnames ?? string.Empty).Split(new char[] { ';' }, StringSplitOptions.RemoveEmptyEntries), Duplicati.Library.Utility.Utility.ParseBoolOption(options, OPTION_WEBSERVICE_API_ONLY), spaPathsString.Split(new char[] { ';' }, StringSplitOptions.RemoveEmptyEntries) diff --git a/Duplicati/WebserverCore/Endpoints/V1/Changelog.cs b/Duplicati/WebserverCore/Endpoints/V1/Changelog.cs index 78a7dc79b..8b5c15fdf 100644 --- a/Duplicati/WebserverCore/Endpoints/V1/Changelog.cs +++ b/Duplicati/WebserverCore/Endpoints/V1/Changelog.cs @@ -1,3 +1,4 @@ +using Duplicati.Library.AutoUpdater; using Duplicati.Server.Database; using Duplicati.WebserverCore.Abstractions; using Duplicati.WebserverCore.Exceptions; @@ -32,7 +33,7 @@ public class Changelog : IEndpointV1 var path = Path.Combine(System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location) ?? ".", "changelog.txt"); return new Dto.ChangelogDto() { - Version = System.Reflection.Assembly.GetExecutingAssembly().GetName().Version?.ToString(), + Version = UpdaterManager.SelfVersion.Version, Changelog = System.IO.File.ReadAllText(path) }; } diff --git a/Duplicati/WebserverCore/Services/SystemInfoProvider.cs b/Duplicati/WebserverCore/Services/SystemInfoProvider.cs index 060b55877..4d767bceb 100644 --- a/Duplicati/WebserverCore/Services/SystemInfoProvider.cs +++ b/Duplicati/WebserverCore/Services/SystemInfoProvider.cs @@ -1,4 +1,5 @@ using System.Globalization; +using Duplicati.Library.AutoUpdater; using Duplicati.Library.RestAPI; using Duplicati.Server; using Duplicati.Server.Serialization.Interface; @@ -190,7 +191,7 @@ public class SystemInfoProvider : ISystemInfoProvider { APIVersion = 1, PasswordPlaceholder = FIXMEGlobal.PASSWORD_PLACEHOLDER, - ServerVersion = System.Reflection.Assembly.GetExecutingAssembly().GetName().Version?.ToString(), + ServerVersion = UpdaterManager.SelfVersion.Version, ServerVersionName = License.VersionNumbers.Version, ServerVersionType = Library.AutoUpdater.UpdaterManager.SelfVersion.ReleaseType, RemoteControlRegistrationUrl = Duplicati.Library.RemoteControl.RegisterForRemote.DefaultRegisterationUrl,