Drops the unnecessary local DB update post-recompress, and associated tests.
This commit is contained in:
@@ -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<string>();
|
||||
|
||||
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<string, string> BuildUpdatedRawOptions(Options originalOptions, IEnumerable<IParsedVolume> remoteFiles, string targetCompressionModule, bool reencrypt)
|
||||
{
|
||||
var updatedOptions = new Dictionary<string, string>(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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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<string, string> options = new Dictionary<string, string>(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<string, string> 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<string, string> options = new Dictionary<string, string>(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<string, string> options = new Dictionary<string, string>(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));
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user