diff --git a/Duplicati/CommandLine/RecoveryTool/Recompress.cs b/Duplicati/CommandLine/RecoveryTool/Recompress.cs index cb3efee00..bca6dff2b 100644 --- a/Duplicati/CommandLine/RecoveryTool/Recompress.cs +++ b/Duplicati/CommandLine/RecoveryTool/Recompress.cs @@ -115,7 +115,6 @@ namespace Duplicati.CommandLine.RecoveryTool bool reencrypt = Library.Utility.Utility.ParseBoolOption(options, "reencrypt"); bool reupload = Library.Utility.Utility.ParseBoolOption(options, "reupload"); - var fullyRewroteRemoteSet = reupload; // Needs order (Files or Blocks) and Indexes as last because indexes content will be adjusted based on recompressed blocks var files = remotefiles.Where(a => a.FileType == RemoteVolumeType.Files).ToArray(); @@ -124,10 +123,6 @@ namespace Duplicati.CommandLine.RecoveryTool remotefiles = files.Concat(blocks).ToArray().Concat(indexes).ToArray(); - Options updatedLocalDatabaseOptions = null; - if (reupload) - updatedLocalDatabaseOptions = new Options(BuildUpdatedRawOptions(m_Options, remotefiles, target_compr_module, reencrypt)); - var retainedReuploadedBlockFiles = new List(); Console.WriteLine("Found {0} files which belongs to backup with prefix {1}", remotefiles.Count(), m_Options.Prefix); @@ -162,14 +157,12 @@ namespace Duplicati.CommandLine.RecoveryTool else { Console.WriteLine(" - cannot detect compression type"); - fullyRewroteRemoteSet = false; continue; } if ((!reencrypt && File.Exists(localFileTarget)) || (reencrypt && File.Exists(localFileTarget + "." + localFileSourceEncryption))) { Console.WriteLine(" - target file already exist"); - fullyRewroteRemoteSet = false; continue; } @@ -305,7 +298,6 @@ namespace Duplicati.CommandLine.RecoveryTool { Console.WriteLine(" error: {0}", ex); errors++; - fullyRewroteRemoteSet = false; } } @@ -332,10 +324,7 @@ namespace Duplicati.CommandLine.RecoveryTool Console.WriteLine("Download complete, of {0} remote files, {1} were downloaded with {2} errors", remotefiles.Count(), downloaded, errors); if (needspass > 0) - { Console.WriteLine("Additonally {0} remote files were skipped because of encryption, supply --passphrase to download those", needspass); - fullyRewroteRemoteSet = false; - } if (errors > 0) { @@ -343,31 +332,10 @@ namespace Duplicati.CommandLine.RecoveryTool return 200; } - if (reupload && reuploaded > 0) - { - if (fullyRewroteRemoteSet && reuploaded == remotefiles.Length) - UpdateLocalDatabase(args[2], m_Options, updatedLocalDatabaseOptions); - else - Console.WriteLine("The local database was not updated because the reupload did not rewrite the full remote set."); - } - return 0; } } - private static void UpdateLocalDatabase(string backendUrl, Options originalOptions, Options updatedOptions) - { - var dbpath = CLIDatabaseLocator.GetDatabasePathForCLI(backendUrl, originalOptions, false, true); - if (string.IsNullOrWhiteSpace(dbpath) || !File.Exists(dbpath)) - { - Console.WriteLine("The local database was not updated because no matching database file was found. Supply --dbpath to update it explicitly."); - return; - } - - Duplicati.Library.Main.Utility.PersistOptionsToDatabaseWithoutValidation(dbpath, updatedOptions, "RecoveryTool Recompress", CancellationToken.None).Await(); - Console.WriteLine("Updated stored backup options in local database: {0}", dbpath); - } - private static void RestoreOptionsFromLocalDatabaseIfAvailable(string backendUrl, Options options) { var dbpath = CLIDatabaseLocator.GetDatabasePathForCLI(backendUrl, options, false, false); @@ -376,38 +344,5 @@ namespace Duplicati.CommandLine.RecoveryTool Duplicati.Library.Main.Utility.UpdateOptionsFromDatabase(dbpath, options, "RecoveryTool Recompress", CancellationToken.None).Await(); } - - private static Dictionary BuildUpdatedRawOptions(Options originalOptions, IEnumerable remoteFiles, string targetCompressionModule, bool reencrypt) - { - var updatedOptions = new Dictionary(originalOptions.RawOptions); - updatedOptions["compression-module"] = targetCompressionModule; - - var encryptionModules = remoteFiles - .Select(volume => volume.EncryptionModule) - .Where(module => !string.IsNullOrWhiteSpace(module)) - .Distinct(StringComparer.OrdinalIgnoreCase) - .ToArray(); - - if (reencrypt && encryptionModules.Length > 0) - { - if (encryptionModules.Length != 1) - throw new UserInformationException("Unable to update the local database because the rewritten remote set contains multiple encryption modules.", "RecoveryToolMultipleEncryptionModules"); - - updatedOptions.Remove("no-encryption"); - updatedOptions["encryption-module"] = encryptionModules[0]; - updatedOptions["passphrase"] = string.IsNullOrWhiteSpace(originalOptions.NewPassphrase) - ? originalOptions.Passphrase - : originalOptions.NewPassphrase; - } - else - { - updatedOptions["no-encryption"] = bool.TrueString; - updatedOptions.Remove("encryption-module"); - updatedOptions.Remove("passphrase"); - } - - updatedOptions.Remove("new-passphrase"); - return updatedOptions; - } } } diff --git a/Duplicati/UnitTest/RecoveryToolTests.cs b/Duplicati/UnitTest/RecoveryToolTests.cs index c921cac55..fe5f5fba6 100644 --- a/Duplicati/UnitTest/RecoveryToolTests.cs +++ b/Duplicati/UnitTest/RecoveryToolTests.cs @@ -298,131 +298,5 @@ namespace Duplicati.UnitTest Assert.AreEqual(0, status); } - [Test] - [Category("RecoveryTool")] - public async Task RecompressReuploadUpdatesLocalDbForNewPassphrase() - { - File.WriteAllText(Path.Combine(this.DATAFOLDER, "sample.txt"), "payload"); - - Dictionary options = new Dictionary(this.TestOptions); - options["prefix"] = "recompressprefix"; - string backendURL = "file://" + this.TARGETFOLDER; - using (Controller c = new Controller(backendURL, options, null)) - { - IBackupResults backupResults = c.Backup(new[] { this.DATAFOLDER }); - Assert.AreEqual(0, backupResults.Errors.Count()); - Assert.AreEqual(0, backupResults.Warnings.Count()); - } - - IDictionary beforeOptions; - await using (var beforeUpdate = await LocalDatabase.CreateLocalDatabaseAsync(this.DBFILE, "before-recompress", true, null, System.Threading.CancellationToken.None)) - beforeOptions = await beforeUpdate.GetDbOptions(System.Threading.CancellationToken.None); - - int status = CommandLine.RecoveryTool.Program.Main(new[] - { - "recompress", - "zip", - backendURL, - this.RESTOREFOLDER, - "--reupload=true", - $"--dbpath={this.DBFILE}", - $"--passphrase={options["passphrase"]}", - "--reencrypt=true", - "--new-passphrase=654321" - }); - - Assert.AreEqual(0, status); - - await using var afterUpdate = await LocalDatabase.CreateLocalDatabaseAsync(this.DBFILE, "after-recompress", true, null, System.Threading.CancellationToken.None); - var afterOptions = await afterUpdate.GetDbOptions(System.Threading.CancellationToken.None); - - Assert.That(afterOptions["prefix"], Is.EqualTo("recompressprefix")); - Assert.That(afterOptions["compression-module"], Is.EqualTo("zip")); - Assert.That(afterOptions["encryption-module"], Is.EqualTo("aes")); - Assert.That(afterOptions["passphrase"], Is.Not.EqualTo(beforeOptions["passphrase"])); - } - - [Test] - [Category("RecoveryTool")] - public async Task RecompressReuploadUpdatesLocalDbForRemovedEncryption() - { - File.WriteAllText(Path.Combine(this.DATAFOLDER, "sample.txt"), "payload"); - - Dictionary options = new Dictionary(this.TestOptions); - string backendURL = "file://" + this.TARGETFOLDER; - using (Controller c = new Controller(backendURL, options, null)) - { - IBackupResults backupResults = c.Backup(new[] { this.DATAFOLDER }); - Assert.AreEqual(0, backupResults.Errors.Count()); - Assert.AreEqual(0, backupResults.Warnings.Count()); - } - - int status = CommandLine.RecoveryTool.Program.Main(new[] - { - "recompress", - "zip", - backendURL, - this.RESTOREFOLDER, - "--reupload=true", - $"--dbpath={this.DBFILE}", - $"--passphrase={options["passphrase"]}" - }); - - Assert.AreEqual(0, status); - - await using var db = await LocalDatabase.CreateLocalDatabaseAsync(this.DBFILE, "after-remove-encryption", true, null, System.Threading.CancellationToken.None); - var storedOptions = await db.GetDbOptions(System.Threading.CancellationToken.None); - - Assert.That(storedOptions["compression-module"], Is.EqualTo("zip")); - Assert.That(storedOptions["passphrase"], Is.EqualTo("no-encryption")); - Assert.That(storedOptions.ContainsKey("encryption-module"), Is.False); - Assert.That(storedOptions.ContainsKey("passphrase-salt"), Is.False); - } - - [Test] - [Category("RecoveryTool")] - public void RecompressReencryptFailsBeforeTouchingBackendWhenRemoteSetHasMixedEncryptionModules() - { - File.WriteAllText(Path.Combine(this.DATAFOLDER, "sample.txt"), "payload"); - - Dictionary options = new Dictionary(this.TestOptions); - string backendURL = "file://" + this.TARGETFOLDER; - using (Controller c = new Controller(backendURL, options, null)) - { - IBackupResults backupResults = c.Backup(new[] { this.DATAFOLDER }); - Assert.AreEqual(0, backupResults.Errors.Count()); - Assert.AreEqual(0, backupResults.Warnings.Count()); - } - - var remoteFile = Directory.GetFiles(this.TARGETFOLDER, "*.aes").First(); - var renamedRemoteFile = remoteFile.Substring(0, remoteFile.Length - ".aes".Length) + ".gpg"; - File.Move(remoteFile, renamedRemoteFile); - - var backendFilesBeforeRun = Directory.GetFiles(this.TARGETFOLDER) - .Select(Path.GetFileName) - .OrderBy(name => name, StringComparer.Ordinal) - .ToArray(); - - int status = CommandLine.RecoveryTool.Program.Main(new[] - { - "recompress", - "zip", - backendURL, - this.RESTOREFOLDER, - "--reupload=true", - "--reencrypt=true", - $"--passphrase={options["passphrase"]}" - }); - - Assert.AreEqual(200, status); - - var backendFilesAfterRun = Directory.GetFiles(this.TARGETFOLDER) - .Select(Path.GetFileName) - .OrderBy(name => name, StringComparer.Ordinal) - .ToArray(); - - Assert.That(backendFilesAfterRun, Is.EqualTo(backendFilesBeforeRun)); - } - } } \ No newline at end of file