diff --git a/BuildTools/LicenseUpdater/Program.cs b/BuildTools/LicenseUpdater/Program.cs
index c69cfbaaa..007341537 100755
--- a/BuildTools/LicenseUpdater/Program.cs
+++ b/BuildTools/LicenseUpdater/Program.cs
@@ -37,7 +37,7 @@ var target_extensions = new[] {
// ".css"
}.ToHashSet(StringComparer.OrdinalIgnoreCase);
-File.WriteAllText(Path.Combine(startpath, "LICENSE.txt"), Fragments.GetLicenseTextWithPrefixedLines(string.Empty));
+File.WriteAllText(Path.Combine(startpath, "LICENSE"), Fragments.GetLicenseTextWithPrefixedLines(string.Empty));
var candidates = Directory.EnumerateFiles(startpath, "*", SearchOption.AllDirectories)
.Where(x => target_extensions.Contains(Path.GetExtension(x) ?? string.Empty));
diff --git a/Duplicati/Library/Main/Backend/BackendManager.cs b/Duplicati/Library/Main/Backend/BackendManager.cs
index 20ded2a5f..3786ff52c 100644
--- a/Duplicati/Library/Main/Backend/BackendManager.cs
+++ b/Duplicati/Library/Main/Backend/BackendManager.cs
@@ -36,15 +36,6 @@ internal partial class BackendManager : IBackendManager
///
private readonly Task queueRunner;
- ///
- /// The last file read size
- ///
- public long LastReadSize { get; private set; }
- ///
- /// The last file write size
- ///
- public long LastWriteSize { get; private set; }
-
///
/// The execution context
///
@@ -171,8 +162,7 @@ internal partial class BackendManager : IBackendManager
Decrypt = true
};
await QueueTask(op).ConfigureAwait(false);
- (var file, var _, var downloadSize) = await op.GetResult().ConfigureAwait(false);
- LastReadSize = downloadSize;
+ (var file, var _, var _) = await op.GetResult().ConfigureAwait(false);
return file;
}
@@ -192,8 +182,7 @@ internal partial class BackendManager : IBackendManager
Decrypt = false
};
await QueueTask(op).ConfigureAwait(false);
- (var file, var _, var downloadSize) = await op.GetResult().ConfigureAwait(false);
- LastReadSize = downloadSize;
+ (var file, var _, var _) = await op.GetResult().ConfigureAwait(false);
return file;
}
@@ -226,7 +215,6 @@ internal partial class BackendManager : IBackendManager
};
await QueueTask(op).ConfigureAwait(false);
(var file, var downloadHash, var downloadSize) = await op.GetResult().ConfigureAwait(false);
- LastReadSize = downloadSize;
return (file, downloadHash, downloadSize);
}
diff --git a/Duplicati/Library/Main/Database/LocalBackupDatabase.cs b/Duplicati/Library/Main/Database/LocalBackupDatabase.cs
index 5c0dae4a9..8e1918bcc 100644
--- a/Duplicati/Library/Main/Database/LocalBackupDatabase.cs
+++ b/Duplicati/Library/Main/Database/LocalBackupDatabase.cs
@@ -660,6 +660,15 @@ SELECT ""BlocklistHash"".""BlocksetID"" FROM ""BlocklistHash"" WHERE ""Blocklist
base.Dispose();
}
+ public long GetLastWrittenDBlockVolumeSize(IDbTransaction? transaction)
+ {
+ using (var cmd = m_connection.CreateCommand(transaction))
+ return cmd.SetCommandAndParameters(@"SELECT ""Size"" FROM ""RemoteVolume"" WHERE ""State"" = @State AND ""Type"" = @Type ORDER BY ""ID"" DESC LIMIT 1")
+ .SetParameterValue("@State", RemoteVolumeState.Uploaded.ToString())
+ .SetParameterValue("@Type", RemoteVolumeType.Blocks.ToString())
+ .ExecuteScalarInt64(-1);
+ }
+
private long GetPreviousFilesetID(IDbCommand cmd)
{
return GetPreviousFilesetID(cmd, OperationTimestamp, m_filesetId, cmd.Transaction);
diff --git a/Duplicati/Library/Main/Database/LocalDatabase.cs b/Duplicati/Library/Main/Database/LocalDatabase.cs
index 446fe87d5..8c56a5744 100644
--- a/Duplicati/Library/Main/Database/LocalDatabase.cs
+++ b/Duplicati/Library/Main/Database/LocalDatabase.cs
@@ -206,17 +206,17 @@ namespace Duplicati.Library.Main.Database
return Library.Utility.Utility.EPOCH.AddSeconds(seconds);
}
- public void UpdateRemoteVolume(string name, RemoteVolumeState state, long size, string hash, IDbTransaction? transaction = null)
+ public void UpdateRemoteVolume(string name, RemoteVolumeState state, long size, string? hash, IDbTransaction? transaction = null)
{
UpdateRemoteVolume(name, state, size, hash, false, transaction);
}
- public void UpdateRemoteVolume(string name, RemoteVolumeState state, long size, string hash, bool suppressCleanup, IDbTransaction? transaction = null)
+ public void UpdateRemoteVolume(string name, RemoteVolumeState state, long size, string? hash, bool suppressCleanup, IDbTransaction? transaction = null)
{
UpdateRemoteVolume(name, state, size, hash, suppressCleanup, new TimeSpan(0), transaction);
}
- public void UpdateRemoteVolume(string name, RemoteVolumeState state, long size, string hash, bool suppressCleanup, TimeSpan deleteGraceTime, IDbTransaction? transaction = null)
+ public void UpdateRemoteVolume(string name, RemoteVolumeState state, long size, string? hash, bool suppressCleanup, TimeSpan deleteGraceTime, IDbTransaction? transaction = null)
{
m_updateremotevolumeCommand.Transaction = transaction;
var c = m_updateremotevolumeCommand.SetParameterValue("@OperationID", m_operationid)
@@ -391,7 +391,7 @@ namespace Duplicati.Library.Main.Database
/// The operation performed
/// The path involved
/// Any data relating to the operation
- public void LogRemoteOperation(string operation, string path, string data, IDbTransaction transaction)
+ public void LogRemoteOperation(string operation, string path, string? data, IDbTransaction? transaction)
{
m_insertremotelogCommand
.SetParameterValue("@OperationID", m_operationid)
@@ -1434,7 +1434,7 @@ AND oldVersion.FilesetID = (SELECT ID FROM Fileset WHERE ID != @FilesetId ORDER
}
}
- public void RenameRemoteFile(string oldname, string newname, IDbTransaction transaction)
+ public void RenameRemoteFile(string oldname, string newname, IDbTransaction? transaction)
{
using (var tr = new TemporaryTransactionWrapper(m_connection, transaction))
using (var cmd = m_connection.CreateCommand(tr.Parent))
diff --git a/Duplicati/Library/Main/IBackendManager.cs b/Duplicati/Library/Main/IBackendManager.cs
index 99c4104ba..380c2c5be 100644
--- a/Duplicati/Library/Main/IBackendManager.cs
+++ b/Duplicati/Library/Main/IBackendManager.cs
@@ -126,16 +126,6 @@ internal interface IBackendManager : IDisposable
/// The downloaded files, hash, size, and name
IAsyncEnumerable<(TempFile File, string Hash, long Size, string Name)> GetFilesOverlappedAsync(IEnumerable volumes, CancellationToken cancelToken);
- ///
- /// Gets the size of the last read operation
- ///
- long LastReadSize { get; }
-
- ///
- /// Gets the size of the last write operation
- ///
- long LastWriteSize { get; }
-
///
/// Flushes the database messages to the database
///
diff --git a/Duplicati/Library/Main/Operation/BackupHandler.cs b/Duplicati/Library/Main/Operation/BackupHandler.cs
index 322e0f1a2..153217795 100644
--- a/Duplicati/Library/Main/Operation/BackupHandler.cs
+++ b/Duplicati/Library/Main/Operation/BackupHandler.cs
@@ -595,7 +595,7 @@ namespace Duplicati.Library.Main.Operation
return new AggregateException(ex.First().Message, ex);
}
- private static async Task FlushBackend(Backup.BackupDatabase database, BackupResults result, IBackendManager backendManager)
+ private static async Task FlushBackend(Backup.BackupDatabase database, BackupResults result, IBackendManager backendManager)
{
// Wait for upload completion
result.OperationProgressUpdater.UpdatePhase(OperationPhase.Backup_WaitForUpload);
@@ -605,14 +605,10 @@ namespace Duplicati.Library.Main.Operation
await database.FlushBackendMessagesAndCommitAsync(backendManager).ConfigureAwait(false);
await backendManager.WaitForEmptyAsync(result.TaskControl.ProgressToken).ConfigureAwait(false);
await database.FlushBackendMessagesAndCommitAsync(backendManager).ConfigureAwait(false);
- // Grab the size of the last uploaded volume
- return backendManager.LastWriteSize;
}
catch (RetiredException)
{
}
-
- return -1;
}
public async Task RunAsync(string[] sources, IBackendManager backendManager, IFilter filter)
@@ -719,7 +715,7 @@ namespace Duplicati.Library.Main.Operation
// Wait for upload completion
m_result.OperationProgressUpdater.UpdatePhase(OperationPhase.Backup_WaitForUpload);
- var lastVolumeSize = await FlushBackend(db, m_result, backendManager).ConfigureAwait(false);
+ await FlushBackend(db, m_result, backendManager).ConfigureAwait(false);
if (!m_options.Dryrun)
database.TerminatedWithActiveUploads = false;
@@ -730,7 +726,10 @@ namespace Duplicati.Library.Main.Operation
{
// If this throws, we should roll back the transaction
if (await m_result.TaskControl.ProgressRendevouz().ConfigureAwait(false))
+ {
+ var lastVolumeSize = m_database.GetLastWrittenDBlockVolumeSize(rtr.Transaction);
await CompactIfRequired(backendManager, rtr, lastVolumeSize);
+ }
if (m_options.UploadVerificationFile && await m_result.TaskControl.ProgressRendevouz().ConfigureAwait(false))
{
diff --git a/Duplicati/License/Duplicati.License.csproj b/Duplicati/License/Duplicati.License.csproj
index d32900c23..ca829d99a 100644
--- a/Duplicati/License/Duplicati.License.csproj
+++ b/Duplicati/License/Duplicati.License.csproj
@@ -18,7 +18,7 @@
changelog.txt
PreserveNewest
-
+
licenses\license.txt
PreserveNewest
diff --git a/Duplicati/Server/webroot/ngax/templates/about.html b/Duplicati/Server/webroot/ngax/templates/about.html
index fceb6cf9f..6a148db1c 100644
--- a/Duplicati/Server/webroot/ngax/templates/about.html
+++ b/Duplicati/Server/webroot/ngax/templates/about.html
@@ -17,9 +17,9 @@
translate-params-mail1="'mailto:kenneth@duplicati.com'"
translate-params-mail2="'mailto:rene@duplicati.com'"
translate-params-websitename="'duplicati.com'"
- translate-params-websitelink="'http://www.duplicati.com'"
+ translate-params-websitelink="'https://duplicati.com'"
translate-params-licensename="'MIT license'"
- translate-params-licenselink="'https://raw.githubusercontent.com/duplicati/duplicati/master/LICENSE.txt'"
+ translate-params-licenselink="'https://raw.githubusercontent.com/duplicati/duplicati/master/LICENSE'"
>
{{appname}} was primarily developed by {{dev1}} and {{dev2}}. {{appname}} can be downloaded from {{websitename}}. {{appname}} is licensed under the {{licensename}}.
diff --git a/Duplicati/UnitTest/DisruptionTests.cs b/Duplicati/UnitTest/DisruptionTests.cs
index 3aa9ddcc8..c4a8f53e2 100644
--- a/Duplicati/UnitTest/DisruptionTests.cs
+++ b/Duplicati/UnitTest/DisruptionTests.cs
@@ -741,6 +741,9 @@ namespace Duplicati.UnitTest
using (var c = new Controller("file://" + TARGETFOLDER, testopts, null))
TestUtils.AssertResults(c.Backup(new string[] { DATAFOLDER }));
+ // Ensure that the target folder only has a single dlist file
+ Assert.AreEqual(1, Directory.EnumerateFiles(TARGETFOLDER, "*.dlist.*").Count(), "There should be only one dlist file in the target folder");
+
// Make a new backup that fails uploading a dblock file
ModifySourceFiles();
@@ -753,6 +756,7 @@ namespace Duplicati.UnitTest
var secondUploadCompleted = false;
// Fail the compact after the first dblock put is completed
+ var uploads = new List();
DeterministicErrorBackend.ErrorGenerator = (DeterministicErrorBackend.BackendAction action, string remotename) =>
{
if (action.IsGetOperation)
@@ -783,6 +787,11 @@ namespace Duplicati.UnitTest
Assert.That(secondUploadStarted, Is.True, "Second upload was not started");
Assert.That(secondUploadCompleted, Is.True, "Second upload was not started");
+ Assert.That(hasFailed, Is.True, "Failed to fail the upload");
+ Assert.That(!uploads.Any(x => x.Contains("dlist")), Is.True, "Upload of dlist file was not skipped");
+
+ // Ensure that the target folder only has a single dlist file
+ Assert.AreEqual(1, Directory.EnumerateFiles(TARGETFOLDER, "*.dlist.*").Count(), $"There should be only one dlist file in the target folder: {string.Join(", ", uploads)}");
// Create a regular backup
using (var c = new Controller("file://" + TARGETFOLDER, testopts, null))
diff --git a/ReleaseBuilder/Build/Command.CreatePackage.cs b/ReleaseBuilder/Build/Command.CreatePackage.cs
index 21232ab44..4d8de5310 100644
--- a/ReleaseBuilder/Build/Command.CreatePackage.cs
+++ b/ReleaseBuilder/Build/Command.CreatePackage.cs
@@ -819,7 +819,7 @@ public static partial class Command
// Write the license file
File.Copy(
- Path.Combine(baseDir, "LICENSE.txt"),
+ Path.Combine(baseDir, "LICENSE"),
EnsureFolderForFile(
Path.Combine(pkgroot, "usr", "share", "doc", "duplicati", "copyright")
)