From 53b4cf05fbec1759e64b00317fe988f75992f8cb Mon Sep 17 00:00:00 2001 From: snsmac Date: Mon, 10 Apr 2023 19:54:50 +0200 Subject: [PATCH] Ensure that cli options specified with action=Highlander can only be set once, even if the set value is a default value. Add tests for action=Highlander. See #7500 #6269 --- src/borg/archiver/_common.py | 7 ++++++- src/borg/testsuite/archiver/argparsing.py | 17 +++++++++++++++++ 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/src/borg/archiver/_common.py b/src/borg/archiver/_common.py index 00729e221..38226e828 100644 --- a/src/borg/archiver/_common.py +++ b/src/borg/archiver/_common.py @@ -249,9 +249,14 @@ def with_archive(method): class Highlander(argparse.Action): """make sure some option is only given once""" + def __init__(self, *args, **kwargs): + self.__called = False + super().__init__(*args, **kwargs) + def __call__(self, parser, namespace, values, option_string=None): - if getattr(namespace, self.dest, None) != self.default: + if self.__called: raise argparse.ArgumentError(self, "There can be only one.") + self.__called = True setattr(namespace, self.dest, values) diff --git a/src/borg/testsuite/archiver/argparsing.py b/src/borg/testsuite/archiver/argparsing.py index 14859237c..1ce41122e 100644 --- a/src/borg/testsuite/archiver/argparsing.py +++ b/src/borg/testsuite/archiver/argparsing.py @@ -11,6 +11,23 @@ class ArchiverTestCase(ArchiverTestCaseBase): self.cmd(f"--repo={self.repository_location}", "create", "test", "input") self.cmd(f"--repo={self.repository_location}", "delete", "--first", "1", "--last", "1", fork=True, exit_code=2) + def test_highlander(self): + self.cmd(f"--repo={self.repository_location}", "rcreate", RK_ENCRYPTION) + self.cmd(f"--repo={self.repository_location}", "create", "--comment", "comment 1", "test-1", __file__) + error_msg = "There can be only one" + # Default umask value is 0077 + # Test that it works with a one time specified default or custom value + output_default = self.cmd(f"--repo={self.repository_location}", "--umask", "0077", "rlist") + assert error_msg not in output_default + output_custom = self.cmd(f"--repo={self.repository_location}", "--umask", "0007", "rlist") + assert error_msg not in output_custom + # Test that all combinations of custom and default values fail + for first, second in [("0007", "0007"), ("0007", "0077"), ("0077", "0007"), ("0077", "0077")]: + output_custom = self.cmd( + f"--repo={self.repository_location}", "--umask", first, "--umask", second, "rlist", exit_code=2 + ) + assert error_msg in output_custom + def test_get_args(): archiver = Archiver()