From 23db3fd0905802e2a76b705fe565c5ad48de223f Mon Sep 17 00:00:00 2001 From: Kenneth Skovhede Date: Wed, 23 Apr 2025 17:05:40 +0200 Subject: [PATCH] Added flag to ignore updating to existing version This fixes #4604 This fixes #3587 This fixes #2275 --- .../Library/Main/Operation/RecreateDatabaseHandler.cs | 8 ++++++++ Duplicati/Library/Main/Options.cs | 7 +++++++ Duplicati/Library/Main/Strings.cs | 2 ++ Duplicati/WebserverCore/Endpoints/V1/Backup/BackupPost.cs | 6 ++++++ 4 files changed, 23 insertions(+) diff --git a/Duplicati/Library/Main/Operation/RecreateDatabaseHandler.cs b/Duplicati/Library/Main/Operation/RecreateDatabaseHandler.cs index 59d4130e8..af4912a95 100644 --- a/Duplicati/Library/Main/Operation/RecreateDatabaseHandler.cs +++ b/Duplicati/Library/Main/Operation/RecreateDatabaseHandler.cs @@ -86,7 +86,15 @@ namespace Duplicati.Library.Main.Operation using (var db = new LocalDatabase(m_options.Dbpath, "Recreate", true)) { if (db.FindMatchingFilesets(m_options.Time, m_options.Version).Any()) + { + if (m_options.IgnoreUpdateIfVersionExists) + { + Logging.Log.WriteInformationMessage(LOGTAG, "UpdateVersionAlreadyExists", "The version(s) being updated to already exists, ignoring update request"); + return; + } + throw new UserInformationException("The version(s) being updated to, already exists", "UpdateVersionAlreadyExists"); + } // Mark as incomplete db.PartiallyRecreated = true; diff --git a/Duplicati/Library/Main/Options.cs b/Duplicati/Library/Main/Options.cs index 8fc44d1d5..723096596 100644 --- a/Duplicati/Library/Main/Options.cs +++ b/Duplicati/Library/Main/Options.cs @@ -484,6 +484,7 @@ namespace Duplicati.Library.Main new CommandLineArgument("restore-volume-downloaders", CommandLineArgument.ArgumentType.Integer, Strings.Options.RestoreVolumeDownloadersShort, Strings.Options.RestoreVolumeDownloadersLong, DEFAULT_RESTORE_VOLUME_DOWNLOADERS.ToString()), new CommandLineArgument("restore-channel-buffer-size", CommandLineArgument.ArgumentType.Integer, Strings.Options.RestoreChannelBufferSizeShort, Strings.Options.RestoreChannelBufferSizeLong, DEFAULT_RESTORE_CHANNEL_BUFFER_SIZE.ToString()), new CommandLineArgument("internal-profiling", CommandLineArgument.ArgumentType.Boolean, Strings.Options.InternalProfilingShort, Strings.Options.InternalProfilingLong, "false"), + new CommandLineArgument("ignore-update-if-version-exists", CommandLineArgument.ArgumentType.Boolean, Strings.Options.IgnoreUpdateIfVersionExistsShort, Strings.Options.IgnoreUpdateIfVersionExistsLong, "false"), ]; /// @@ -2245,6 +2246,12 @@ namespace Duplicati.Library.Main get { return Library.Utility.Utility.ParseBoolOption(m_options, "internal-profiling"); } } + /// + /// Ignores the update if the version already exists in the database. + /// + public bool IgnoreUpdateIfVersionExists + => Library.Utility.Utility.ParseBoolOption(m_options, "ignore-update-if-version-exists"); + /// /// Class for handling a single RetentionPolicy timeframe-interval-pair /// diff --git a/Duplicati/Library/Main/Strings.cs b/Duplicati/Library/Main/Strings.cs index bb5bfca54..429641098 100644 --- a/Duplicati/Library/Main/Strings.cs +++ b/Duplicati/Library/Main/Strings.cs @@ -345,6 +345,8 @@ namespace Duplicati.Library.Main.Strings public static string RestoreChannelBufferSizeLong { get { return LC.L("Use this option to set the size of the buffers of the channels used during restore. The buffers are used to allow for better asynchronous communication between the processes in the restore flow. Increasing the buffer size may improve restore performance."); } } public static string InternalProfilingShort { get { return LC.L("Enable internal profiling"); } } public static string InternalProfilingLong { get { return LC.L("Use this option to enable internal profiling. Profiling is used to measure the performance of the internal code. The profiling data is written to the log file and can be used to identify performance bottlenecks."); } } + public static string IgnoreUpdateIfVersionExistsShort { get { return LC.L("Ignore update if version exists"); } } + public static string IgnoreUpdateIfVersionExistsLong { get { return LC.L("Use this option to ignore the update if the version already exists. This can be used to avoid errors if asking to update the database with a version that already exists."); } } } internal static class Common diff --git a/Duplicati/WebserverCore/Endpoints/V1/Backup/BackupPost.cs b/Duplicati/WebserverCore/Endpoints/V1/Backup/BackupPost.cs index 47284e9eb..8b58ff846 100644 --- a/Duplicati/WebserverCore/Endpoints/V1/Backup/BackupPost.cs +++ b/Duplicati/WebserverCore/Endpoints/V1/Backup/BackupPost.cs @@ -155,9 +155,15 @@ public class BackupPost : IEndpointV1 if (input.only_paths.HasValue) extra["repair-only-paths"] = input.only_paths.Value.ToString(); if (!string.IsNullOrWhiteSpace(input.time)) + { extra["time"] = input.time; + extra["ignore-update-if-version-exists"] = "true"; + } if (!string.IsNullOrWhiteSpace(input.version)) + { extra["version"] = input.version; + extra["ignore-update-if-version-exists"] = "true"; + } } var filters = input?.paths ?? [];