diff --git a/Duplicati/Server/webroot/ngax/templates/restorewizard.html b/Duplicati/Server/webroot/ngax/templates/restorewizard.html
index 49a5d6fea..21c795378 100644
--- a/Duplicati/Server/webroot/ngax/templates/restorewizard.html
+++ b/Duplicati/Server/webroot/ngax/templates/restorewizard.html
@@ -26,7 +26,7 @@
Last successful restore: {{time}} (took {{duration || '0 seconds'}})
diff --git a/Duplicati/Service/Duplicati.Service.csproj b/Duplicati/Service/Duplicati.Service.csproj
index d4721401d..f4e9a4f18 100644
--- a/Duplicati/Service/Duplicati.Service.csproj
+++ b/Duplicati/Service/Duplicati.Service.csproj
@@ -1,14 +1,14 @@
-
+
Debug
AnyCPU
{E93F3DE2-FF3A-4709-96A3-8190AA14FA25}
Exe
- False
+ False
Duplicati.Service
Duplicati.Service
- v4.5
+ v4.6.2
false
@@ -32,6 +32,9 @@
true
false
+
+ true
+
diff --git a/Duplicati/Service/app.config b/Duplicati/Service/app.config
index 1e3d7fb2e..dd1b7be4b 100644
--- a/Duplicati/Service/app.config
+++ b/Duplicati/Service/app.config
@@ -1,27 +1,21 @@
-
+
+
+
-
-
-
-
-
-
-
-
-
-
+
+
-
+
-
-
+
+
diff --git a/Duplicati/Tools/Duplicati.Tools.csproj b/Duplicati/Tools/Duplicati.Tools.csproj
index efe428109..3506a2ff4 100644
--- a/Duplicati/Tools/Duplicati.Tools.csproj
+++ b/Duplicati/Tools/Duplicati.Tools.csproj
@@ -1,5 +1,5 @@
-
+
Debug
AnyCPU
@@ -7,8 +7,9 @@
Library
Duplicati.Tools
Duplicati.Tools
- v4.5
+ v4.6.2
false
+
true
diff --git a/Duplicati/UnitTest/BasicSetupHelper.cs b/Duplicati/UnitTest/BasicSetupHelper.cs
index d984fc13c..94b138059 100644
--- a/Duplicati/UnitTest/BasicSetupHelper.cs
+++ b/Duplicati/UnitTest/BasicSetupHelper.cs
@@ -74,23 +74,60 @@ namespace Duplicati.UnitTest
}
[OneTimeSetUp]
- public virtual void PrepareSourceData()
+ public virtual void OneTimeSetUp()
{
if (DEBUG_OUTPUT)
+ {
Console.SetOut(TestContext.Progress);
+ }
- ProgressWriteLine("Deleting backup data and log...");
- if (Directory.Exists(DATAFOLDER))
- Directory.Delete(DATAFOLDER, true);
- if (File.Exists(LOGFILE))
- File.Delete(LOGFILE);
- ProgressWriteLine("Deleting older data");
- if (File.Exists(DBFILE))
- File.Delete(DBFILE);
- if (Directory.Exists(TARGETFOLDER))
- Directory.Delete(TARGETFOLDER, true);
+ Directory.CreateDirectory(BASEFOLDER);
+ this.TearDown();
+ this.OneTimeTearDown();
}
+ [OneTimeTearDown]
+ public virtual void OneTimeTearDown()
+ {
+ // No-op by default.
+ }
+
+ [SetUp]
+ public void SetUp()
+ {
+ Directory.CreateDirectory(this.DATAFOLDER);
+ Directory.CreateDirectory(this.TARGETFOLDER);
+ Directory.CreateDirectory(this.RESTOREFOLDER);
+ }
+
+ [TearDown]
+ public virtual void TearDown()
+ {
+ if (Directory.Exists(this.DATAFOLDER))
+ {
+ Directory.Delete(this.DATAFOLDER, true);
+ }
+ if (Directory.Exists(this.TARGETFOLDER))
+ {
+ Directory.Delete(this.TARGETFOLDER, true);
+ }
+ if (Directory.Exists(this.RESTOREFOLDER))
+ {
+ Directory.Delete(this.RESTOREFOLDER, true);
+ }
+ if (File.Exists(this.LOGFILE))
+ {
+ File.Delete(this.LOGFILE);
+ }
+ if (File.Exists(this.DBFILE))
+ {
+ File.Delete(this.DBFILE);
+ }
+ if (File.Exists($"{this.DBFILE}-journal"))
+ {
+ File.Delete($"{this.DBFILE}-journal");
+ }
+ }
protected virtual Dictionary TestOptions
{
diff --git a/Duplicati/UnitTest/BorderTests.cs b/Duplicati/UnitTest/BorderTests.cs
index 68aa88e0a..c67a0a299 100644
--- a/Duplicati/UnitTest/BorderTests.cs
+++ b/Duplicati/UnitTest/BorderTests.cs
@@ -24,19 +24,22 @@ namespace Duplicati.UnitTest
{
public class BorderTests : BasicSetupHelper
{
- public override void PrepareSourceData()
- {
- base.PrepareSourceData();
+ private readonly string recreatedDatabaseFile = Path.Combine(BASEFOLDER, "recreated-database.sqlite");
- Directory.CreateDirectory(DATAFOLDER);
- Directory.CreateDirectory(TARGETFOLDER);
+ public override void TearDown()
+ {
+ base.TearDown();
+
+ if (File.Exists(this.recreatedDatabaseFile))
+ {
+ File.Delete(this.recreatedDatabaseFile);
+ }
}
[Test]
[Category("Border")]
public void Run10kNoProgress()
{
- PrepareSourceData();
RunCommands(1024 * 10, modifyOptions: opts => {
opts["disable-file-scanner"] = "true";
});
@@ -46,7 +49,6 @@ namespace Duplicati.UnitTest
[Category("Border")]
public void Run10k()
{
- PrepareSourceData();
RunCommands(1024 * 10);
}
@@ -54,7 +56,6 @@ namespace Duplicati.UnitTest
[Category("Border")]
public void Run10mb()
{
- PrepareSourceData();
RunCommands(1024 * 10, modifyOptions: opts => {
opts["blocksize"] = "10mb";
});
@@ -64,7 +65,6 @@ namespace Duplicati.UnitTest
[Category("Border")]
public void Run100k()
{
- PrepareSourceData();
RunCommands(1024 * 100);
}
@@ -72,7 +72,6 @@ namespace Duplicati.UnitTest
[Category("Border")]
public void Run12345_1()
{
- PrepareSourceData();
RunCommands(12345);
}
@@ -80,7 +79,6 @@ namespace Duplicati.UnitTest
[Category("Border")]
public void Run12345_2()
{
- PrepareSourceData();
RunCommands(12345, 1024 * 1024 * 10);
}
@@ -88,7 +86,6 @@ namespace Duplicati.UnitTest
[Category("Border")]
public void RunNoMetadata()
{
- PrepareSourceData();
RunCommands(1024 * 10, modifyOptions: opts => {
opts["skip-metadata"] = "true";
});
@@ -99,7 +96,6 @@ namespace Duplicati.UnitTest
[Category("Border")]
public void RunMD5()
{
- PrepareSourceData();
RunCommands(1024 * 10, modifyOptions: opts => {
opts["block-hash-algorithm"] = "MD5";
opts["file-hash-algorithm"] = "MD5";
@@ -110,7 +106,6 @@ namespace Duplicati.UnitTest
[Category("Border")]
public void RunSHA384()
{
- PrepareSourceData();
RunCommands(1024 * 10, modifyOptions: opts => {
opts["block-hash-algorithm"] = "SHA384";
opts["file-hash-algorithm"] = "SHA384";
@@ -121,7 +116,6 @@ namespace Duplicati.UnitTest
[Category("Border")]
public void RunMixedBlockFile_1()
{
- PrepareSourceData();
RunCommands(1024 * 10, modifyOptions: opts => {
opts["block-hash-algorithm"] = "MD5";
opts["file-hash-algorithm"] = "SHA1";
@@ -132,7 +126,6 @@ namespace Duplicati.UnitTest
[Category("Border")]
public void RunMixedBlockFile_2()
{
- PrepareSourceData();
RunCommands(1024 * 10, modifyOptions: opts => {
opts["block-hash-algorithm"] = "MD5";
opts["file-hash-algorithm"] = "SHA256";
@@ -143,7 +136,6 @@ namespace Duplicati.UnitTest
[Category("Border")]
public void RunNoIndexFiles()
{
- PrepareSourceData();
RunCommands(1024 * 10, modifyOptions: opts => {
opts["index-file-policy"] = "None";
});
@@ -153,7 +145,6 @@ namespace Duplicati.UnitTest
[Category("Border")]
public void RunSlimIndexFiles()
{
- PrepareSourceData();
RunCommands(1024 * 10, modifyOptions: opts => {
opts["index-file-policy"] = "Lookup";
});
@@ -163,7 +154,6 @@ namespace Duplicati.UnitTest
[Category("Border")]
public void RunQuickTimestamps()
{
- PrepareSourceData();
RunCommands(1024 * 10, modifyOptions: opts =>
{
opts["check-filetime-only"] = "true";
@@ -174,7 +164,6 @@ namespace Duplicati.UnitTest
[Category("Border")]
public void RunFullScan()
{
- PrepareSourceData();
RunCommands(1024 * 10, modifyOptions: opts =>
{
opts["disable-filetime-check"] = "true";
@@ -218,7 +207,7 @@ namespace Duplicati.UnitTest
private void RunCommands(int blocksize, int basedatasize = 0, Action> modifyOptions = null)
{
var testopts = TestOptions;
- testopts["blocksize"] = blocksize.ToString() + "b";
+ testopts["blocksize"] = blocksize.ToString() + "b";
modifyOptions?.Invoke(testopts);
var filenames = WriteTestFilesToFolder(DATAFOLDER, blocksize, basedatasize);
@@ -287,11 +276,7 @@ namespace Duplicati.UnitTest
Assert.AreEqual((filenames.Count * 3) + 1, r.Files.Count());
}
- var newdb = Path.Combine(Path.GetDirectoryName(DBFILE), Path.ChangeExtension(Path.GetFileNameWithoutExtension(DBFILE) + "-recreated", Path.GetExtension(DBFILE)));
- if (File.Exists(newdb))
- File.Delete(newdb);
-
- testopts["dbpath"] = newdb;
+ testopts["dbpath"] = this.recreatedDatabaseFile;
using(var c = new Library.Main.Controller("file://" + TARGETFOLDER, testopts, null))
c.Repair();
@@ -323,10 +308,6 @@ namespace Duplicati.UnitTest
Assert.AreEqual((filenames.Count * 3) + 1, r.Files.Count());
}
- if (Directory.Exists(RESTOREFOLDER))
- Directory.Delete(RESTOREFOLDER, true);
- Directory.CreateDirectory(RESTOREFOLDER);
-
using(var c = new Library.Main.Controller("file://" + TARGETFOLDER, testopts.Expand(new { restore_path = RESTOREFOLDER, no_local_blocks = true }), null))
{
var r = c.Restore(null);
diff --git a/Duplicati/UnitTest/CommandLineOperationsTests.cs b/Duplicati/UnitTest/CommandLineOperationsTests.cs
index 254a706aa..c7caa8616 100644
--- a/Duplicati/UnitTest/CommandLineOperationsTests.cs
+++ b/Duplicati/UnitTest/CommandLineOperationsTests.cs
@@ -19,35 +19,95 @@ using NUnit.Framework;
using System.Collections.Generic;
using System.IO;
using System.Linq;
+using System.Net;
namespace Duplicati.UnitTest
{
public class CommandLineOperationsTests : BasicSetupHelper
{
+ private static string S3_URL = $"https://s3.amazonaws.com/duplicati-test-file-hosting/";
+
///
/// The log tag
///
private static readonly string LOGTAG = Library.Logging.Log.LogTagFromType();
+
///
/// The folder that contains all the source data which the test is based on
///
protected readonly string SOURCEFOLDER = Path.Combine(BASEFOLDER, "data");
+ private readonly string zipFilename = "data.zip";
+ private string zipFilepath => Path.Combine(BASEFOLDER, this.zipFilename);
+
+ private readonly string zipAlternativeFilename = "data-alternative.zip";
+ private string zipAlternativeFilepath => Path.Combine(BASEFOLDER, this.zipAlternativeFilename);
+
protected virtual IEnumerable SourceDataFolders
{
get
{
- return
+ return
from x in Directory.EnumerateDirectories(SOURCEFOLDER)
orderby x
select x;
}
}
- [OneTimeSetUp]
- public override void PrepareSourceData()
+ public override void OneTimeSetUp()
{
- base.PrepareSourceData();
+ base.OneTimeSetUp();
+
+ if (!File.Exists(zipAlternativeFilepath))
+ {
+ var url = $"{S3_URL}{this.zipFilename}";
+ DownloadS3FileIfNewer(zipFilepath, url);
+ System.IO.Compression.ZipFile.ExtractToDirectory(this.zipFilepath, BASEFOLDER);
+ }
+ else
+ {
+ System.IO.Compression.ZipFile.ExtractToDirectory(this.zipAlternativeFilepath, BASEFOLDER);
+ }
+ }
+
+ private void DownloadS3FileIfNewer(string destinationFilePath, string url)
+ {
+ var webRequest = (HttpWebRequest)WebRequest.Create(url);
+
+ if (File.Exists(destinationFilePath))
+ {
+ webRequest.IfModifiedSince = File.GetLastWriteTimeUtc(destinationFilePath);
+ }
+
+ try
+ {
+ // check if the file should be downloaded, exception if not
+ var checkIfChangedWebResponse = (HttpWebResponse)webRequest.GetResponse();
+
+ using (WebClient client = new WebClient())
+ {
+ client.DownloadFile(url, destinationFilePath);
+ }
+ }
+ catch (WebException ex)
+ {
+ if (ex.Response == null){
+ throw;
+ }
+
+ if (((HttpWebResponse) ex.Response).StatusCode != HttpStatusCode.NotModified)
+ {
+ throw;
+ }
+ }
+ }
+
+ public override void OneTimeTearDown()
+ {
+ if (Directory.Exists(this.SOURCEFOLDER))
+ {
+ Directory.Delete(this.SOURCEFOLDER, true);
+ }
}
[Test]
@@ -55,8 +115,6 @@ namespace Duplicati.UnitTest
[Category("BulkNormal")]
public void RunCommands()
{
- if (Directory.Exists(DATAFOLDER))
- PrepareSourceData();
DoRunCommands(TARGETFOLDER);
}
@@ -65,8 +123,6 @@ namespace Duplicati.UnitTest
[Category("BulkNoSize")]
public void RunCommandsWithoutSize()
{
- if (Directory.Exists(DATAFOLDER))
- PrepareSourceData();
DoRunCommands(new SizeOmittingBackend().ProtocolKey + "://" + TARGETFOLDER);
}
@@ -86,12 +142,13 @@ namespace Duplicati.UnitTest
var foldername = Path.GetFileName(n);
var targetfolder = Path.Combine(DATAFOLDER, foldername);
ProgressWriteLine("Adding folder {0} to source", foldername);
- TestUtils.CopyDirectoryRecursive(n, targetfolder);
+
+ Directory.Move(n, targetfolder);
var size = Directory.EnumerateFiles(targetfolder, "*", SearchOption.AllDirectories).Select(x => new FileInfo(x).Length).Sum();
ProgressWriteLine("Running backup with {0} data added ...", Duplicati.Library.Utility.Utility.FormatSizeString(size));
- using(new Library.Logging.Timer(LOGTAG, "BackupWithDataAdded", string.Format("Backup with {0} data added", Duplicati.Library.Utility.Utility.FormatSizeString(size))))
+ using (new Library.Logging.Timer(LOGTAG, "BackupWithDataAdded", string.Format("Backup with {0} data added", Duplicati.Library.Utility.Utility.FormatSizeString(size))))
Duplicati.CommandLine.Program.RealMain(backupargs);
ProgressWriteLine("Testing data ...");
@@ -101,18 +158,18 @@ namespace Duplicati.UnitTest
}
ProgressWriteLine("Running unchanged backup ...");
- using(new Library.Logging.Timer(LOGTAG, "UnchangedBackup", "Unchanged backup"))
+ using (new Library.Logging.Timer(LOGTAG, "UnchangedBackup", "Unchanged backup"))
Duplicati.CommandLine.Program.RealMain(backupargs);
var datafolders = Directory.EnumerateDirectories(DATAFOLDER);
-
+
var f = datafolders.Skip(datafolders.Count() / 2).First();
ProgressWriteLine("Renaming folder {0}", Path.GetFileName(f));
Directory.Move(f, Path.Combine(Path.GetDirectoryName(f), Path.GetFileName(f) + "-renamed"));
ProgressWriteLine("Running backup with renamed folder...");
- using(new Library.Logging.Timer(LOGTAG, "BackupWithRenamedFolder", "Backup with renamed folder"))
+ using (new Library.Logging.Timer(LOGTAG, "BackupWithRenamedFolder", "Backup with renamed folder"))
Duplicati.CommandLine.Program.RealMain(backupargs);
datafolders = Directory.EnumerateDirectories(DATAFOLDER);
@@ -129,85 +186,74 @@ namespace Duplicati.UnitTest
File.Delete(n);
ProgressWriteLine("Running backup with deleted data...");
- using(new Library.Logging.Timer(LOGTAG, "BackupWithDeletedData", "Backup with deleted data"))
+ using (new Library.Logging.Timer(LOGTAG, "BackupWithDeletedData", "Backup with deleted data"))
Duplicati.CommandLine.Program.RealMain(backupargs);
ProgressWriteLine("Testing the compare method ...");
- using(new Library.Logging.Timer(LOGTAG, "CompareMethod", "Compare method"))
+ using (new Library.Logging.Timer(LOGTAG, "CompareMethod", "Compare method"))
Duplicati.CommandLine.Program.RealMain((new string[] { "compare", target, "0", "1" }.Union(opts)).ToArray());
- for(var i = 0; i < 5; i++)
+ for (var i = 0; i < 5; i++)
{
ProgressWriteLine("Running backup with changed logfile {0} of {1} ...", i + 1, 5);
File.Copy(LOGFILE, Path.Combine(SOURCEFOLDER, Path.GetFileName(LOGFILE)), true);
- using(new Library.Logging.Timer(LOGTAG, "BackupWithLogfileChange", string.Format("Backup with logfilechange {0}", i + 1)))
- Duplicati.CommandLine.Program.RealMain(backupargs);
+ using (new Library.Logging.Timer(LOGTAG, "BackupWithLogfileChange", string.Format("Backup with logfilechange {0}", i + 1)))
+ Duplicati.CommandLine.Program.RealMain(backupargs);
}
ProgressWriteLine("Compacting data ...");
- using(new Library.Logging.Timer(LOGTAG, "Compacting", "Compacting"))
+ using (new Library.Logging.Timer(LOGTAG, "Compacting", "Compacting"))
Duplicati.CommandLine.Program.RealMain((new string[] { "compact", target, "--small-file-max-count=2" }.Union(opts)).ToArray());
datafolders = Directory.EnumerateDirectories(DATAFOLDER);
var rf = datafolders.Skip(datafolders.Count() - 2).First();
- if (Directory.Exists(RESTOREFOLDER))
- Directory.Delete(RESTOREFOLDER, true);
-
ProgressWriteLine("Partial restore of {0} ...", Path.GetFileName(rf));
- using(new Library.Logging.Timer(LOGTAG, "PartialRestore", "Partial restore"))
+ using (new Library.Logging.Timer(LOGTAG, "PartialRestore", "Partial restore"))
Duplicati.CommandLine.Program.RealMain((new string[] { "restore", target, rf + "*", "--restore-path=\"" + RESTOREFOLDER + "\"" }.Union(opts)).ToArray());
ProgressWriteLine("Verifying partial restore ...");
using (new Library.Logging.Timer(LOGTAG, "VerifiationOfPartialRestore", "Verification of partial restored files"))
TestUtils.VerifyDir(rf, RESTOREFOLDER, true);
- if (Directory.Exists(RESTOREFOLDER))
- Directory.Delete(RESTOREFOLDER, true);
+ Directory.Delete(RESTOREFOLDER, true);
ProgressWriteLine("Partial restore of {0} without local db...", Path.GetFileName(rf));
- using(new Library.Logging.Timer(LOGTAG, "PartialRestoreWithoutLocalDb", "Partial restore without local db"))
+ using (new Library.Logging.Timer(LOGTAG, "PartialRestoreWithoutLocalDb", "Partial restore without local db"))
Duplicati.CommandLine.Program.RealMain((new string[] { "restore", target, rf + "*", "--restore-path=\"" + RESTOREFOLDER + "\"", "--no-local-db" }.Union(opts)).ToArray());
ProgressWriteLine("Verifying partial restore ...");
using (new Library.Logging.Timer(LOGTAG, "VerificationOfPartialRestore", "Verification of partial restored files"))
TestUtils.VerifyDir(rf, RESTOREFOLDER, true);
-
- if (Directory.Exists(RESTOREFOLDER))
- Directory.Delete(RESTOREFOLDER, true);
+
+ Directory.Delete(RESTOREFOLDER, true);
ProgressWriteLine("Full restore ...");
- using(new Library.Logging.Timer(LOGTAG, "FullRestore", "Full restore"))
+ using (new Library.Logging.Timer(LOGTAG, "FullRestore", "Full restore"))
Duplicati.CommandLine.Program.RealMain((new string[] { "restore", target, "*", "--restore-path=\"" + RESTOREFOLDER + "\"" }.Union(opts)).ToArray());
ProgressWriteLine("Verifying full restore ...");
using (new Library.Logging.Timer(LOGTAG, "VerificationOfFullRestore", "Verification of restored files"))
- foreach(var s in Directory.EnumerateDirectories(DATAFOLDER))
+ foreach (var s in Directory.EnumerateDirectories(DATAFOLDER))
TestUtils.VerifyDir(s, Path.Combine(RESTOREFOLDER, Path.GetFileName(s)), true);
- if (Directory.Exists(RESTOREFOLDER))
- Directory.Delete(RESTOREFOLDER, true);
+ Directory.Delete(RESTOREFOLDER, true);
ProgressWriteLine("Full restore without local db...");
- using(new Library.Logging.Timer(LOGTAG, "FullRestoreWithoutDb", "Full restore without local db"))
+ using (new Library.Logging.Timer(LOGTAG, "FullRestoreWithoutDb", "Full restore without local db"))
Duplicati.CommandLine.Program.RealMain((new string[] { "restore", target, "*", "--restore-path=\"" + RESTOREFOLDER + "\"", "--no-local-db" }.Union(opts)).ToArray());
ProgressWriteLine("Verifying full restore ...");
using (new Library.Logging.Timer(LOGTAG, "VerificationOfFullRestoreWithoutDb", "Verification of restored files"))
- foreach(var s in Directory.EnumerateDirectories(DATAFOLDER))
+ foreach (var s in Directory.EnumerateDirectories(DATAFOLDER))
TestUtils.VerifyDir(s, Path.Combine(RESTOREFOLDER, Path.GetFileName(s)), true);
-
+
ProgressWriteLine("Testing data ...");
using (new Library.Logging.Timer(LOGTAG, "TestRemoteData", "Test remote data"))
if (Duplicati.CommandLine.Program.RealMain((new string[] { "test", target, "all" }.Union(opts)).ToArray()) != 0)
throw new Exception("Failed during final remote verification");
-
- foreach (var datafolder in datafolders)
- {
- Directory.Delete(datafolder, true);
- }
}
}
}
diff --git a/Duplicati/UnitTest/Duplicati.UnitTest.csproj b/Duplicati/UnitTest/Duplicati.UnitTest.csproj
index 3587361e8..0dc6ca622 100644
--- a/Duplicati/UnitTest/Duplicati.UnitTest.csproj
+++ b/Duplicati/UnitTest/Duplicati.UnitTest.csproj
@@ -1,5 +1,6 @@
-
+
+
Debug
AnyCPU
@@ -7,8 +8,11 @@
Library
Duplicati.UnitTest
Duplicati.UnitTest
- v4.5
+ v4.6.2
false
+
+
+
true
@@ -28,11 +32,15 @@
4
false
+
+ true
+
-
-
- ..\..\packages\NUnit.3.5.0\lib\net45\nunit.framework.dll
+
+ ..\..\packages\NUnit.3.12.0\lib\net45\nunit.framework.dll
+
+
@@ -122,10 +130,6 @@
{0CA86ECF-5BEC-4909-B4F6-110A03B30B92}
Duplicati.Library.DynamicLoader
-
- {94484FDB-2EFA-4CF0-9BE6-A561157B4F87}
- Duplicati.Library.Encryption
-
{C5899F45-B0FF-483C-9D38-24A9FCAAB237}
Duplicati.Library.Interface
@@ -187,4 +191,10 @@
+
+
+ This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.
+
+
+
\ No newline at end of file
diff --git a/Duplicati/UnitTest/FilterTest.cs b/Duplicati/UnitTest/FilterTest.cs
index 3b715aad0..602afbdb7 100644
--- a/Duplicati/UnitTest/FilterTest.cs
+++ b/Duplicati/UnitTest/FilterTest.cs
@@ -14,26 +14,18 @@
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-using System;
-using System.Collections.Generic;
-using System.IO;
-using System.Linq;
-using Duplicati.Library.Common.IO;
-using Duplicati.Library.Utility;
-using NUnit.Framework;
-
-namespace Duplicati.UnitTest
-{
- public class FilterTest : BasicSetupHelper
- {
- public override void PrepareSourceData()
- {
- base.PrepareSourceData();
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using Duplicati.Library.Common.IO;
+using Duplicati.Library.Utility;
+using NUnit.Framework;
- Directory.CreateDirectory(DATAFOLDER);
- Directory.CreateDirectory(TARGETFOLDER);
- }
-
+namespace Duplicati.UnitTest
+{
+ public class FilterTest : BasicSetupHelper
+ {
[Test]
[Category("Filter")]
public void TestEmptyFolderExclude()
@@ -158,38 +150,38 @@ namespace Duplicati.UnitTest
if (files != 0)
throw new Exception($"Empty not satisfied, found {files} files, but expected 0");
}
- }
-
- [Test]
- [Category("Filter")]
- public static void WildcardPatterns()
+ }
+
+ [Test]
+ [Category("Filter")]
+ public static void WildcardPatterns()
{
- // These examples were taken from https://www.c-sharpcorner.com/uploadfile/b81385/efficient-string-matching-algorithm-with-use-of-wildcard-characters/.
- Dictionary shouldMatch = new Dictionary
- {
- { @"*", "Something" },
- { @"S*eth??g", "Something" },
- { @"A *?string*", "A very long long long stringggggggg" },
- { @"Performance issue when using *,Window server ???? R? and java *.*.*_*", "Performance issue when using WebSphere MQ 7.1 ,Window server 2008 R2 and java 1.6.0_21" },
- { @"Performance* and java 1.6.0_21", "Performance issue when using WebSphere MQ 7.1 ,Window server 2008 R2 and java 1.6.0_21" }
- };
-
+ // These examples were taken from https://www.c-sharpcorner.com/uploadfile/b81385/efficient-string-matching-algorithm-with-use-of-wildcard-characters/.
+ Dictionary shouldMatch = new Dictionary
+ {
+ { @"*", "Something" },
+ { @"S*eth??g", "Something" },
+ { @"A *?string*", "A very long long long stringggggggg" },
+ { @"Performance issue when using *,Window server ???? R? and java *.*.*_*", "Performance issue when using WebSphere MQ 7.1 ,Window server 2008 R2 and java 1.6.0_21" },
+ { @"Performance* and java 1.6.0_21", "Performance issue when using WebSphere MQ 7.1 ,Window server 2008 R2 and java 1.6.0_21" }
+ };
+
Dictionary shouldNotMatch = new Dictionary
{
{ @"Performance issue when using *,Window server ???? R? and java *.*.*_", "Performance issue when using WebSphere MQ 7.1 ,Window server 2008 R2 and java 1.6.0_21" }
- };
-
- foreach (KeyValuePair entry in shouldMatch)
- {
+ };
+
+ foreach (KeyValuePair entry in shouldMatch)
+ {
IFilter filter = new FilterExpression(entry.Key);
- Assert.IsTrue(filter.Matches(entry.Value, out _, out _));
+ Assert.IsTrue(filter.Matches(entry.Value, out _, out _));
}
- foreach (KeyValuePair entry in shouldNotMatch)
- {
- IFilter filter = new FilterExpression(entry.Key);
+ foreach (KeyValuePair entry in shouldNotMatch)
+ {
+ IFilter filter = new FilterExpression(entry.Key);
Assert.IsFalse(filter.Matches(entry.Value, out _, out _));
- }
- }
- }
-}
+ }
+ }
+ }
+}
diff --git a/Duplicati/UnitTest/GeneralBlackBoxTesting.cs b/Duplicati/UnitTest/GeneralBlackBoxTesting.cs
index eeb3c2a87..75bb9fbf3 100644
--- a/Duplicati/UnitTest/GeneralBlackBoxTesting.cs
+++ b/Duplicati/UnitTest/GeneralBlackBoxTesting.cs
@@ -19,18 +19,17 @@ using System.Linq;
using System.IO;
using System;
using System.Collections.Generic;
+using System.Net;
using System.Reflection;
+using Duplicati.Library.Utility;
namespace Duplicati.UnitTest
{
- public class GeneralBlackBoxTesting
+ public class GeneralBlackBoxTesting : BasicSetupHelper
{
- private static readonly string SOURCE_FOLDERS =
- Path.Combine(
- string.IsNullOrWhiteSpace(Environment.GetEnvironmentVariable("UNITTEST_BASEFOLDER"))
- ? Path.Combine(Library.Utility.Utility.HOME_PATH, "duplicati_testdata")
- : Environment.GetEnvironmentVariable("UNITTEST_BASEFOLDER")
- , "DSMCBE");
+ private static readonly string SOURCE_FOLDERS = Path.Combine(BASEFOLDER, "DSMCBE");
+ private readonly string zipFilename = "DSMCBE.zip";
+ private string zipFilepath => Path.Combine(BASEFOLDER, this.zipFilename);
protected IEnumerable TestFolders
{
@@ -46,7 +45,7 @@ namespace Duplicati.UnitTest
}
}
- protected Dictionary TestOptions
+ protected override Dictionary TestOptions
{
get
{
@@ -62,12 +61,38 @@ namespace Duplicati.UnitTest
return x == "x" ? null : x;
}
}
+
+ public override void OneTimeSetUp()
+ {
+ base.OneTimeSetUp();
+
+ using (WebClient client = new WebClient())
+ {
+ client.DownloadFile($"https://s3.amazonaws.com/duplicati-test-file-hosting/{this.zipFilename}", this.zipFilepath);
+ }
+
+ System.IO.Compression.ZipFile.ExtractToDirectory(this.zipFilepath, BASEFOLDER);
+ }
+
+ public override void OneTimeTearDown()
+ {
+ if (Directory.Exists(SOURCE_FOLDERS))
+ {
+ Directory.Delete(SOURCE_FOLDERS, true);
+ }
+ if (File.Exists(this.zipFilepath))
+ {
+ File.Delete(this.zipFilepath);
+ }
+ }
+
[Test]
[Category("SVNData")]
public void TestWithSVNShort()
{
SVNCheckoutTest.RunTest(TestFolders.Take(5).ToArray(), TestOptions, TestTarget);
}
+
[Test]
[Category("SVNDataLong")]
public void TestWithSVNLong()
diff --git a/Duplicati/UnitTest/Issue1410.cs b/Duplicati/UnitTest/Issue1410.cs
index d610daa19..9effb49a0 100644
--- a/Duplicati/UnitTest/Issue1410.cs
+++ b/Duplicati/UnitTest/Issue1410.cs
@@ -24,15 +24,6 @@ namespace Duplicati.UnitTest
{
public class Issue1410 : BasicSetupHelper
{
- [OneTimeSetUp]
- public override void PrepareSourceData()
- {
- base.PrepareSourceData();
-
- Directory.CreateDirectory(DATAFOLDER);
- Directory.CreateDirectory(TARGETFOLDER);
- }
-
[Test]
[Category("Targeted")]
public void RunCommands()
diff --git a/Duplicati/UnitTest/Issue1723.cs b/Duplicati/UnitTest/Issue1723.cs
index c805fb75e..25aeb2159 100644
--- a/Duplicati/UnitTest/Issue1723.cs
+++ b/Duplicati/UnitTest/Issue1723.cs
@@ -22,15 +22,6 @@ namespace Duplicati.UnitTest
{
public class Issue1723 : BasicSetupHelper
{
- [OneTimeSetUp]
- public override void PrepareSourceData()
- {
- base.PrepareSourceData();
-
- Directory.CreateDirectory(DATAFOLDER);
- Directory.CreateDirectory(TARGETFOLDER);
- }
-
[Test]
[Category("Targeted")]
public void RunCommands()
diff --git a/Duplicati/UnitTest/PurgeTesting.cs b/Duplicati/UnitTest/PurgeTesting.cs
index a5e253e36..86d165879 100644
--- a/Duplicati/UnitTest/PurgeTesting.cs
+++ b/Duplicati/UnitTest/PurgeTesting.cs
@@ -18,28 +18,18 @@ using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
-using Duplicati.Library.Common.IO;
-using Duplicati.Library.Utility;
+using Duplicati.Library.Common.IO;
+using Duplicati.Library.Utility;
using NUnit.Framework;
namespace Duplicati.UnitTest
{
public class PurgeTesting : BasicSetupHelper
{
- public override void PrepareSourceData()
- {
- base.PrepareSourceData();
-
- Directory.CreateDirectory(DATAFOLDER);
- Directory.CreateDirectory(TARGETFOLDER);
- }
-
[Test]
[Category("Purge")]
public void PurgeTest()
{
- PrepareSourceData();
-
var blocksize = 1024 * 10;
var basedatasize = 0;
@@ -165,8 +155,6 @@ namespace Duplicati.UnitTest
[Category("Purge")]
public void PurgeBrokenFilesTest()
{
- PrepareSourceData();
-
var blocksize = 1024 * 10;
var basedatasize = 0;
diff --git a/Duplicati/UnitTest/RunScriptTests.cs b/Duplicati/UnitTest/RunScriptTests.cs
index 646f28c7d..30a9eaabd 100644
--- a/Duplicati/UnitTest/RunScriptTests.cs
+++ b/Duplicati/UnitTest/RunScriptTests.cs
@@ -14,32 +14,22 @@
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-using System;
+using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
-using Duplicati.Library.Common;
+using Duplicati.Library.Common;
using Duplicati.Library.Interface;
using NUnit.Framework;
-namespace Duplicati.UnitTest
-{
- public class RunScriptTests : BasicSetupHelper
+namespace Duplicati.UnitTest
+{
+ public class RunScriptTests : BasicSetupHelper
{
- public override void PrepareSourceData()
- {
- base.PrepareSourceData();
-
- Directory.CreateDirectory(DATAFOLDER);
- Directory.CreateDirectory(TARGETFOLDER);
- }
-
[Test]
[Category("Border")]
public void RunScriptBefore()
{
- PrepareSourceData();
-
var blocksize = 10 * 1024;
var options = TestOptions;
options["blocksize"] = blocksize.ToString() + "b";
@@ -196,6 +186,6 @@ namespace Duplicati.UnitTest
return filename;
}
- }
- }
-}
+ }
+ }
+}
diff --git a/Duplicati/UnitTest/TestUtils.cs b/Duplicati/UnitTest/TestUtils.cs
index 80e301b9b..0c8732d65 100644
--- a/Duplicati/UnitTest/TestUtils.cs
+++ b/Duplicati/UnitTest/TestUtils.cs
@@ -21,6 +21,8 @@ using Duplicati.Library.Utility;
using System.Linq;
using Duplicati.Library.Logging;
using System.Reflection;
+using System.Threading;
+using System.Threading.Tasks;
using Duplicati.Library.Common.IO;
namespace Duplicati.UnitTest
@@ -46,6 +48,30 @@ namespace Duplicati.UnitTest
}
}
+ public static async Task GrowingFile(string testFile, CancellationToken token)
+ {
+ try
+ {
+ var str = new string('*', 50);
+ while (true)
+ {
+ if (token.IsCancellationRequested)
+ {
+ continue;
+ }
+ File.AppendAllText(testFile, str);
+ await Task.Delay(18, token).ConfigureAwait(false);
+ }
+ }
+ finally
+ {
+ if (File.Exists(testFile))
+ {
+ File.Delete(testFile);
+ }
+ }
+ }
+
public static string GetDefaultTarget(string other = null)
{
string alttarget = System.IO.Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "unittest_target.txt");
diff --git a/Duplicati/UnitTest/UtilityTests.cs b/Duplicati/UnitTest/UtilityTests.cs
index 2ef4c7a59..66823f16d 100644
--- a/Duplicati/UnitTest/UtilityTests.cs
+++ b/Duplicati/UnitTest/UtilityTests.cs
@@ -22,6 +22,8 @@ using System.Collections.Generic;
using System.Linq;
using System.Globalization;
using System.IO;
+using System.Threading;
+using System.Threading.Tasks;
namespace Duplicati.UnitTest
{
@@ -94,6 +96,35 @@ namespace Duplicati.UnitTest
}
}
+ [Test]
+ [Category("Utility")]
+ public static void ReadLimitLengthStreamWithGrowingFile()
+ {
+ var growingFilename = Path.GetTempFileName();
+ long fixedGrowingStreamLength, limitStreamLength, nextGrowingStreamLength;
+ using (CancellationTokenSource tokenSource = new CancellationTokenSource())
+ {
+ Task task = TestUtils.GrowingFile(growingFilename, tokenSource.Token);
+ Thread.Sleep(100);
+ using (FileStream growingStream = new FileStream(growingFilename, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
+ {
+ Thread.Sleep(100);
+ fixedGrowingStreamLength = growingStream.Length;
+ Thread.Sleep(100);
+ using (var limitStream = new ReadLimitLengthStream(growingStream, fixedGrowingStreamLength))
+ {
+ Thread.Sleep(100);
+ nextGrowingStreamLength = growingStream.Length;
+ limitStreamLength = limitStream.Length;
+ }
+ }
+ }
+ Console.WriteLine($"fixedGrowingStreamLength:{fixedGrowingStreamLength} limitStreamLength:{limitStreamLength} nextGrowingStreamLength:{nextGrowingStreamLength}");
+ Assert.IsTrue(fixedGrowingStreamLength > 0);
+ Assert.AreEqual(fixedGrowingStreamLength, limitStreamLength);
+ Assert.IsTrue(limitStreamLength < nextGrowingStreamLength);
+ }
+
[Test]
[Category("Utility")]
public static void ForceStreamRead()
@@ -169,6 +200,32 @@ namespace Duplicati.UnitTest
Assert.IsNotNull(actualDuplicateItems);
}
+ [Test]
+ [Category("Utility")]
+ public void NormalizeDateTime()
+ {
+ DateTime baseDateTime = new DateTime(2000, 1, 2, 3, 4, 5);
+ DateTime baseDateTimeUTC = baseDateTime.ToUniversalTime();
+ Assert.AreEqual(baseDateTimeUTC, Utility.NormalizeDateTime(baseDateTime.AddMilliseconds(1)));
+ Assert.AreEqual(baseDateTimeUTC, Utility.NormalizeDateTime(baseDateTime.AddMilliseconds(500)));
+ Assert.AreEqual(baseDateTimeUTC, Utility.NormalizeDateTime(baseDateTime.AddMilliseconds(999)));
+ Assert.AreEqual(baseDateTimeUTC.AddSeconds(-1), Utility.NormalizeDateTime(baseDateTime.AddMilliseconds(-1)));
+ Assert.AreEqual(baseDateTimeUTC.AddSeconds(1), Utility.NormalizeDateTime(baseDateTime.AddSeconds(1.9)));
+ }
+
+ [Test]
+ [Category("Utility")]
+ public void NormalizeDateTimeToEpochSeconds()
+ {
+ DateTime baseDateTime = new DateTime(2000, 1, 2, 3, 4, 5);
+ long epochSeconds = (long) (baseDateTime.ToUniversalTime() - Utility.EPOCH).TotalSeconds;
+ Assert.AreEqual(epochSeconds, Utility.NormalizeDateTimeToEpochSeconds(baseDateTime.AddMilliseconds(1)));
+ Assert.AreEqual(epochSeconds, Utility.NormalizeDateTimeToEpochSeconds(baseDateTime.AddMilliseconds(500)));
+ Assert.AreEqual(epochSeconds, Utility.NormalizeDateTimeToEpochSeconds(baseDateTime.AddMilliseconds(999)));
+ Assert.AreEqual(epochSeconds - 1, Utility.NormalizeDateTimeToEpochSeconds(baseDateTime.AddMilliseconds(-1)));
+ Assert.AreEqual(epochSeconds + 1, Utility.NormalizeDateTimeToEpochSeconds(baseDateTime.AddSeconds(1.9)));
+ }
+
[Test]
[Category("Utility")]
public void ParseBool()
diff --git a/Duplicati/UnitTest/app.config b/Duplicati/UnitTest/app.config
index f171dd7bb..fa5edff2d 100644
--- a/Duplicati/UnitTest/app.config
+++ b/Duplicati/UnitTest/app.config
@@ -1,27 +1,20 @@
+
-
-
-
-
-
-
-
-
-
-
+
+
-
+
-
-
+
+
-
\ No newline at end of file
+
diff --git a/Duplicati/UnitTest/packages.config b/Duplicati/UnitTest/packages.config
index c108d442f..20d68e1a3 100644
--- a/Duplicati/UnitTest/packages.config
+++ b/Duplicati/UnitTest/packages.config
@@ -1,4 +1,4 @@
-
+
\ No newline at end of file
diff --git a/Duplicati/WindowsService/App.config b/Duplicati/WindowsService/App.config
index 877624ed9..e89424bca 100644
--- a/Duplicati/WindowsService/App.config
+++ b/Duplicati/WindowsService/App.config
@@ -1,6 +1,6 @@
-
+
diff --git a/Duplicati/WindowsService/WindowsService.csproj b/Duplicati/WindowsService/WindowsService.csproj
index a5b3b96b0..727c1f75a 100644
--- a/Duplicati/WindowsService/WindowsService.csproj
+++ b/Duplicati/WindowsService/WindowsService.csproj
@@ -1,5 +1,5 @@
-
+
Debug
@@ -10,7 +10,7 @@
Properties
Duplicati.WindowsService
Duplicati.WindowsService
- v4.5
+ v4.6.2
512
true
diff --git a/Installer/AssemblyRedirects.xml b/Installer/AssemblyRedirects.xml
index f031c1dc1..57f8304b0 100644
--- a/Installer/AssemblyRedirects.xml
+++ b/Installer/AssemblyRedirects.xml
@@ -20,13 +20,25 @@
-
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+
\ No newline at end of file
diff --git a/Installer/Docker/README.md b/Installer/Docker/README.md
index 3047e2f69..ffcf4527e 100644
--- a/Installer/Docker/README.md
+++ b/Installer/Docker/README.md
@@ -3,7 +3,7 @@ Duplicati is a free, open source, backup client that securely stores encrypted,
*Amazon S3, OneDrive, Google Drive, Rackspace Cloud Files, HubiC, Backblaze (B2), Amazon Cloud Drive (AmzCD), Swift / OpenStack, WebDAV, SSH (SFTP), FTP, and more!*
-Duplicati is licensed under LGPL and available for Windows, OSX and Linux (.NET 4.5+ or Mono required).
+Duplicati is licensed under LGPL and available for Windows, OSX and Linux (.NET 4.6.2+ or Mono 4.8.0+ required).
## Available tags
diff --git a/Installer/Windows/Duplicati.wxs b/Installer/Windows/Duplicati.wxs
index acef64ab6..06f68b91d 100644
--- a/Installer/Windows/Duplicati.wxs
+++ b/Installer/Windows/Duplicati.wxs
@@ -26,9 +26,9 @@
-
-
-
+
+
+
@@ -84,13 +84,13 @@
-
+
-
+
diff --git a/Installer/Windows/UpgradeLog.htm b/Installer/Windows/UpgradeLog.htm
new file mode 100644
index 000000000..371f58c3a
Binary files /dev/null and b/Installer/Windows/UpgradeLog.htm differ
diff --git a/Installer/Windows/WixInstaller.wixproj b/Installer/Windows/WixInstaller.wixproj
index c2d1f0b3f..1a8374ec6 100644
--- a/Installer/Windows/WixInstaller.wixproj
+++ b/Installer/Windows/WixInstaller.wixproj
@@ -1,4 +1,4 @@
-
+
Debug
x64
@@ -71,9 +71,9 @@
-
-
-
-
-
+
+
+
+
+
\ No newline at end of file
diff --git a/README.md b/README.md
index e723e08a8..5b4182704 100644
--- a/README.md
+++ b/README.md
@@ -23,7 +23,7 @@ Duplicati is a free, open source, backup client that securely stores encrypted,
*Amazon Cloud Drive and S3, [Backblaze (B2)](https://www.backblaze.com/blog/duplicati-backups-cloud-storage/ "Duplicati with Backblaze B2 Cloud Storage"), Box, Dropbox, FTP, Google Cloud and Drive, HubiC, MEGA, Microsoft Azure and OneDrive, Rackspace Cloud Files, OpenStack Storage (Swift), Sia, SSH (SFTP), WebDAV, [and more!](https://duplicati.readthedocs.io/en/latest/01-introduction/#supported-backends)*
-Duplicati is licensed under LGPL and available for Windows, OSX and Linux (.NET 4.5+ or Mono required).
+Duplicati is licensed under LGPL and available for Windows, OSX and Linux (.NET 4.6.2+ or Mono 4.8.0+ required).
Download
========
diff --git a/Tools/SQLiteTool/App.config b/Tools/SQLiteTool/App.config
index 2ae22ede8..e6848d0ef 100644
--- a/Tools/SQLiteTool/App.config
+++ b/Tools/SQLiteTool/App.config
@@ -1,6 +1,6 @@
-
+
-
+
-
\ No newline at end of file
+
diff --git a/Tools/SQLiteTool/SQLiteTool.csproj b/Tools/SQLiteTool/SQLiteTool.csproj
index 04d4d84b3..4a4c19948 100644
--- a/Tools/SQLiteTool/SQLiteTool.csproj
+++ b/Tools/SQLiteTool/SQLiteTool.csproj
@@ -1,5 +1,5 @@
-
+
Debug
AnyCPU
@@ -7,10 +7,11 @@
2.0
{3B546BD0-7549-4CE3-9B68-5C149B8AA2E7}
Exe
- False
+ False
SQLiteTool
SQLiteTool
- v4.5
+ v4.6.2
+
full
diff --git a/Tools/ZipFileDebugger/ZipFileDebugger.csproj b/Tools/ZipFileDebugger/ZipFileDebugger.csproj
index 8ad515a68..408dd657d 100644
--- a/Tools/ZipFileDebugger/ZipFileDebugger.csproj
+++ b/Tools/ZipFileDebugger/ZipFileDebugger.csproj
@@ -1,4 +1,4 @@
-
+
Debug
@@ -7,7 +7,8 @@
Exe
ZipFileDebugger
ZipFileDebugger
- v4.6.1
+ v4.6.2
+
true
@@ -47,5 +48,8 @@
Duplicati.Library.Logging
+
+
+
\ No newline at end of file
diff --git a/Tools/ZipFileDebugger/app.config b/Tools/ZipFileDebugger/app.config
new file mode 100644
index 000000000..2a0024f75
--- /dev/null
+++ b/Tools/ZipFileDebugger/app.config
@@ -0,0 +1,3 @@
+
+
+
diff --git a/Updates/build_version.txt b/Updates/build_version.txt
index 409940768..9902f1784 100644
--- a/Updates/build_version.txt
+++ b/Updates/build_version.txt
@@ -1 +1 @@
-23
+28
diff --git a/build-release.sh b/build-release.sh
index 5fec34ee2..0775f9dd1 100644
--- a/build-release.sh
+++ b/build-release.sh
@@ -125,7 +125,8 @@ fi
rm -rf "Duplicati/GUI/Duplicati.GUI.TrayIcon/bin/Release"
-"${XBUILD}" /property:Configuration=Release "BuildTools/UpdateVersionStamp/UpdateVersionStamp.csproj"
+"${NUGET}" restore "BuildTools/UpdateVersionStamp/UpdateVersionStamp.sln"
+"${XBUILD}" /property:Configuration=Release "BuildTools/UpdateVersionStamp/UpdateVersionStamp.sln"
"${MONO}" "BuildTools/UpdateVersionStamp/bin/Release/UpdateVersionStamp.exe" --version="${RELEASE_VERSION}"
"${NUGET}" restore "BuildTools/AutoUpdateBuilder/AutoUpdateBuilder.sln"
diff --git a/build.sh b/build.sh
index 7f4610b83..12008517c 100755
--- a/build.sh
+++ b/build.sh
@@ -32,51 +32,14 @@ msbuild /p:Configuration=Release Duplicati.sln
cp -r ./Duplicati/Server/webroot ./Duplicati/GUI/Duplicati.GUI.TrayIcon/bin/Release/webroot
echo "travis_fold:end:build_duplicati"
-# download and extract testdata
-echo "travis_fold:start:download_extract_testdata"
-list_dir .
-
-if [ ! -d ~/tmp ]; then mkdir ~/tmp; fi
-if [ ! -d ~/download ]; then mkdir ~/download; fi
-if [ ! -d ~/download/svn ]; then mkdir ~/download/svn; fi
-if [ ! -d ~/download/bulk ]; then mkdir ~/download/bulk; fi
-
-if [ "$CATEGORY" == "SVNData" ] || [ "$CATEGORY" == "SVNDataLong" ]; then
- # test if zip file exists and contains no errors
- unzip -t ~/download/svn/DSMCBE.zip &> /dev/null || \
- wget --progress=dot:giga "https://s3.amazonaws.com/duplicati-test-file-hosting/DSMCBE.zip" -O ~/download/svn/DSMCBE.zip
- list_dir ~/download/svn
-fi
-
-if [ "$CATEGORY" == "BulkNormal" ] || [ "$CATEGORY" == "BulkNoSize" ]; then
- # test if zip file exists and contains no errors
- unzip -t ~/download/bulk/data.zip &> /dev/null || \
- wget --progress=dot:giga "https://s3.amazonaws.com/duplicati-test-file-hosting/data.zip" -O ~/download/bulk/data.zip
- list_dir ~/download/bulk
-fi
-
rm -rf ~/duplicati_testdata && mkdir ~/duplicati_testdata
-
-if [ "$CATEGORY" == "SVNData" ] || [ "$CATEGORY" == "SVNDataLong" ]; then
- mkdir ~/duplicati_testdata/DSMCBE
- unzip -q ~/download/svn/DSMCBE.zip -d ~/duplicati_testdata/
- list_dir ~/duplicati_testdata/DSMCBE
-fi
-
-if [ "$CATEGORY" == "BulkNormal" ] || [ "$CATEGORY" == "BulkNoSize" ]; then
- mkdir ~/duplicati_testdata/data
- unzip -q ~/download/bulk/data.zip -d ~/duplicati_testdata/
- list_dir ~/duplicati_testdata/data
-fi
-
chown -R $TESTUSER ~/duplicati_testdata/
chmod -R 755 ~/duplicati_testdata
-echo "travis_fold:end:download_extract_testdata"
# run unit tests
echo "travis_fold:start:unit_test"
if [[ "$CATEGORY" != "GUI" && "$CATEGORY" != "" ]]; then
- mono ./testrunner/NUnit.ConsoleRunner.3.5.0/tools/nunit3-console.exe \
+ mono ./testrunner/NUnit.ConsoleRunner.3.10.0/tools/nunit3-console.exe \
./Duplicati/UnitTest/bin/Release/Duplicati.UnitTest.dll --where:cat==$CATEGORY --workers=1
fi
echo "travis_fold:end:unit_test"
diff --git a/changelog.txt b/changelog.txt
index 498022784..167ecc513 100644
--- a/changelog.txt
+++ b/changelog.txt
@@ -1,3 +1,97 @@
+2019-09-05 - 2.0.4.28_canary_2019-09-05
+==========
+* Updated CoCoL and WiX to fix rollback and upgrade errors, thanks @BlueBlock
+
+2019-09-03 - 2.0.4.27_canary_2019-09-03
+==========
+* Fixed issues with the MSI packages not upgrading correctly, thanks @BlueBlock
+* Fixed some assembly redirects and package references, thanks @BlueBlock
+* Code cleanup for EPOCH times, thanks @warwickmm
+
+2019-09-02 - 2.0.4.26_canary_2019-09-02
+==========
+== This is a rebuild of 2.0.4.24 with MSI packages and **new** assembly redirect fixes ==
+
+Change list from 2.0.4.24:
+* Code cleanup, thanks @warwickmm
+* Removed extra console output, thanks @wjansenw
+* Fixed disposing backends after job completion, thanks @warwickmm
+* Fixed an issue with throttled write, thanks @warwickmm
+* Spelling fix, thanks @BlueBlock
+* Fixed documetation in `run-script` examples, thanks @beppo-dd
+* Improved unittests, thanks @BlueBlock
+* Improved auto-compact and auto-vacuum, thanks @drwtsn32x
+* Fixed problem with exceeeding the number of parameters supported by SQLite, thanks @drwtsn32x
+* Improved status display, thanks @drwtsn32x
+* Improved bugreport database scrubbing, thanks @drwtsn32x
+* Removed GoogleDrive trash items in listing, thanks @BlueBlock
+* Fixed the rename method in the GoogleDrive backend, thanks @BlueBlock
+* Improved GCS storage class text, thanks @warwickmm
+* Improved unittests for easier local testing, thanks @warwickmm
+* Added workaround for AFTP upload delay, thanks @BlueBlock
+* Fixed issue with reading the largest path prefix, thanks @BlueBlock
+* Added conditional download of unittest data zip files, thanks @BlueBlock
+* CI testing improvements, thanks @BlueBlock
+* Fixed sporadic issue with backups of files being written, thanks @BlueBlock
+* Updated to .Net Framework 4.6.2
+* Fixed issue with temporary files not being deleted as expected, thanks @BlueBlock
+* Support for forcing calendar dates in time pickers, thanks @LacunaSoftware
+
+2019-09-02 - 2.0.4.25_canary_2019-09-02
+==========
+== This is a rebuild of 2.0.4.24 with MSI packages and assembly redirect fixes ==
+
+Change list from 2.0.4.24:
+* Code cleanup, thanks @warwickmm
+* Removed extra console output, thanks @wjansenw
+* Fixed disposing backends after job completion, thanks @warwickmm
+* Fixed an issue with throttled write, thanks @warwickmm
+* Spelling fix, thanks @BlueBlock
+* Fixed documetation in `run-script` examples, thanks @beppo-dd
+* Improved unittests, thanks @BlueBlock
+* Improved auto-compact and auto-vacuum, thanks @drwtsn32x
+* Fixed problem with exceeeding the number of parameters supported by SQLite, thanks @drwtsn32x
+* Improved status display, thanks @drwtsn32x
+* Improved bugreport database scrubbing, thanks @drwtsn32x
+* Removed GoogleDrive trash items in listing, thanks @BlueBlock
+* Fixed the rename method in the GoogleDrive backend, thanks @BlueBlock
+* Improved GCS storage class text, thanks @warwickmm
+* Improved unittests for easier local testing, thanks @warwickmm
+* Added workaround for AFTP upload delay, thanks @BlueBlock
+* Fixed issue with reading the largest path prefix, thanks @BlueBlock
+* Added conditional download of unittest data zip files, thanks @BlueBlock
+* CI testing improvements, thanks @BlueBlock
+* Fixed sporadic issue with backups of files being written, thanks @BlueBlock
+* Updated to .Net Framework 4.6.2
+* Fixed issue with temporary files not being deleted as expected, thanks @BlueBlock
+* Support for forcing calendar dates in time pickers, thanks @LacunaSoftware
+
+2019-09-02 - 2.0.4.24_canary_2019-09-02
+==========
+* Code cleanup, thanks @warwickmm
+* Removed extra console output, thanks @wjansenw
+* Fixed disposing backends after job completion, thanks @warwickmm
+* Fixed an issue with throttled write, thanks @warwickmm
+* Spelling fix, thanks @BlueBlock
+* Fixed documetation in `run-script` examples, thanks @beppo-dd
+* Improved unittests, thanks @BlueBlock
+* Improved auto-compact and auto-vacuum, thanks @drwtsn32x
+* Fixed problem with exceeeding the number of parameters supported by SQLite, thanks @drwtsn32x
+* Improved status display, thanks @drwtsn32x
+* Improved bugreport database scrubbing, thanks @drwtsn32x
+* Removed GoogleDrive trash items in listing, thanks @BlueBlock
+* Fixed the rename method in the GoogleDrive backend, thanks @BlueBlock
+* Improved GCS storage class text, thanks @warwickmm
+* Improved unittests for easier local testing, thanks @warwickmm
+* Added workaround for AFTP upload delay, thanks @BlueBlock
+* Fixed issue with reading the largest path prefix, thanks @BlueBlock
+* Added conditional download of unittest data zip files, thanks @BlueBlock
+* CI testing improvements, thanks @BlueBlock
+* Fixed sporadic issue with backups of files being written, thanks @BlueBlock
+* Updated to .Net Framework 4.6.2
+* Fixed issue with temporary files not being deleted as expected, thanks @BlueBlock
+* Support for forcing calendar dates in time pickers, thanks @LacunaSoftware
+
2019-07-14 - 2.0.4.23_beta_2019-07-14
==========
This update only contains warnings to inform users on Amazon Cloud Drive that the service is discontinued.
diff --git a/thirdparty/SQLite/win32/SQLite.Interop.dll b/thirdparty/SQLite/win32/SQLite.Interop.dll
index 584e03963..9df592365 100755
Binary files a/thirdparty/SQLite/win32/SQLite.Interop.dll and b/thirdparty/SQLite/win32/SQLite.Interop.dll differ
diff --git a/thirdparty/SQLite/win32/System.Data.SQLite.dll b/thirdparty/SQLite/win32/System.Data.SQLite.dll
index 8b8a9d021..68f62fdd1 100755
Binary files a/thirdparty/SQLite/win32/System.Data.SQLite.dll and b/thirdparty/SQLite/win32/System.Data.SQLite.dll differ
diff --git a/thirdparty/SQLite/win64/SQLite.Interop.dll b/thirdparty/SQLite/win64/SQLite.Interop.dll
index b42c58f65..ccea49ef8 100755
Binary files a/thirdparty/SQLite/win64/SQLite.Interop.dll and b/thirdparty/SQLite/win64/SQLite.Interop.dll differ
diff --git a/thirdparty/SQLite/win64/System.Data.SQLite.dll b/thirdparty/SQLite/win64/System.Data.SQLite.dll
index 8b8a9d021..68f62fdd1 100755
Binary files a/thirdparty/SQLite/win64/System.Data.SQLite.dll and b/thirdparty/SQLite/win64/System.Data.SQLite.dll differ
diff --git a/thirdparty/SharpAESCrypt/SharpAESCrypt.exe b/thirdparty/SharpAESCrypt/SharpAESCrypt.exe
new file mode 100644
index 000000000..4ee0a6403
Binary files /dev/null and b/thirdparty/SharpAESCrypt/SharpAESCrypt.exe differ
diff --git a/thirdparty/TlsTest/TlsTest.csproj b/thirdparty/TlsTest/TlsTest.csproj
index 7ef228c3b..10c6f75cf 100644
--- a/thirdparty/TlsTest/TlsTest.csproj
+++ b/thirdparty/TlsTest/TlsTest.csproj
@@ -1,14 +1,15 @@
-
-
+
+
Debug
AnyCPU
{95B35AA3-7F86-43F1-9794-0CA115CFDF32}
Exe
- False
+ False
TlsTest
TlsTest
- v4.5
+ v4.6.2
+
true
@@ -29,5 +30,8 @@
+
+
+
\ No newline at end of file
diff --git a/thirdparty/TlsTest/app.config b/thirdparty/TlsTest/app.config
new file mode 100644
index 000000000..2a0024f75
--- /dev/null
+++ b/thirdparty/TlsTest/app.config
@@ -0,0 +1,3 @@
+
+
+
diff --git a/thirdparty/UnixSupport/UnixSupport.csproj b/thirdparty/UnixSupport/UnixSupport.csproj
index 5400fb0a8..1e6aaac1d 100644
--- a/thirdparty/UnixSupport/UnixSupport.csproj
+++ b/thirdparty/UnixSupport/UnixSupport.csproj
@@ -1,5 +1,5 @@
-
-
+
+
Debug
AnyCPU
@@ -9,10 +9,11 @@
Library
UnixSupport
UnixSupport
- v4.5
+ v4.6.2
Duplicati.snk
1.0
false
+
true
@@ -39,4 +40,8 @@
+
+
+
+
\ No newline at end of file
diff --git a/thirdparty/mozroots/app.config b/thirdparty/mozroots/app.config
new file mode 100644
index 000000000..2a0024f75
--- /dev/null
+++ b/thirdparty/mozroots/app.config
@@ -0,0 +1,3 @@
+
+
+
diff --git a/thirdparty/mozroots/mozroots.csproj b/thirdparty/mozroots/mozroots.csproj
index a681b630e..125aa4b6f 100644
--- a/thirdparty/mozroots/mozroots.csproj
+++ b/thirdparty/mozroots/mozroots.csproj
@@ -1,14 +1,15 @@
-
-
+
+
Debug
AnyCPU
{C44F0C79-B4E2-4D41-B357-1FD7B8888E78}
Exe
- False
+ False
mozroots
mozroots
- v4.5
+ v4.6.2
+
true
@@ -29,5 +30,8 @@
+
+
+
\ No newline at end of file