diff --git a/Duplicati/Tools/Duplicati.Tools.csproj b/Duplicati/Tools/Duplicati.Tools.csproj
index ecb48b4cc..28ca8eea6 100644
--- a/Duplicati/Tools/Duplicati.Tools.csproj
+++ b/Duplicati/Tools/Duplicati.Tools.csproj
@@ -5,7 +5,7 @@
Library
Copyright © 2024 Team Duplicati, MIT license
-
+
utility-scripts\DuplicatiVerify.ps1
@@ -24,12 +24,15 @@
utility-scripts\pause-resume.py
-
+
+
+
+
all
runtime; build; native; contentfiles; analyzers; buildtransitive
-
+
diff --git a/Duplicati/UnitTest/ToolTests.cs b/Duplicati/UnitTest/ToolTests.cs
new file mode 100644
index 000000000..a1e48084c
--- /dev/null
+++ b/Duplicati/UnitTest/ToolTests.cs
@@ -0,0 +1,65 @@
+using Duplicati.Library.Common.IO;
+using Duplicati.Library.Main;
+using NUnit.Framework;
+using System;
+using System.Collections.Generic;
+using System.IO;
+
+namespace Duplicati.UnitTest
+{
+
+ public class ToolTests : BasicSetupHelper
+ {
+
+ [Test]
+ [Category("Tools")]
+ public void TestRemoteSynchronization()
+ {
+ var home = Environment.GetEnvironmentVariable("HOME");
+ var base_path = $"{home}/git/duplicati-carl/rsync";
+ var l1 = $"{base_path}/l1";
+ var l2 = $"{base_path}/l2";
+ var l1r = $"{base_path}/l1_restore";
+ var l2r = $"{base_path}/l2_restore";
+ var backup_path = $"{home}/tmp/adaptivecpp";
+
+ Dictionary options = new ()
+ {
+ ["passphrase"] = "1234"
+ };
+
+ // Create the directories if they do not exist
+ foreach (var p in new string[] { base_path, l1, l2, l1r, l2r })
+ {
+ if (!SystemIO.IO_OS.DirectoryExists(p))
+ SystemIO.IO_OS.DirectoryCreate(p);
+ }
+
+ // Backup the first level
+ using (var c = new Controller($"file://{l1}", options, null))
+ {
+ var results = c.Backup([backup_path]);
+ Console.WriteLine($"Backed up {results.AddedFiles} files to {l1}");
+ }
+
+ // TODO Call the remote synchronization tool
+ var exe = RemoteSynchronization.Program.Main;
+
+ options["restore-path"] = l1r;
+ using (var c = new Controller($"file://{l1}", options, null))
+ {
+ var results = c.Restore([Path.Combine(backup_path, "*")]);
+ Console.WriteLine($"Restored {results.RestoredFiles} files to {options["restore-path"]}");
+ }
+
+ // Try to restore the second level
+ options["restore-path"] = l2r;
+ using (var c = new Controller($"file://{l2}", options, null))
+ {
+ var results = c.Restore([]);
+ Console.WriteLine($"Restored {results.RestoredFiles} files to {options["restore-path"]}");
+ }
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/Tools/RemoteSynchronization/Program.cs b/Tools/RemoteSynchronization/Program.cs
index c96642a76..6ef22f714 100644
--- a/Tools/RemoteSynchronization/Program.cs
+++ b/Tools/RemoteSynchronization/Program.cs
@@ -19,7 +19,6 @@
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
-using Duplicati.Library.Main;
using Duplicati.Library.Common.IO;
using Duplicati.Library.Interface;
using System;
@@ -31,40 +30,12 @@ using System.Threading;
namespace RemoteSynchronization
{
- class Program
+ public class Program
{
- static void Main(string[] args)
+ public static void Main(string[] args)
{
- // TODO testing start
- var home = Environment.GetEnvironmentVariable("HOME");
- var base_path = $"{home}/git/duplicati-carl/rsync";
- var l1 = $"{base_path}/l1";
- var l2 = $"{base_path}/l2";
- var l1r = $"{base_path}/l1_restore";
- var l2r = $"{base_path}/l2_restore";
- var backup_path = $"{home}/tmp/adaptivecpp";
- Dictionary options = new (){
- ["passphrase"] = "1234"
- };
- // Create the directories if they do not exist
- foreach (var p in new string[] { base_path, l1, l2, l1r, l2r })
- {
- if (!SystemIO.IO_OS.DirectoryExists(p))
- SystemIO.IO_OS.DirectoryCreate(p);
- }
-
- // Backup the first level
- using (var c = new Controller($"file://{l1}", options, null))
- {
- var results = c.Backup([backup_path]);
- Console.WriteLine($"Backed up {results.AddedFiles} files to {l1}");
- }
-
- // TODO testing end
-
- // Sync the first level to the second level
using (var b1 = Duplicati.Library.DynamicLoader.BackendLoader.GetBackend($"file://{l1}", options))
{
var b1s = b1 as IStreamingBackend;
@@ -80,29 +51,8 @@ namespace RemoteSynchronization
Console.WriteLine($"Copied {copied} files from {l1} to {l2}");
}
}
-
- // TODO testing start
- // Try to restore the first level
- options["restore-path"] = l1r;
- using (var c = new Controller($"file://{l1}", options, null))
- {
- var results = c.Restore([Path.Combine(backup_path, "*")]);
- Console.WriteLine($"Restored {results.RestoredFiles} files to {options["restore-path"]}");
- }
-
- // Try to restore the second level
- options["restore-path"] = l2r;
- using (var c = new Controller($"file://{l2}", options, null))
- {
- var results = c.Restore([]);
- Console.WriteLine($"Restored {results.RestoredFiles} files to {options["restore-path"]}");
- }
- // TODO testing end
}
- // TODO check whether a backend is empty
- // TODO check whether the backend files are consistent: src.files.count >= dst.files.count
- // TODO handle files deleted from src, which should also be deleted in dst
// TODO maximum retention?: don't delete files, only rename old ones.
// TODO have concurrency parameters: uploaders, downloaders
// TODO low memory mode, where things aren't kept in memory. Maybe utilize SQLite?