diff --git a/src/borg/archiver/__init__.py b/src/borg/archiver/__init__.py index 7fe3969d1..d959f8cad 100644 --- a/src/borg/archiver/__init__.py +++ b/src/borg/archiver/__init__.py @@ -21,6 +21,7 @@ try: logger = create_logger() + from ._common import Highlander from .. import __version__ from ..constants import * # NOQA from ..helpers import EXIT_SUCCESS, EXIT_WARNING, EXIT_ERROR, EXIT_SIGNAL_BASE @@ -219,7 +220,15 @@ class Archiver( def add_argument(*args, **kwargs): if "dest" in kwargs: 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" if is_append: self.append_options.add(kwargs["dest"]) diff --git a/src/borg/archiver/_common.py b/src/borg/archiver/_common.py index bbaaae526..376d4ec31 100644 --- a/src/borg/archiver/_common.py +++ b/src/borg/archiver/_common.py @@ -339,6 +339,7 @@ def define_exclude_and_patterns(add_option, *, tag_files=False, strip_components dest="strip_components", type=int, default=0, + action=Highlander, help="Remove the specified number of leading path elements. " "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", type=SortBySpec, default=sort_by_default, + action=Highlander, help="Comma-separated list of sorting keys; valid keys are: {}; default is: {}".format( ", ".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", metavar="N", dest="first", - default=0, type=positive_int_validator, + default=0, + action=Highlander, help="consider first N archives after other filters were applied", ) group.add_argument( "--last", metavar="N", dest="last", - default=0, type=positive_int_validator, + default=0, + action=Highlander, 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( "--oldest", metavar="TIMESPAN", - type=relative_time_marker_validator, 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.", ) group.add_argument( "--newest", metavar="TIMESPAN", - type=relative_time_marker_validator, 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.", ) @@ -418,15 +424,17 @@ def define_archive_filters_group(subparser, *, sort_by=True, first_last=True, ol group.add_argument( "--older", metavar="TIMESPAN", - type=relative_time_marker_validator, dest="older", + type=relative_time_marker_validator, + action=Highlander, help="consider archives older than (now - TIMESPAN), e.g. 7d oder 12m.", ) group.add_argument( "--newer", metavar="TIMESPAN", - type=relative_time_marker_validator, dest="newer", + type=relative_time_marker_validator, + action=Highlander, 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", type=int, 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).", ) add_common_option( @@ -517,12 +526,14 @@ def define_common_options(add_common_option): dest="umask", type=lambda s: int(s, 8), default=UMASK_DEFAULT, + action=Highlander, help="set umask to M (local only, default: %(default)04o)", ) add_common_option( "--remote-path", metavar="PATH", dest="remote_path", + action=Highlander, help='use PATH as borg executable on the remote (default: "borg")', ) add_common_option( @@ -530,6 +541,7 @@ def define_common_options(add_common_option): metavar="RATE", dest="upload_ratelimit", type=int, + action=Highlander, help="set network upload rate limit in kiByte/s (default: 0=unlimited)", ) add_common_option( @@ -537,6 +549,7 @@ def define_common_options(add_common_option): metavar="UPLOAD_BUFFER", dest="upload_buffer", type=int, + action=Highlander, help="set network upload buffer size in MiB. (default: 0=no buffer)", ) add_common_option( @@ -544,6 +557,7 @@ def define_common_options(add_common_option): metavar="FILE", dest="debug_profile", default=None, + action=Highlander, help="Write execution profile in Borg format into FILE. For local use a Python-" 'compatible file can be generated by suffixing FILE with ".pyprof".', ) @@ -551,6 +565,7 @@ def define_common_options(add_common_option): "--rsh", metavar="RSH", dest="rsh", + action=Highlander, help="Use this command to connect to the 'borg serve' process (default: 'ssh')", ) add_common_option( @@ -560,6 +575,7 @@ def define_common_options(add_common_option): dest="location", type=location_validator(other=False), default=Location(other=False), + action=Highlander, help="repository to use", ) diff --git a/src/borg/archiver/check_cmd.py b/src/borg/archiver/check_cmd.py index 04fc0ee14..e63e86529 100644 --- a/src/borg/archiver/check_cmd.py +++ b/src/borg/archiver/check_cmd.py @@ -1,5 +1,5 @@ import argparse -from ._common import with_repository +from ._common import with_repository, Highlander from ..archive import ArchiveChecker from ..constants import * # NOQA from ..helpers import EXIT_SUCCESS, EXIT_WARNING, EXIT_ERROR @@ -176,6 +176,7 @@ class CheckMixIn: dest="max_duration", type=int, default=0, + action=Highlander, help="do only a partial repo check for max. SECONDS seconds (Default: unlimited)", ) define_archive_filters_group(subparser) diff --git a/src/borg/archiver/compact_cmd.py b/src/borg/archiver/compact_cmd.py index e7960ace7..ba8cf8936 100644 --- a/src/borg/archiver/compact_cmd.py +++ b/src/borg/archiver/compact_cmd.py @@ -1,6 +1,6 @@ import argparse -from ._common import with_repository +from ._common import with_repository, Highlander from ..constants import * # NOQA from ..helpers import EXIT_SUCCESS from ..manifest import Manifest @@ -61,5 +61,6 @@ class CompactMixIn: dest="threshold", type=int, default=10, + action=Highlander, help="set minimum threshold for saved space in PERCENT (Default: 10)", ) diff --git a/src/borg/archiver/create_cmd.py b/src/borg/archiver/create_cmd.py index 93f931076..911abb378 100644 --- a/src/borg/archiver/create_cmd.py +++ b/src/borg/archiver/create_cmd.py @@ -763,6 +763,7 @@ class CreateMixIn: metavar="NAME", dest="stdin_name", default="stdin", + action=Highlander, help="use NAME in archive for stdin data (default: %(default)r)", ) subparser.add_argument( @@ -770,6 +771,7 @@ class CreateMixIn: metavar="USER", dest="stdin_user", default=None, + action=Highlander, help="set user USER in archive for stdin data (default: do not store user/uid)", ) subparser.add_argument( @@ -777,6 +779,7 @@ class CreateMixIn: metavar="GROUP", dest="stdin_group", default=None, + action=Highlander, help="set group GROUP in archive for stdin data (default: do not store group/gid)", ) subparser.add_argument( @@ -785,6 +788,7 @@ class CreateMixIn: dest="stdin_mode", type=lambda s: int(s, 8), default=STDIN_MODE_DEFAULT, + action=Highlander, help="set mode to M in archive for stdin data (default: %(default)04o)", ) subparser.add_argument( @@ -804,6 +808,7 @@ class CreateMixIn: ) subparser.add_argument( "--paths-delimiter", + action=Highlander, metavar="DELIM", help="set path delimiter for ``--paths-from-stdin`` and ``--paths-from-command`` (default: \\n) ", ) @@ -878,6 +883,7 @@ class CreateMixIn: dest="comment", type=comment_validator, default="", + action=Highlander, help="add a comment text to the archive", ) archive_group.add_argument( @@ -886,6 +892,7 @@ class CreateMixIn: dest="timestamp", type=timestamp, default=None, + action=Highlander, 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.", ) @@ -896,6 +903,7 @@ class CreateMixIn: dest="checkpoint_interval", type=int, default=1800, + action=Highlander, help="write checkpoint every SECONDS seconds (Default: 1800)", ) archive_group.add_argument( @@ -904,6 +912,7 @@ class CreateMixIn: dest="checkpoint_volume", type=int, default=0, + action=Highlander, help="write checkpoint every BYTES bytes (Default: 0, meaning no volume based checkpointing)", ) archive_group.add_argument( @@ -923,6 +932,7 @@ class CreateMixIn: dest="compression", type=CompressionSpec, default=CompressionSpec("lz4"), + action=Highlander, help="select compression algorithm, see the output of the " '"borg help compression" command for details.', ) diff --git a/src/borg/archiver/debug_cmd.py b/src/borg/archiver/debug_cmd.py index e9a1adab1..6c0d1892f 100644 --- a/src/borg/archiver/debug_cmd.py +++ b/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 ..repoobj import RepoObj -from ._common import with_repository +from ._common import with_repository, Highlander from ._common import process_epilog @@ -521,16 +521,18 @@ class DebugMixIn: "--segment", metavar="SEG", dest="segment", - default=None, type=positive_int_validator, + default=None, + action=Highlander, help="used together with --ghost: limit processing to given segment.", ) subparser.add_argument( "--offset", metavar="OFFS", dest="offset", - default=None, type=positive_int_validator, + default=None, + action=Highlander, help="used together with --ghost: limit processing to given offset.", ) @@ -553,6 +555,7 @@ class DebugMixIn: "wanted", metavar="WANTED", type=str, + action=Highlander, help="term to search the repo for, either 0x1234abcd hex term or a string", ) debug_id_hash_epilog = process_epilog( @@ -631,6 +634,7 @@ class DebugMixIn: dest="compression", type=CompressionSpec, default=CompressionSpec("lz4"), + action=Highlander, help="select compression algorithm, see the output of the " '"borg help compression" command for details.', ) subparser.add_argument( diff --git a/src/borg/archiver/delete_cmd.py b/src/borg/archiver/delete_cmd.py index 5ff6817d4..e9444dcf7 100644 --- a/src/borg/archiver/delete_cmd.py +++ b/src/borg/archiver/delete_cmd.py @@ -1,7 +1,7 @@ import argparse import logging -from ._common import with_repository +from ._common import with_repository, Highlander from ..archive import Archive, Statistics from ..cache import Cache from ..constants import * # NOQA @@ -156,6 +156,7 @@ class DeleteMixIn: dest="checkpoint_interval", type=int, default=1800, + action=Highlander, help="write checkpoint every SECONDS seconds (Default: 1800)", ) define_archive_filters_group(subparser) diff --git a/src/borg/archiver/list_cmd.py b/src/borg/archiver/list_cmd.py index 9a007b672..a71bc9e11 100644 --- a/src/borg/archiver/list_cmd.py +++ b/src/borg/archiver/list_cmd.py @@ -2,7 +2,7 @@ import argparse import textwrap import sys -from ._common import with_repository, build_matcher +from ._common import with_repository, build_matcher, Highlander from ..archive import Archive from ..cache import Cache from ..constants import * # NOQA @@ -105,6 +105,7 @@ class ListMixIn: "--format", metavar="FORMAT", dest="format", + action=Highlander, help="specify format for file listing " '(default: "{mode} {user:6} {group:6} {size:8} {mtime} {path}{extra}{NL}")', ) diff --git a/src/borg/archiver/prune_cmd.py b/src/borg/archiver/prune_cmd.py index 1fae9e94b..55fb89d00 100644 --- a/src/borg/archiver/prune_cmd.py +++ b/src/borg/archiver/prune_cmd.py @@ -5,7 +5,7 @@ import logging from operator import attrgetter import re -from ._common import with_repository +from ._common import with_repository, Highlander from ..archive import Archive, Statistics from ..cache import Cache from ..constants import * # NOQA @@ -257,6 +257,7 @@ class PruneMixIn: metavar="INTERVAL", dest="within", type=interval, + action=Highlander, help="keep all archives within this time interval", ) subparser.add_argument( @@ -265,25 +266,61 @@ class PruneMixIn: dest="secondly", type=int, default=0, + action=Highlander, help="number of secondly archives to keep", ) 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( - "-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( - "-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( - "-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( - "-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( - "-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) subparser.add_argument( @@ -293,5 +330,6 @@ class PruneMixIn: dest="checkpoint_interval", type=int, default=1800, + action=Highlander, help="write checkpoint every SECONDS seconds (Default: 1800)", ) diff --git a/src/borg/archiver/rcompress_cmd.py b/src/borg/archiver/rcompress_cmd.py index adc14a6f4..038fd70be 100644 --- a/src/borg/archiver/rcompress_cmd.py +++ b/src/borg/archiver/rcompress_cmd.py @@ -1,7 +1,7 @@ import argparse from collections import defaultdict -from ._common import with_repository +from ._common import with_repository, Highlander from ..constants import * # NOQA from ..compress import CompressionSpec, ObfuscateSize, Auto, COMPRESSOR_TABLE from ..helpers import sig_int, ProgressIndicatorPercent @@ -230,6 +230,7 @@ class RCompressMixIn: dest="compression", type=CompressionSpec, default=CompressionSpec("lz4"), + action=Highlander, help="select compression algorithm, see the output of the " '"borg help compression" command for details.', ) @@ -242,5 +243,6 @@ class RCompressMixIn: dest="checkpoint_interval", type=int, default=1800, + action=Highlander, help="write checkpoint every SECONDS seconds (Default: 1800)", ) diff --git a/src/borg/archiver/rcreate_cmd.py b/src/borg/archiver/rcreate_cmd.py index a3324104b..9e0504a01 100644 --- a/src/borg/archiver/rcreate_cmd.py +++ b/src/borg/archiver/rcreate_cmd.py @@ -1,6 +1,6 @@ import argparse -from ._common import with_repository, with_other_repository +from ._common import with_repository, with_other_repository, Highlander from ..cache import Cache from ..constants import * # NOQA from ..crypto.key import key_creator, key_argument_names, tam_required_file @@ -184,6 +184,7 @@ class RCreateMixIn: dest="other_location", type=location_validator(other=True), default=Location(other=True), + action=Highlander, help="reuse the key material from the other repository", ) subparser.add_argument( @@ -193,6 +194,7 @@ class RCreateMixIn: dest="encryption", required=True, choices=key_argument_names(), + action=Highlander, help="select encryption key mode **(required)**", ) subparser.add_argument( @@ -210,6 +212,7 @@ class RCreateMixIn: dest="storage_quota", default=None, type=parse_storage_quota, + action=Highlander, help="Set storage quota of the new repository (e.g. 5G, 1.5T). Default: no quota.", ) subparser.add_argument( diff --git a/src/borg/archiver/recreate_cmd.py b/src/borg/archiver/recreate_cmd.py index fe58d5f77..833493480 100644 --- a/src/borg/archiver/recreate_cmd.py +++ b/src/borg/archiver/recreate_cmd.py @@ -149,6 +149,7 @@ class RecreateMixIn: metavar="TARGET", default=None, type=archivename_validator, + action=Highlander, help="create a new archive with the name ARCHIVE, do not replace existing archive " "(only applies for a single archive)", ) @@ -158,6 +159,7 @@ class RecreateMixIn: dest="checkpoint_interval", type=int, default=1800, + action=Highlander, metavar="SECONDS", help="write checkpoint every SECONDS seconds (Default: 1800)", ) @@ -167,6 +169,7 @@ class RecreateMixIn: dest="checkpoint_volume", type=int, default=0, + action=Highlander, help="write checkpoint every BYTES bytes (Default: 0, meaning no volume based checkpointing)", ) archive_group.add_argument( @@ -175,6 +178,7 @@ class RecreateMixIn: dest="comment", type=comment_validator, default=None, + action=Highlander, help="add a comment text to the archive", ) archive_group.add_argument( @@ -183,6 +187,7 @@ class RecreateMixIn: dest="timestamp", type=timestamp, default=None, + action=Highlander, 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.", ) @@ -193,6 +198,7 @@ class RecreateMixIn: dest="compression", type=CompressionSpec, default=CompressionSpec("lz4"), + action=Highlander, help="select compression algorithm, see the output of the " '"borg help compression" command for details.', ) archive_group.add_argument( @@ -203,6 +209,7 @@ class RecreateMixIn: default="never", const="if-different", choices=("never", "if-different", "always"), + action=Highlander, help="recompress data chunks according to `MODE` and ``--compression``. " "Possible modes are " "`if-different`: recompress if current compression is with a different " @@ -217,9 +224,9 @@ class RecreateMixIn: "--chunker-params", metavar="PARAMS", dest="chunker_params", - action=Highlander, type=ChunkerParams, default=None, + action=Highlander, 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. " "default: do not rechunk", diff --git a/src/borg/archiver/rlist_cmd.py b/src/borg/archiver/rlist_cmd.py index 895d426a1..411712626 100644 --- a/src/borg/archiver/rlist_cmd.py +++ b/src/borg/archiver/rlist_cmd.py @@ -2,7 +2,7 @@ import argparse import textwrap import sys -from ._common import with_repository +from ._common import with_repository, Highlander from ..constants import * # NOQA from ..helpers import BaseFormatter, ArchiveFormatter, json_print, basic_json_data from ..manifest import Manifest @@ -106,6 +106,7 @@ class RListMixIn: "--format", metavar="FORMAT", dest="format", + action=Highlander, help="specify format for archive listing " '(default: "{archive:<36} {time} [{id}]{NL}")', ) subparser.add_argument( diff --git a/src/borg/archiver/serve_cmd.py b/src/borg/archiver/serve_cmd.py index bb0afee1a..b69d60329 100644 --- a/src/borg/archiver/serve_cmd.py +++ b/src/borg/archiver/serve_cmd.py @@ -1,5 +1,6 @@ import argparse +from ._common import Highlander from ..constants import * # NOQA from ..helpers import EXIT_SUCCESS from ..helpers import parse_storage_quota @@ -76,6 +77,7 @@ class ServeMixIn: dest="storage_quota", type=parse_storage_quota, default=None, + action=Highlander, 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 " "repository as well. Default: no quota.", diff --git a/src/borg/archiver/tar_cmds.py b/src/borg/archiver/tar_cmds.py index 2bbe81854..30f4a6d68 100644 --- a/src/borg/archiver/tar_cmds.py +++ b/src/borg/archiver/tar_cmds.py @@ -390,7 +390,11 @@ class TarMixIn: ) subparser.set_defaults(func=self.do_export_tar) 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( "--list", dest="output_list", action="store_true", help="output verbose list of items (files, dirs, ...)" @@ -401,6 +405,7 @@ class TarMixIn: dest="tar_format", default="GNU", choices=("BORG", "PAX", "GNU"), + action=Highlander, help="select tar format: BORG, PAX or GNU", ) subparser.add_argument("name", metavar="NAME", type=archivename_validator, help="specify the archive name") @@ -504,6 +509,7 @@ class TarMixIn: dest="comment", type=comment_validator, default="", + action=Highlander, help="add a comment text to the archive", ) archive_group.add_argument( @@ -511,6 +517,7 @@ class TarMixIn: dest="timestamp", type=timestamp, default=None, + action=Highlander, metavar="TIMESTAMP", 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.", @@ -521,6 +528,7 @@ class TarMixIn: dest="checkpoint_interval", type=int, default=1800, + action=Highlander, metavar="SECONDS", help="write checkpoint every SECONDS seconds (Default: 1800)", ) @@ -530,14 +538,15 @@ class TarMixIn: dest="checkpoint_volume", type=int, default=0, + action=Highlander, help="write checkpoint every BYTES bytes (Default: 0, meaning no volume based checkpointing)", ) archive_group.add_argument( "--chunker-params", dest="chunker_params", - action=Highlander, type=ChunkerParams, default=CHUNKER_PARAMS, + action=Highlander, metavar="PARAMS", 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, @@ -549,6 +558,7 @@ class TarMixIn: dest="compression", type=CompressionSpec, default=CompressionSpec("lz4"), + action=Highlander, help="select compression algorithm, see the output of the " '"borg help compression" command for details.', ) diff --git a/src/borg/archiver/transfer_cmd.py b/src/borg/archiver/transfer_cmd.py index dcde6b883..6be3dbdbb 100644 --- a/src/borg/archiver/transfer_cmd.py +++ b/src/borg/archiver/transfer_cmd.py @@ -1,6 +1,6 @@ import argparse -from ._common import with_repository, with_other_repository +from ._common import with_repository, with_other_repository, Highlander from ..archive import Archive from ..constants import * # NOQA from ..crypto.key import uses_same_id_hash, uses_same_chunker_secret @@ -210,6 +210,7 @@ class TransferMixIn: dest="other_location", type=location_validator(other=True), default=Location(other=True), + action=Highlander, help="transfer archives from the other repository", ) subparser.add_argument( @@ -218,6 +219,7 @@ class TransferMixIn: dest="upgrader", type=str, default="NoOp", + action=Highlander, help="use the upgrader to convert transferred data (default: no conversion)", ) define_archive_filters_group(subparser)