Browse Source

Merge pull request #7499 from ThomasWaldmann/more-highlander

more Highlander options, fixes #6269
TW 2 năm trước cách đây
mục cha
commit
cf55dd0ebd

+ 10 - 1
src/borg/archiver/__init__.py

@@ -21,6 +21,7 @@ try:
 
 
     logger = create_logger()
     logger = create_logger()
 
 
+    from ._common import Highlander
     from .. import __version__
     from .. import __version__
     from ..constants import *  # NOQA
     from ..constants import *  # NOQA
     from ..helpers import EXIT_SUCCESS, EXIT_WARNING, EXIT_ERROR, EXIT_SIGNAL_BASE
     from ..helpers import EXIT_SUCCESS, EXIT_WARNING, EXIT_ERROR, EXIT_SIGNAL_BASE
@@ -219,7 +220,15 @@ class Archiver(
             def add_argument(*args, **kwargs):
             def add_argument(*args, **kwargs):
                 if "dest" in kwargs:
                 if "dest" in kwargs:
                     kwargs.setdefault("action", "store")
                     kwargs.setdefault("action", "store")
-                    assert kwargs["action"] in ("help", "store_const", "store_true", "store_false", "store", "append")
+                    assert kwargs["action"] in (
+                        Highlander,
+                        "help",
+                        "store_const",
+                        "store_true",
+                        "store_false",
+                        "store",
+                        "append",
+                    )
                     is_append = kwargs["action"] == "append"
                     is_append = kwargs["action"] == "append"
                     if is_append:
                     if is_append:
                         self.append_options.add(kwargs["dest"])
                         self.append_options.add(kwargs["dest"])

+ 22 - 6
src/borg/archiver/_common.py

@@ -339,6 +339,7 @@ def define_exclude_and_patterns(add_option, *, tag_files=False, strip_components
             dest="strip_components",
             dest="strip_components",
             type=int,
             type=int,
             default=0,
             default=0,
+            action=Highlander,
             help="Remove the specified number of leading path elements. "
             help="Remove the specified number of leading path elements. "
             "Paths with fewer elements will be silently skipped.",
             "Paths with fewer elements will be silently skipped.",
         )
         )
@@ -372,6 +373,7 @@ def define_archive_filters_group(subparser, *, sort_by=True, first_last=True, ol
             dest="sort_by",
             dest="sort_by",
             type=SortBySpec,
             type=SortBySpec,
             default=sort_by_default,
             default=sort_by_default,
+            action=Highlander,
             help="Comma-separated list of sorting keys; valid keys are: {}; default is: {}".format(
             help="Comma-separated list of sorting keys; valid keys are: {}; default is: {}".format(
                 ", ".join(AI_HUMAN_SORT_KEYS), sort_by_default
                 ", ".join(AI_HUMAN_SORT_KEYS), sort_by_default
             ),
             ),
@@ -383,16 +385,18 @@ def define_archive_filters_group(subparser, *, sort_by=True, first_last=True, ol
             "--first",
             "--first",
             metavar="N",
             metavar="N",
             dest="first",
             dest="first",
-            default=0,
             type=positive_int_validator,
             type=positive_int_validator,
+            default=0,
+            action=Highlander,
             help="consider first N archives after other filters were applied",
             help="consider first N archives after other filters were applied",
         )
         )
         group.add_argument(
         group.add_argument(
             "--last",
             "--last",
             metavar="N",
             metavar="N",
             dest="last",
             dest="last",
-            default=0,
             type=positive_int_validator,
             type=positive_int_validator,
+            default=0,
+            action=Highlander,
             help="consider last N archives after other filters were applied",
             help="consider last N archives after other filters were applied",
         )
         )
 
 
@@ -401,15 +405,17 @@ def define_archive_filters_group(subparser, *, sort_by=True, first_last=True, ol
         group.add_argument(
         group.add_argument(
             "--oldest",
             "--oldest",
             metavar="TIMESPAN",
             metavar="TIMESPAN",
-            type=relative_time_marker_validator,
             dest="oldest",
             dest="oldest",
+            type=relative_time_marker_validator,
+            action=Highlander,
             help="consider archives between the oldest archive's timestamp and (oldest + TIMESPAN), e.g. 7d or 12m.",
             help="consider archives between the oldest archive's timestamp and (oldest + TIMESPAN), e.g. 7d or 12m.",
         )
         )
         group.add_argument(
         group.add_argument(
             "--newest",
             "--newest",
             metavar="TIMESPAN",
             metavar="TIMESPAN",
-            type=relative_time_marker_validator,
             dest="newest",
             dest="newest",
+            type=relative_time_marker_validator,
+            action=Highlander,
             help="consider archives between the newest archive's timestamp and (newest - TIMESPAN), e.g. 7d or 12m.",
             help="consider archives between the newest archive's timestamp and (newest - TIMESPAN), e.g. 7d or 12m.",
         )
         )
 
 
@@ -418,15 +424,17 @@ def define_archive_filters_group(subparser, *, sort_by=True, first_last=True, ol
         group.add_argument(
         group.add_argument(
             "--older",
             "--older",
             metavar="TIMESPAN",
             metavar="TIMESPAN",
-            type=relative_time_marker_validator,
             dest="older",
             dest="older",
+            type=relative_time_marker_validator,
+            action=Highlander,
             help="consider archives older than (now - TIMESPAN), e.g. 7d oder 12m.",
             help="consider archives older than (now - TIMESPAN), e.g. 7d oder 12m.",
         )
         )
         group.add_argument(
         group.add_argument(
             "--newer",
             "--newer",
             metavar="TIMESPAN",
             metavar="TIMESPAN",
-            type=relative_time_marker_validator,
             dest="newer",
             dest="newer",
+            type=relative_time_marker_validator,
+            action=Highlander,
             help="consider archives newer than (now - TIMESPAN), e.g. 7d or 12m.",
             help="consider archives newer than (now - TIMESPAN), e.g. 7d or 12m.",
         )
         )
 
 
@@ -500,6 +508,7 @@ def define_common_options(add_common_option):
         dest="lock_wait",
         dest="lock_wait",
         type=int,
         type=int,
         default=int(os.environ.get("BORG_LOCK_WAIT", 1)),
         default=int(os.environ.get("BORG_LOCK_WAIT", 1)),
+        action=Highlander,
         help="wait at most SECONDS for acquiring a repository/cache lock (default: %(default)d).",
         help="wait at most SECONDS for acquiring a repository/cache lock (default: %(default)d).",
     )
     )
     add_common_option(
     add_common_option(
@@ -517,12 +526,14 @@ def define_common_options(add_common_option):
         dest="umask",
         dest="umask",
         type=lambda s: int(s, 8),
         type=lambda s: int(s, 8),
         default=UMASK_DEFAULT,
         default=UMASK_DEFAULT,
+        action=Highlander,
         help="set umask to M (local only, default: %(default)04o)",
         help="set umask to M (local only, default: %(default)04o)",
     )
     )
     add_common_option(
     add_common_option(
         "--remote-path",
         "--remote-path",
         metavar="PATH",
         metavar="PATH",
         dest="remote_path",
         dest="remote_path",
+        action=Highlander,
         help='use PATH as borg executable on the remote (default: "borg")',
         help='use PATH as borg executable on the remote (default: "borg")',
     )
     )
     add_common_option(
     add_common_option(
@@ -530,6 +541,7 @@ def define_common_options(add_common_option):
         metavar="RATE",
         metavar="RATE",
         dest="upload_ratelimit",
         dest="upload_ratelimit",
         type=int,
         type=int,
+        action=Highlander,
         help="set network upload rate limit in kiByte/s (default: 0=unlimited)",
         help="set network upload rate limit in kiByte/s (default: 0=unlimited)",
     )
     )
     add_common_option(
     add_common_option(
@@ -537,6 +549,7 @@ def define_common_options(add_common_option):
         metavar="UPLOAD_BUFFER",
         metavar="UPLOAD_BUFFER",
         dest="upload_buffer",
         dest="upload_buffer",
         type=int,
         type=int,
+        action=Highlander,
         help="set network upload buffer size in MiB. (default: 0=no buffer)",
         help="set network upload buffer size in MiB. (default: 0=no buffer)",
     )
     )
     add_common_option(
     add_common_option(
@@ -544,6 +557,7 @@ def define_common_options(add_common_option):
         metavar="FILE",
         metavar="FILE",
         dest="debug_profile",
         dest="debug_profile",
         default=None,
         default=None,
+        action=Highlander,
         help="Write execution profile in Borg format into FILE. For local use a Python-"
         help="Write execution profile in Borg format into FILE. For local use a Python-"
         'compatible file can be generated by suffixing FILE with ".pyprof".',
         'compatible file can be generated by suffixing FILE with ".pyprof".',
     )
     )
@@ -551,6 +565,7 @@ def define_common_options(add_common_option):
         "--rsh",
         "--rsh",
         metavar="RSH",
         metavar="RSH",
         dest="rsh",
         dest="rsh",
+        action=Highlander,
         help="Use this command to connect to the 'borg serve' process (default: 'ssh')",
         help="Use this command to connect to the 'borg serve' process (default: 'ssh')",
     )
     )
     add_common_option(
     add_common_option(
@@ -560,6 +575,7 @@ def define_common_options(add_common_option):
         dest="location",
         dest="location",
         type=location_validator(other=False),
         type=location_validator(other=False),
         default=Location(other=False),
         default=Location(other=False),
+        action=Highlander,
         help="repository to use",
         help="repository to use",
     )
     )
 
 

+ 2 - 1
src/borg/archiver/check_cmd.py

@@ -1,5 +1,5 @@
 import argparse
 import argparse
-from ._common import with_repository
+from ._common import with_repository, Highlander
 from ..archive import ArchiveChecker
 from ..archive import ArchiveChecker
 from ..constants import *  # NOQA
 from ..constants import *  # NOQA
 from ..helpers import EXIT_SUCCESS, EXIT_WARNING, EXIT_ERROR
 from ..helpers import EXIT_SUCCESS, EXIT_WARNING, EXIT_ERROR
@@ -176,6 +176,7 @@ class CheckMixIn:
             dest="max_duration",
             dest="max_duration",
             type=int,
             type=int,
             default=0,
             default=0,
+            action=Highlander,
             help="do only a partial repo check for max. SECONDS seconds (Default: unlimited)",
             help="do only a partial repo check for max. SECONDS seconds (Default: unlimited)",
         )
         )
         define_archive_filters_group(subparser)
         define_archive_filters_group(subparser)

+ 2 - 1
src/borg/archiver/compact_cmd.py

@@ -1,6 +1,6 @@
 import argparse
 import argparse
 
 
-from ._common import with_repository
+from ._common import with_repository, Highlander
 from ..constants import *  # NOQA
 from ..constants import *  # NOQA
 from ..helpers import EXIT_SUCCESS
 from ..helpers import EXIT_SUCCESS
 from ..manifest import Manifest
 from ..manifest import Manifest
@@ -61,5 +61,6 @@ class CompactMixIn:
             dest="threshold",
             dest="threshold",
             type=int,
             type=int,
             default=10,
             default=10,
+            action=Highlander,
             help="set minimum threshold for saved space in PERCENT (Default: 10)",
             help="set minimum threshold for saved space in PERCENT (Default: 10)",
         )
         )

+ 10 - 0
src/borg/archiver/create_cmd.py

@@ -763,6 +763,7 @@ class CreateMixIn:
             metavar="NAME",
             metavar="NAME",
             dest="stdin_name",
             dest="stdin_name",
             default="stdin",
             default="stdin",
+            action=Highlander,
             help="use NAME in archive for stdin data (default: %(default)r)",
             help="use NAME in archive for stdin data (default: %(default)r)",
         )
         )
         subparser.add_argument(
         subparser.add_argument(
@@ -770,6 +771,7 @@ class CreateMixIn:
             metavar="USER",
             metavar="USER",
             dest="stdin_user",
             dest="stdin_user",
             default=None,
             default=None,
+            action=Highlander,
             help="set user USER in archive for stdin data (default: do not store user/uid)",
             help="set user USER in archive for stdin data (default: do not store user/uid)",
         )
         )
         subparser.add_argument(
         subparser.add_argument(
@@ -777,6 +779,7 @@ class CreateMixIn:
             metavar="GROUP",
             metavar="GROUP",
             dest="stdin_group",
             dest="stdin_group",
             default=None,
             default=None,
+            action=Highlander,
             help="set group GROUP in archive for stdin data (default: do not store group/gid)",
             help="set group GROUP in archive for stdin data (default: do not store group/gid)",
         )
         )
         subparser.add_argument(
         subparser.add_argument(
@@ -785,6 +788,7 @@ class CreateMixIn:
             dest="stdin_mode",
             dest="stdin_mode",
             type=lambda s: int(s, 8),
             type=lambda s: int(s, 8),
             default=STDIN_MODE_DEFAULT,
             default=STDIN_MODE_DEFAULT,
+            action=Highlander,
             help="set mode to M in archive for stdin data (default: %(default)04o)",
             help="set mode to M in archive for stdin data (default: %(default)04o)",
         )
         )
         subparser.add_argument(
         subparser.add_argument(
@@ -804,6 +808,7 @@ class CreateMixIn:
         )
         )
         subparser.add_argument(
         subparser.add_argument(
             "--paths-delimiter",
             "--paths-delimiter",
+            action=Highlander,
             metavar="DELIM",
             metavar="DELIM",
             help="set path delimiter for ``--paths-from-stdin`` and ``--paths-from-command`` (default: \\n) ",
             help="set path delimiter for ``--paths-from-stdin`` and ``--paths-from-command`` (default: \\n) ",
         )
         )
@@ -878,6 +883,7 @@ class CreateMixIn:
             dest="comment",
             dest="comment",
             type=comment_validator,
             type=comment_validator,
             default="",
             default="",
+            action=Highlander,
             help="add a comment text to the archive",
             help="add a comment text to the archive",
         )
         )
         archive_group.add_argument(
         archive_group.add_argument(
@@ -886,6 +892,7 @@ class CreateMixIn:
             dest="timestamp",
             dest="timestamp",
             type=timestamp,
             type=timestamp,
             default=None,
             default=None,
+            action=Highlander,
             help="manually specify the archive creation date/time (yyyy-mm-ddThh:mm:ss[(+|-)HH:MM] format, "
             help="manually specify the archive creation date/time (yyyy-mm-ddThh:mm:ss[(+|-)HH:MM] format, "
             "(+|-)HH:MM is the UTC offset, default: local time zone). Alternatively, give a reference file/directory.",
             "(+|-)HH:MM is the UTC offset, default: local time zone). Alternatively, give a reference file/directory.",
         )
         )
@@ -896,6 +903,7 @@ class CreateMixIn:
             dest="checkpoint_interval",
             dest="checkpoint_interval",
             type=int,
             type=int,
             default=1800,
             default=1800,
+            action=Highlander,
             help="write checkpoint every SECONDS seconds (Default: 1800)",
             help="write checkpoint every SECONDS seconds (Default: 1800)",
         )
         )
         archive_group.add_argument(
         archive_group.add_argument(
@@ -904,6 +912,7 @@ class CreateMixIn:
             dest="checkpoint_volume",
             dest="checkpoint_volume",
             type=int,
             type=int,
             default=0,
             default=0,
+            action=Highlander,
             help="write checkpoint every BYTES bytes (Default: 0, meaning no volume based checkpointing)",
             help="write checkpoint every BYTES bytes (Default: 0, meaning no volume based checkpointing)",
         )
         )
         archive_group.add_argument(
         archive_group.add_argument(
@@ -923,6 +932,7 @@ class CreateMixIn:
             dest="compression",
             dest="compression",
             type=CompressionSpec,
             type=CompressionSpec,
             default=CompressionSpec("lz4"),
             default=CompressionSpec("lz4"),
+            action=Highlander,
             help="select compression algorithm, see the output of the " '"borg help compression" command for details.',
             help="select compression algorithm, see the output of the " '"borg help compression" command for details.',
         )
         )
 
 

+ 7 - 3
src/borg/archiver/debug_cmd.py

@@ -18,7 +18,7 @@ from ..platform import get_process_id
 from ..repository import Repository, LIST_SCAN_LIMIT, TAG_PUT, TAG_DELETE, TAG_COMMIT
 from ..repository import Repository, LIST_SCAN_LIMIT, TAG_PUT, TAG_DELETE, TAG_COMMIT
 from ..repoobj import RepoObj
 from ..repoobj import RepoObj
 
 
-from ._common import with_repository
+from ._common import with_repository, Highlander
 from ._common import process_epilog
 from ._common import process_epilog
 
 
 
 
@@ -521,16 +521,18 @@ class DebugMixIn:
             "--segment",
             "--segment",
             metavar="SEG",
             metavar="SEG",
             dest="segment",
             dest="segment",
-            default=None,
             type=positive_int_validator,
             type=positive_int_validator,
+            default=None,
+            action=Highlander,
             help="used together with --ghost: limit processing to given segment.",
             help="used together with --ghost: limit processing to given segment.",
         )
         )
         subparser.add_argument(
         subparser.add_argument(
             "--offset",
             "--offset",
             metavar="OFFS",
             metavar="OFFS",
             dest="offset",
             dest="offset",
-            default=None,
             type=positive_int_validator,
             type=positive_int_validator,
+            default=None,
+            action=Highlander,
             help="used together with --ghost: limit processing to given offset.",
             help="used together with --ghost: limit processing to given offset.",
         )
         )
 
 
@@ -553,6 +555,7 @@ class DebugMixIn:
             "wanted",
             "wanted",
             metavar="WANTED",
             metavar="WANTED",
             type=str,
             type=str,
+            action=Highlander,
             help="term to search the repo for, either 0x1234abcd hex term or a string",
             help="term to search the repo for, either 0x1234abcd hex term or a string",
         )
         )
         debug_id_hash_epilog = process_epilog(
         debug_id_hash_epilog = process_epilog(
@@ -631,6 +634,7 @@ class DebugMixIn:
             dest="compression",
             dest="compression",
             type=CompressionSpec,
             type=CompressionSpec,
             default=CompressionSpec("lz4"),
             default=CompressionSpec("lz4"),
+            action=Highlander,
             help="select compression algorithm, see the output of the " '"borg help compression" command for details.',
             help="select compression algorithm, see the output of the " '"borg help compression" command for details.',
         )
         )
         subparser.add_argument(
         subparser.add_argument(

+ 2 - 1
src/borg/archiver/delete_cmd.py

@@ -1,7 +1,7 @@
 import argparse
 import argparse
 import logging
 import logging
 
 
-from ._common import with_repository
+from ._common import with_repository, Highlander
 from ..archive import Archive, Statistics
 from ..archive import Archive, Statistics
 from ..cache import Cache
 from ..cache import Cache
 from ..constants import *  # NOQA
 from ..constants import *  # NOQA
@@ -156,6 +156,7 @@ class DeleteMixIn:
             dest="checkpoint_interval",
             dest="checkpoint_interval",
             type=int,
             type=int,
             default=1800,
             default=1800,
+            action=Highlander,
             help="write checkpoint every SECONDS seconds (Default: 1800)",
             help="write checkpoint every SECONDS seconds (Default: 1800)",
         )
         )
         define_archive_filters_group(subparser)
         define_archive_filters_group(subparser)

+ 2 - 1
src/borg/archiver/list_cmd.py

@@ -2,7 +2,7 @@ import argparse
 import textwrap
 import textwrap
 import sys
 import sys
 
 
-from ._common import with_repository, build_matcher
+from ._common import with_repository, build_matcher, Highlander
 from ..archive import Archive
 from ..archive import Archive
 from ..cache import Cache
 from ..cache import Cache
 from ..constants import *  # NOQA
 from ..constants import *  # NOQA
@@ -105,6 +105,7 @@ class ListMixIn:
             "--format",
             "--format",
             metavar="FORMAT",
             metavar="FORMAT",
             dest="format",
             dest="format",
+            action=Highlander,
             help="specify format for file listing "
             help="specify format for file listing "
             '(default: "{mode} {user:6} {group:6} {size:8} {mtime} {path}{extra}{NL}")',
             '(default: "{mode} {user:6} {group:6} {size:8} {mtime} {path}{extra}{NL}")',
         )
         )

+ 45 - 7
src/borg/archiver/prune_cmd.py

@@ -5,7 +5,7 @@ import logging
 from operator import attrgetter
 from operator import attrgetter
 import re
 import re
 
 
-from ._common import with_repository
+from ._common import with_repository, Highlander
 from ..archive import Archive, Statistics
 from ..archive import Archive, Statistics
 from ..cache import Cache
 from ..cache import Cache
 from ..constants import *  # NOQA
 from ..constants import *  # NOQA
@@ -257,6 +257,7 @@ class PruneMixIn:
             metavar="INTERVAL",
             metavar="INTERVAL",
             dest="within",
             dest="within",
             type=interval,
             type=interval,
+            action=Highlander,
             help="keep all archives within this time interval",
             help="keep all archives within this time interval",
         )
         )
         subparser.add_argument(
         subparser.add_argument(
@@ -265,25 +266,61 @@ class PruneMixIn:
             dest="secondly",
             dest="secondly",
             type=int,
             type=int,
             default=0,
             default=0,
+            action=Highlander,
             help="number of secondly archives to keep",
             help="number of secondly archives to keep",
         )
         )
         subparser.add_argument(
         subparser.add_argument(
-            "--keep-minutely", dest="minutely", type=int, default=0, help="number of minutely archives to keep"
+            "--keep-minutely",
+            dest="minutely",
+            type=int,
+            default=0,
+            action=Highlander,
+            help="number of minutely archives to keep",
         )
         )
         subparser.add_argument(
         subparser.add_argument(
-            "-H", "--keep-hourly", dest="hourly", type=int, default=0, help="number of hourly archives to keep"
+            "-H",
+            "--keep-hourly",
+            dest="hourly",
+            type=int,
+            default=0,
+            action=Highlander,
+            help="number of hourly archives to keep",
         )
         )
         subparser.add_argument(
         subparser.add_argument(
-            "-d", "--keep-daily", dest="daily", type=int, default=0, help="number of daily archives to keep"
+            "-d",
+            "--keep-daily",
+            dest="daily",
+            type=int,
+            default=0,
+            action=Highlander,
+            help="number of daily archives to keep",
         )
         )
         subparser.add_argument(
         subparser.add_argument(
-            "-w", "--keep-weekly", dest="weekly", type=int, default=0, help="number of weekly archives to keep"
+            "-w",
+            "--keep-weekly",
+            dest="weekly",
+            type=int,
+            default=0,
+            action=Highlander,
+            help="number of weekly archives to keep",
         )
         )
         subparser.add_argument(
         subparser.add_argument(
-            "-m", "--keep-monthly", dest="monthly", type=int, default=0, help="number of monthly archives to keep"
+            "-m",
+            "--keep-monthly",
+            dest="monthly",
+            type=int,
+            default=0,
+            action=Highlander,
+            help="number of monthly archives to keep",
         )
         )
         subparser.add_argument(
         subparser.add_argument(
-            "-y", "--keep-yearly", dest="yearly", type=int, default=0, help="number of yearly archives to keep"
+            "-y",
+            "--keep-yearly",
+            dest="yearly",
+            type=int,
+            default=0,
+            action=Highlander,
+            help="number of yearly archives to keep",
         )
         )
         define_archive_filters_group(subparser, sort_by=False, first_last=False)
         define_archive_filters_group(subparser, sort_by=False, first_last=False)
         subparser.add_argument(
         subparser.add_argument(
@@ -293,5 +330,6 @@ class PruneMixIn:
             dest="checkpoint_interval",
             dest="checkpoint_interval",
             type=int,
             type=int,
             default=1800,
             default=1800,
+            action=Highlander,
             help="write checkpoint every SECONDS seconds (Default: 1800)",
             help="write checkpoint every SECONDS seconds (Default: 1800)",
         )
         )

+ 3 - 1
src/borg/archiver/rcompress_cmd.py

@@ -1,7 +1,7 @@
 import argparse
 import argparse
 from collections import defaultdict
 from collections import defaultdict
 
 
-from ._common import with_repository
+from ._common import with_repository, Highlander
 from ..constants import *  # NOQA
 from ..constants import *  # NOQA
 from ..compress import CompressionSpec, ObfuscateSize, Auto, COMPRESSOR_TABLE
 from ..compress import CompressionSpec, ObfuscateSize, Auto, COMPRESSOR_TABLE
 from ..helpers import sig_int, ProgressIndicatorPercent
 from ..helpers import sig_int, ProgressIndicatorPercent
@@ -230,6 +230,7 @@ class RCompressMixIn:
             dest="compression",
             dest="compression",
             type=CompressionSpec,
             type=CompressionSpec,
             default=CompressionSpec("lz4"),
             default=CompressionSpec("lz4"),
+            action=Highlander,
             help="select compression algorithm, see the output of the " '"borg help compression" command for details.',
             help="select compression algorithm, see the output of the " '"borg help compression" command for details.',
         )
         )
 
 
@@ -242,5 +243,6 @@ class RCompressMixIn:
             dest="checkpoint_interval",
             dest="checkpoint_interval",
             type=int,
             type=int,
             default=1800,
             default=1800,
+            action=Highlander,
             help="write checkpoint every SECONDS seconds (Default: 1800)",
             help="write checkpoint every SECONDS seconds (Default: 1800)",
         )
         )

+ 4 - 1
src/borg/archiver/rcreate_cmd.py

@@ -1,6 +1,6 @@
 import argparse
 import argparse
 
 
-from ._common import with_repository, with_other_repository
+from ._common import with_repository, with_other_repository, Highlander
 from ..cache import Cache
 from ..cache import Cache
 from ..constants import *  # NOQA
 from ..constants import *  # NOQA
 from ..crypto.key import key_creator, key_argument_names, tam_required_file
 from ..crypto.key import key_creator, key_argument_names, tam_required_file
@@ -184,6 +184,7 @@ class RCreateMixIn:
             dest="other_location",
             dest="other_location",
             type=location_validator(other=True),
             type=location_validator(other=True),
             default=Location(other=True),
             default=Location(other=True),
+            action=Highlander,
             help="reuse the key material from the other repository",
             help="reuse the key material from the other repository",
         )
         )
         subparser.add_argument(
         subparser.add_argument(
@@ -193,6 +194,7 @@ class RCreateMixIn:
             dest="encryption",
             dest="encryption",
             required=True,
             required=True,
             choices=key_argument_names(),
             choices=key_argument_names(),
+            action=Highlander,
             help="select encryption key mode **(required)**",
             help="select encryption key mode **(required)**",
         )
         )
         subparser.add_argument(
         subparser.add_argument(
@@ -210,6 +212,7 @@ class RCreateMixIn:
             dest="storage_quota",
             dest="storage_quota",
             default=None,
             default=None,
             type=parse_storage_quota,
             type=parse_storage_quota,
+            action=Highlander,
             help="Set storage quota of the new repository (e.g. 5G, 1.5T). Default: no quota.",
             help="Set storage quota of the new repository (e.g. 5G, 1.5T). Default: no quota.",
         )
         )
         subparser.add_argument(
         subparser.add_argument(

+ 8 - 1
src/borg/archiver/recreate_cmd.py

@@ -149,6 +149,7 @@ class RecreateMixIn:
             metavar="TARGET",
             metavar="TARGET",
             default=None,
             default=None,
             type=archivename_validator,
             type=archivename_validator,
+            action=Highlander,
             help="create a new archive with the name ARCHIVE, do not replace existing archive "
             help="create a new archive with the name ARCHIVE, do not replace existing archive "
             "(only applies for a single archive)",
             "(only applies for a single archive)",
         )
         )
@@ -158,6 +159,7 @@ class RecreateMixIn:
             dest="checkpoint_interval",
             dest="checkpoint_interval",
             type=int,
             type=int,
             default=1800,
             default=1800,
+            action=Highlander,
             metavar="SECONDS",
             metavar="SECONDS",
             help="write checkpoint every SECONDS seconds (Default: 1800)",
             help="write checkpoint every SECONDS seconds (Default: 1800)",
         )
         )
@@ -167,6 +169,7 @@ class RecreateMixIn:
             dest="checkpoint_volume",
             dest="checkpoint_volume",
             type=int,
             type=int,
             default=0,
             default=0,
+            action=Highlander,
             help="write checkpoint every BYTES bytes (Default: 0, meaning no volume based checkpointing)",
             help="write checkpoint every BYTES bytes (Default: 0, meaning no volume based checkpointing)",
         )
         )
         archive_group.add_argument(
         archive_group.add_argument(
@@ -175,6 +178,7 @@ class RecreateMixIn:
             dest="comment",
             dest="comment",
             type=comment_validator,
             type=comment_validator,
             default=None,
             default=None,
+            action=Highlander,
             help="add a comment text to the archive",
             help="add a comment text to the archive",
         )
         )
         archive_group.add_argument(
         archive_group.add_argument(
@@ -183,6 +187,7 @@ class RecreateMixIn:
             dest="timestamp",
             dest="timestamp",
             type=timestamp,
             type=timestamp,
             default=None,
             default=None,
+            action=Highlander,
             help="manually specify the archive creation date/time (yyyy-mm-ddThh:mm:ss[(+|-)HH:MM] format, "
             help="manually specify the archive creation date/time (yyyy-mm-ddThh:mm:ss[(+|-)HH:MM] format, "
             "(+|-)HH:MM is the UTC offset, default: local time zone). Alternatively, give a reference file/directory.",
             "(+|-)HH:MM is the UTC offset, default: local time zone). Alternatively, give a reference file/directory.",
         )
         )
@@ -193,6 +198,7 @@ class RecreateMixIn:
             dest="compression",
             dest="compression",
             type=CompressionSpec,
             type=CompressionSpec,
             default=CompressionSpec("lz4"),
             default=CompressionSpec("lz4"),
+            action=Highlander,
             help="select compression algorithm, see the output of the " '"borg help compression" command for details.',
             help="select compression algorithm, see the output of the " '"borg help compression" command for details.',
         )
         )
         archive_group.add_argument(
         archive_group.add_argument(
@@ -203,6 +209,7 @@ class RecreateMixIn:
             default="never",
             default="never",
             const="if-different",
             const="if-different",
             choices=("never", "if-different", "always"),
             choices=("never", "if-different", "always"),
+            action=Highlander,
             help="recompress data chunks according to `MODE` and ``--compression``. "
             help="recompress data chunks according to `MODE` and ``--compression``. "
             "Possible modes are "
             "Possible modes are "
             "`if-different`: recompress if current compression is with a different "
             "`if-different`: recompress if current compression is with a different "
@@ -217,9 +224,9 @@ class RecreateMixIn:
             "--chunker-params",
             "--chunker-params",
             metavar="PARAMS",
             metavar="PARAMS",
             dest="chunker_params",
             dest="chunker_params",
-            action=Highlander,
             type=ChunkerParams,
             type=ChunkerParams,
             default=None,
             default=None,
+            action=Highlander,
             help="rechunk using given chunker parameters (ALGO, CHUNK_MIN_EXP, CHUNK_MAX_EXP, "
             help="rechunk using given chunker parameters (ALGO, CHUNK_MIN_EXP, CHUNK_MAX_EXP, "
             "HASH_MASK_BITS, HASH_WINDOW_SIZE) or `default` to use the chunker defaults. "
             "HASH_MASK_BITS, HASH_WINDOW_SIZE) or `default` to use the chunker defaults. "
             "default: do not rechunk",
             "default: do not rechunk",

+ 2 - 1
src/borg/archiver/rlist_cmd.py

@@ -2,7 +2,7 @@ import argparse
 import textwrap
 import textwrap
 import sys
 import sys
 
 
-from ._common import with_repository
+from ._common import with_repository, Highlander
 from ..constants import *  # NOQA
 from ..constants import *  # NOQA
 from ..helpers import BaseFormatter, ArchiveFormatter, json_print, basic_json_data
 from ..helpers import BaseFormatter, ArchiveFormatter, json_print, basic_json_data
 from ..manifest import Manifest
 from ..manifest import Manifest
@@ -106,6 +106,7 @@ class RListMixIn:
             "--format",
             "--format",
             metavar="FORMAT",
             metavar="FORMAT",
             dest="format",
             dest="format",
+            action=Highlander,
             help="specify format for archive listing " '(default: "{archive:<36} {time} [{id}]{NL}")',
             help="specify format for archive listing " '(default: "{archive:<36} {time} [{id}]{NL}")',
         )
         )
         subparser.add_argument(
         subparser.add_argument(

+ 2 - 0
src/borg/archiver/serve_cmd.py

@@ -1,5 +1,6 @@
 import argparse
 import argparse
 
 
+from ._common import Highlander
 from ..constants import *  # NOQA
 from ..constants import *  # NOQA
 from ..helpers import EXIT_SUCCESS
 from ..helpers import EXIT_SUCCESS
 from ..helpers import parse_storage_quota
 from ..helpers import parse_storage_quota
@@ -76,6 +77,7 @@ class ServeMixIn:
             dest="storage_quota",
             dest="storage_quota",
             type=parse_storage_quota,
             type=parse_storage_quota,
             default=None,
             default=None,
+            action=Highlander,
             help="Override storage quota of the repository (e.g. 5G, 1.5T). "
             help="Override storage quota of the repository (e.g. 5G, 1.5T). "
             "When a new repository is initialized, sets the storage quota on the new "
             "When a new repository is initialized, sets the storage quota on the new "
             "repository as well. Default: no quota.",
             "repository as well. Default: no quota.",

+ 12 - 2
src/borg/archiver/tar_cmds.py

@@ -390,7 +390,11 @@ class TarMixIn:
         )
         )
         subparser.set_defaults(func=self.do_export_tar)
         subparser.set_defaults(func=self.do_export_tar)
         subparser.add_argument(
         subparser.add_argument(
-            "--tar-filter", dest="tar_filter", default="auto", help="filter program to pipe data through"
+            "--tar-filter",
+            dest="tar_filter",
+            default="auto",
+            action=Highlander,
+            help="filter program to pipe data through",
         )
         )
         subparser.add_argument(
         subparser.add_argument(
             "--list", dest="output_list", action="store_true", help="output verbose list of items (files, dirs, ...)"
             "--list", dest="output_list", action="store_true", help="output verbose list of items (files, dirs, ...)"
@@ -401,6 +405,7 @@ class TarMixIn:
             dest="tar_format",
             dest="tar_format",
             default="GNU",
             default="GNU",
             choices=("BORG", "PAX", "GNU"),
             choices=("BORG", "PAX", "GNU"),
+            action=Highlander,
             help="select tar format: BORG, PAX or GNU",
             help="select tar format: BORG, PAX or GNU",
         )
         )
         subparser.add_argument("name", metavar="NAME", type=archivename_validator, help="specify the archive name")
         subparser.add_argument("name", metavar="NAME", type=archivename_validator, help="specify the archive name")
@@ -504,6 +509,7 @@ class TarMixIn:
             dest="comment",
             dest="comment",
             type=comment_validator,
             type=comment_validator,
             default="",
             default="",
+            action=Highlander,
             help="add a comment text to the archive",
             help="add a comment text to the archive",
         )
         )
         archive_group.add_argument(
         archive_group.add_argument(
@@ -511,6 +517,7 @@ class TarMixIn:
             dest="timestamp",
             dest="timestamp",
             type=timestamp,
             type=timestamp,
             default=None,
             default=None,
+            action=Highlander,
             metavar="TIMESTAMP",
             metavar="TIMESTAMP",
             help="manually specify the archive creation date/time (yyyy-mm-ddThh:mm:ss[(+|-)HH:MM] format, "
             help="manually specify the archive creation date/time (yyyy-mm-ddThh:mm:ss[(+|-)HH:MM] format, "
             "(+|-)HH:MM is the UTC offset, default: local time zone). Alternatively, give a reference file/directory.",
             "(+|-)HH:MM is the UTC offset, default: local time zone). Alternatively, give a reference file/directory.",
@@ -521,6 +528,7 @@ class TarMixIn:
             dest="checkpoint_interval",
             dest="checkpoint_interval",
             type=int,
             type=int,
             default=1800,
             default=1800,
+            action=Highlander,
             metavar="SECONDS",
             metavar="SECONDS",
             help="write checkpoint every SECONDS seconds (Default: 1800)",
             help="write checkpoint every SECONDS seconds (Default: 1800)",
         )
         )
@@ -530,14 +538,15 @@ class TarMixIn:
             dest="checkpoint_volume",
             dest="checkpoint_volume",
             type=int,
             type=int,
             default=0,
             default=0,
+            action=Highlander,
             help="write checkpoint every BYTES bytes (Default: 0, meaning no volume based checkpointing)",
             help="write checkpoint every BYTES bytes (Default: 0, meaning no volume based checkpointing)",
         )
         )
         archive_group.add_argument(
         archive_group.add_argument(
             "--chunker-params",
             "--chunker-params",
             dest="chunker_params",
             dest="chunker_params",
-            action=Highlander,
             type=ChunkerParams,
             type=ChunkerParams,
             default=CHUNKER_PARAMS,
             default=CHUNKER_PARAMS,
+            action=Highlander,
             metavar="PARAMS",
             metavar="PARAMS",
             help="specify the chunker parameters (ALGO, CHUNK_MIN_EXP, CHUNK_MAX_EXP, "
             help="specify the chunker parameters (ALGO, CHUNK_MIN_EXP, CHUNK_MAX_EXP, "
             "HASH_MASK_BITS, HASH_WINDOW_SIZE). default: %s,%d,%d,%d,%d" % CHUNKER_PARAMS,
             "HASH_MASK_BITS, HASH_WINDOW_SIZE). default: %s,%d,%d,%d,%d" % CHUNKER_PARAMS,
@@ -549,6 +558,7 @@ class TarMixIn:
             dest="compression",
             dest="compression",
             type=CompressionSpec,
             type=CompressionSpec,
             default=CompressionSpec("lz4"),
             default=CompressionSpec("lz4"),
+            action=Highlander,
             help="select compression algorithm, see the output of the " '"borg help compression" command for details.',
             help="select compression algorithm, see the output of the " '"borg help compression" command for details.',
         )
         )
 
 

+ 3 - 1
src/borg/archiver/transfer_cmd.py

@@ -1,6 +1,6 @@
 import argparse
 import argparse
 
 
-from ._common import with_repository, with_other_repository
+from ._common import with_repository, with_other_repository, Highlander
 from ..archive import Archive
 from ..archive import Archive
 from ..constants import *  # NOQA
 from ..constants import *  # NOQA
 from ..crypto.key import uses_same_id_hash, uses_same_chunker_secret
 from ..crypto.key import uses_same_id_hash, uses_same_chunker_secret
@@ -210,6 +210,7 @@ class TransferMixIn:
             dest="other_location",
             dest="other_location",
             type=location_validator(other=True),
             type=location_validator(other=True),
             default=Location(other=True),
             default=Location(other=True),
+            action=Highlander,
             help="transfer archives from the other repository",
             help="transfer archives from the other repository",
         )
         )
         subparser.add_argument(
         subparser.add_argument(
@@ -218,6 +219,7 @@ class TransferMixIn:
             dest="upgrader",
             dest="upgrader",
             type=str,
             type=str,
             default="NoOp",
             default="NoOp",
+            action=Highlander,
             help="use the upgrader to convert transferred data (default: no conversion)",
             help="use the upgrader to convert transferred data (default: no conversion)",
         )
         )
         define_archive_filters_group(subparser)
         define_archive_filters_group(subparser)