From 2df0710d7eceacf2d483cdd00b126b0313b8ec33 Mon Sep 17 00:00:00 2001 From: Carl Johnsen Date: Tue, 28 Jan 2025 09:48:51 +0100 Subject: [PATCH] Added the capability to forward multiple tokens to an option --- Duplicati/UnitTest/ToolTests.cs | 7 ++++++- Tools/RemoteSynchronization/Program.cs | 27 ++++++++++++++++++++++++-- 2 files changed, 31 insertions(+), 3 deletions(-) diff --git a/Duplicati/UnitTest/ToolTests.cs b/Duplicati/UnitTest/ToolTests.cs index 6268e284f..b187bdfb9 100644 --- a/Duplicati/UnitTest/ToolTests.cs +++ b/Duplicati/UnitTest/ToolTests.cs @@ -70,7 +70,12 @@ namespace Duplicati.UnitTest // Call the tool var exe = RemoteSynchronization.Program.Main; - var args = new string[] { $"file://{l1}", $"file://{l2}" }; + var args = new string[] { + $"file://{l1}", $"file://{l2}", + // Pass along multi token options to test that the parser won't fail + "--src-options", "ssh-accept-any-fingerprints=true", "ssh-keyfile=/path/to/keyfile", + "--dst-options", "some-other-key=value", "another-key=value2" + }; var async_call = exe(args); async_call.Wait(); Assert.AreEqual(0, async_call.Result, "Remote synchronization tool did not return 0."); diff --git a/Tools/RemoteSynchronization/Program.cs b/Tools/RemoteSynchronization/Program.cs index 471d2fac7..5766ecad1 100644 --- a/Tools/RemoteSynchronization/Program.cs +++ b/Tools/RemoteSynchronization/Program.cs @@ -40,11 +40,15 @@ namespace RemoteSynchronization var src_arg = new Argument(name: "backend_src", description: "The source backend string"); var dst_arg = new Argument(name: "backend_dst", description: "The destination backend string"); var dry_run_opt = new Option(aliases: ["--dry-run", "-d"], description: "Do not actually write or delete files"); + var src_opts = OptionWithMultipleTokens(aliases: ["--src-options"], description: "Options for the source backend"); + var dst_opts = OptionWithMultipleTokens(aliases: ["--dst-options"], description: "Options for the destination backend"); var root_cmd = new RootCommand("Remote Synchronization Tool"); root_cmd.AddArgument(src_arg); root_cmd.AddArgument(dst_arg); root_cmd.AddOption(dry_run_opt); + root_cmd.AddOption(src_opts); + root_cmd.AddOption(dst_opts); root_cmd.SetHandler((InvocationContext ctx) => { @@ -65,12 +69,22 @@ namespace RemoteSynchronization { ["dry-run"] = dry_run.ToString() }; + Dictionary src_opts = (options["src-options"] as List) + ?.Select(x => x.Split("=")) + .ToDictionary(x => x[0], x => x[1]) + ?? []; + Dictionary dst_opts = (options["dst-options"] as List) + ?.Select(x => x.Split("=")) + .ToDictionary(x => x[0], x => x[1]) + ?? []; + foreach (var x in duplicati_options) + src_opts[x.Key] = dst_opts[x.Key] = x.Value; - using var b1 = Duplicati.Library.DynamicLoader.BackendLoader.GetBackend(src, duplicati_options); + using var b1 = Duplicati.Library.DynamicLoader.BackendLoader.GetBackend(src, src_opts); var b1s = b1 as IStreamingBackend; System.Diagnostics.Debug.Assert(b1s != null); - using var b2 = Duplicati.Library.DynamicLoader.BackendLoader.GetBackend(dst, duplicati_options); + using var b2 = Duplicati.Library.DynamicLoader.BackendLoader.GetBackend(dst, dst_opts); var b2s = b2 as IStreamingBackend; System.Diagnostics.Debug.Assert(b2s != null); @@ -148,6 +162,15 @@ namespace RemoteSynchronization return successful_deletes; } + private static Option> OptionWithMultipleTokens(string[] aliases, string description) + { + return new Option>(aliases: aliases, description: description) + { + Arity = ArgumentArity.OneOrMore, + AllowMultipleArgumentsPerToken = true + }; + } + private static (IEnumerable, IEnumerable) PrepareFileLists(IStreamingBackend b_src, IStreamingBackend b_dst) { var files_src = b_src.List();