2019-06-23 04:32:27 +00:00
import collections
2020-11-15 21:39:15 +00:00
from argparse import Action , ArgumentParser
2019-06-23 04:32:27 +00:00
from borgmatic . config import collect
SUBPARSER_ALIASES = {
2022-08-21 21:25:16 +00:00
' rcreate ' : [ ' init ' , ' -I ' ] ,
' prune ' : [ ' -p ' ] ,
2022-02-08 07:29:44 +00:00
' compact ' : [ ] ,
2022-08-21 21:25:16 +00:00
' create ' : [ ' -C ' ] ,
' check ' : [ ' -k ' ] ,
' extract ' : [ ' -x ' ] ,
' export-tar ' : [ ] ,
' mount ' : [ ' -m ' ] ,
' umount ' : [ ' -u ' ] ,
' restore ' : [ ' -r ' ] ,
2022-08-15 22:04:40 +00:00
' rlist ' : [ ] ,
2022-08-21 21:25:16 +00:00
' list ' : [ ' -l ' ] ,
2022-08-13 06:06:56 +00:00
' rinfo ' : [ ] ,
2022-08-21 21:25:16 +00:00
' info ' : [ ' -i ' ] ,
2022-08-18 21:28:12 +00:00
' transfer ' : [ ] ,
2022-10-04 20:42:18 +00:00
' break-lock ' : [ ] ,
2021-06-18 03:41:44 +00:00
' borg ' : [ ] ,
2019-06-23 04:32:27 +00:00
}
2019-09-20 18:43:27 +00:00
def parse_subparser_arguments ( unparsed_arguments , subparsers ) :
2019-06-23 04:32:27 +00:00
'''
2021-06-18 03:41:44 +00:00
Given a sequence of arguments and a dict from subparser name to argparse . ArgumentParser
instance , give each requested action ' s subparser a shot at parsing all arguments. This allows
common arguments like " --repository " to be shared across multiple subparsers .
2019-06-23 04:32:27 +00:00
2021-06-18 03:41:44 +00:00
Return the result as a tuple of ( a dict mapping from subparser name to a parsed namespace of
arguments , a list of remaining arguments not claimed by any subparser ) .
2019-06-23 04:32:27 +00:00
'''
arguments = collections . OrderedDict ( )
remaining_arguments = list ( unparsed_arguments )
alias_to_subparser_name = {
alias : subparser_name
for subparser_name , aliases in SUBPARSER_ALIASES . items ( )
for alias in aliases
}
2021-06-18 03:41:44 +00:00
# If the "borg" action is used, skip all other subparsers. This avoids confusion like
# "borg list" triggering borgmatic's own list action.
if ' borg ' in unparsed_arguments :
subparsers = { ' borg ' : subparsers [ ' borg ' ] }
2023-03-08 21:19:41 +00:00
for argument in remaining_arguments :
canonical_name = alias_to_subparser_name . get ( argument , argument )
subparser = subparsers . get ( canonical_name )
2019-06-23 04:32:27 +00:00
2023-03-08 21:19:41 +00:00
if not subparser :
continue
2019-06-23 04:32:27 +00:00
2019-09-20 18:43:27 +00:00
# If a parsed value happens to be the same as the name of a subparser, remove it from the
# remaining arguments. This prevents, for instance, "check --only extract" from triggering
# the "extract" subparser.
parsed , unused_remaining = subparser . parse_known_args ( unparsed_arguments )
for value in vars ( parsed ) . values ( ) :
if isinstance ( value , str ) :
2021-06-18 03:41:44 +00:00
if value in subparsers :
2019-09-20 18:43:27 +00:00
remaining_arguments . remove ( value )
elif isinstance ( value , list ) :
for item in value :
2021-06-18 03:41:44 +00:00
if item in subparsers :
2019-09-20 18:43:27 +00:00
remaining_arguments . remove ( item )
2019-06-23 04:32:27 +00:00
arguments [ canonical_name ] = parsed
2023-03-08 22:05:06 +00:00
# If no actions are explicitly requested, assume defaults.
2019-06-23 04:32:27 +00:00
if not arguments and ' --help ' not in unparsed_arguments and ' -h ' not in unparsed_arguments :
2023-03-08 22:05:06 +00:00
for subparser_name in ( ' create ' , ' prune ' , ' compact ' , ' check ' ) :
2021-06-18 03:41:44 +00:00
subparser = subparsers [ subparser_name ]
2019-09-20 18:43:27 +00:00
parsed , unused_remaining = subparser . parse_known_args ( unparsed_arguments )
2019-06-23 04:32:27 +00:00
arguments [ subparser_name ] = parsed
2019-09-20 18:43:27 +00:00
remaining_arguments = list ( unparsed_arguments )
2019-06-23 04:32:27 +00:00
2021-06-18 03:41:44 +00:00
# Now ask each subparser, one by one, to greedily consume arguments.
for subparser_name , subparser in subparsers . items ( ) :
if subparser_name not in arguments . keys ( ) :
2019-09-20 18:43:27 +00:00
continue
2019-06-23 04:32:27 +00:00
2021-06-18 03:41:44 +00:00
subparser = subparsers [ subparser_name ]
2019-09-20 18:43:27 +00:00
unused_parsed , remaining_arguments = subparser . parse_known_args ( remaining_arguments )
2021-06-18 03:41:44 +00:00
# Special case: If "borg" is present in the arguments, consume all arguments after (+1) the
# "borg" action.
if ' borg ' in arguments :
borg_options_index = remaining_arguments . index ( ' borg ' ) + 1
arguments [ ' borg ' ] . options = remaining_arguments [ borg_options_index : ]
remaining_arguments = remaining_arguments [ : borg_options_index ]
2019-09-22 18:30:58 +00:00
2019-09-20 18:43:27 +00:00
# Remove the subparser names themselves.
2021-06-18 03:41:44 +00:00
for subparser_name , subparser in subparsers . items ( ) :
2019-09-20 18:43:27 +00:00
if subparser_name in remaining_arguments :
remaining_arguments . remove ( subparser_name )
2021-06-18 03:41:44 +00:00
return ( arguments , remaining_arguments )
2019-06-23 04:32:27 +00:00
2020-11-15 21:39:15 +00:00
class Extend_action ( Action ) :
'''
An argparse action to support Python 3.8 ' s " extend " action in older versions of Python.
'''
def __call__ ( self , parser , namespace , values , option_string = None ) :
items = getattr ( namespace , self . dest , None )
if items :
items . extend ( values )
else :
setattr ( namespace , self . dest , list ( values ) )
2022-05-26 17:27:53 +00:00
def make_parsers ( ) :
2019-06-23 04:32:27 +00:00
'''
2022-05-26 17:27:53 +00:00
Build a top - level parser and its subparsers and return them as a tuple .
2019-06-23 04:32:27 +00:00
'''
2020-01-02 18:37:31 +00:00
config_paths = collect . get_default_config_paths ( expand_home = True )
unexpanded_config_paths = collect . get_default_config_paths ( expand_home = False )
2019-06-23 04:32:27 +00:00
global_parser = ArgumentParser ( add_help = False )
2020-11-15 21:39:15 +00:00
global_parser . register ( ' action ' , ' extend ' , Extend_action )
2019-06-23 04:32:27 +00:00
global_group = global_parser . add_argument_group ( ' global arguments ' )
global_group . add_argument (
' -c ' ,
' --config ' ,
nargs = ' * ' ,
dest = ' config_paths ' ,
default = config_paths ,
2023-03-24 06:11:14 +00:00
help = f " Configuration filenames or directories, defaults to: { ' ' . join ( unexpanded_config_paths ) } " ,
2019-06-23 04:32:27 +00:00
)
global_group . add_argument (
' --excludes ' ,
dest = ' excludes_filename ' ,
help = ' Deprecated in favor of exclude_patterns within configuration ' ,
)
global_group . add_argument (
' -n ' ,
' --dry-run ' ,
dest = ' dry_run ' ,
action = ' store_true ' ,
help = ' Go through the motions, but do not actually write to any repositories ' ,
)
global_group . add_argument (
' -nc ' , ' --no-color ' , dest = ' no_color ' , action = ' store_true ' , help = ' Disable colored output '
)
global_group . add_argument (
' -v ' ,
' --verbosity ' ,
type = int ,
2019-11-03 08:55:19 +00:00
choices = range ( - 1 , 3 ) ,
2019-06-23 04:32:27 +00:00
default = 0 ,
2019-11-18 06:52:26 +00:00
help = ' Display verbose progress to the console (from only errors to very verbose: -1, 0, 1, or 2) ' ,
2019-06-23 04:32:27 +00:00
)
global_group . add_argument (
' --syslog-verbosity ' ,
type = int ,
2019-11-03 08:55:19 +00:00
choices = range ( - 1 , 3 ) ,
2019-06-23 04:32:27 +00:00
default = 0 ,
2019-11-18 06:52:26 +00:00
help = ' Log verbose progress to syslog (from only errors to very verbose: -1, 0, 1, or 2). Ignored when console is interactive or --log-file is given ' ,
2019-11-02 18:23:18 +00:00
)
global_group . add_argument (
' --log-file-verbosity ' ,
type = int ,
2019-11-03 08:55:19 +00:00
choices = range ( - 1 , 3 ) ,
default = 0 ,
2019-11-18 06:52:26 +00:00
help = ' Log verbose progress to log file (from only errors to very verbose: -1, 0, 1, or 2). Only used when --log-file is given ' ,
2019-06-23 04:32:27 +00:00
)
2020-01-22 23:10:47 +00:00
global_group . add_argument (
' --monitoring-verbosity ' ,
type = int ,
choices = range ( - 1 , 3 ) ,
2020-01-31 18:23:36 +00:00
default = 0 ,
2020-01-22 23:10:47 +00:00
help = ' Log verbose progress to monitoring integrations that support logging (from only errors to very verbose: -1, 0, 1, or 2) ' ,
)
2019-10-31 09:44:22 +00:00
global_group . add_argument (
' --log-file ' ,
type = str ,
default = None ,
2019-11-02 18:23:18 +00:00
help = ' Write log messages to this file instead of syslog ' ,
2019-10-31 09:44:22 +00:00
)
2019-12-17 19:46:27 +00:00
global_group . add_argument (
' --override ' ,
metavar = ' SECTION.OPTION=VALUE ' ,
nargs = ' + ' ,
dest = ' overrides ' ,
2020-10-23 23:06:00 +00:00
action = ' extend ' ,
2019-12-17 19:46:27 +00:00
help = ' One or more configuration file options to override with specified values ' ,
)
2022-06-16 16:52:54 +00:00
global_group . add_argument (
2022-06-16 18:35:24 +00:00
' --no-environment-interpolation ' ,
2022-06-16 16:52:54 +00:00
dest = ' resolve_env ' ,
action = ' store_false ' ,
help = ' Do not resolve environment variables in configuration file ' ,
)
2022-05-26 17:27:53 +00:00
global_group . add_argument (
' --bash-completion ' ,
default = False ,
action = ' store_true ' ,
help = ' Show bash completion script and exit ' ,
)
2019-06-23 04:32:27 +00:00
global_group . add_argument (
' --version ' ,
dest = ' version ' ,
default = False ,
action = ' store_true ' ,
help = ' Display installed version number of borgmatic and exit ' ,
)
top_level_parser = ArgumentParser (
description = '''
2019-11-18 06:49:16 +00:00
Simple , configuration - driven backup software for servers and workstations . If none of
2023-03-08 22:05:06 +00:00
the action options are given , then borgmatic defaults to : create , prune , compact , and
2022-02-09 22:33:12 +00:00
check .
2019-06-23 04:32:27 +00:00
''' ,
parents = [ global_parser ] ,
)
2019-06-23 16:46:22 +00:00
subparsers = top_level_parser . add_subparsers (
title = ' actions ' ,
metavar = ' ' ,
2023-03-24 21:14:56 +00:00
help = ' Specify zero or more actions. Defaults to create, prune, compact, and check. Use --help with action for details: ' ,
2019-06-23 16:46:22 +00:00
)
2022-08-12 21:53:20 +00:00
rcreate_parser = subparsers . add_parser (
' rcreate ' ,
aliases = SUBPARSER_ALIASES [ ' rcreate ' ] ,
help = ' Create a new, empty Borg repository ' ,
description = ' Create a new, empty Borg repository ' ,
2019-06-23 04:32:27 +00:00
add_help = False ,
)
2022-08-12 21:53:20 +00:00
rcreate_group = rcreate_parser . add_argument_group ( ' rcreate arguments ' )
rcreate_group . add_argument (
2019-06-23 04:32:27 +00:00
' -e ' ,
' --encryption ' ,
dest = ' encryption_mode ' ,
help = ' Borg repository encryption mode ' ,
required = True ,
)
2022-08-18 00:33:09 +00:00
rcreate_group . add_argument (
2022-08-19 06:06:51 +00:00
' --source-repository ' ,
2022-08-18 00:33:09 +00:00
' --other-repo ' ,
2022-08-19 06:06:51 +00:00
metavar = ' KEY_REPOSITORY ' ,
2022-08-18 00:33:09 +00:00
help = ' Path to an existing Borg repository whose key material should be reused (Borg 2.x+ only) ' ,
)
2023-02-27 07:22:23 +00:00
rcreate_group . add_argument (
' --repository ' ,
help = ' Path of the new repository to create (must be already specified in a borgmatic configuration file), defaults to the configured repository if there is only one ' ,
)
2022-08-12 21:53:20 +00:00
rcreate_group . add_argument (
2022-08-18 21:28:12 +00:00
' --copy-crypt-key ' ,
2019-06-23 04:32:27 +00:00
action = ' store_true ' ,
2022-08-19 06:06:51 +00:00
help = ' Copy the crypt key used for authenticated encryption from the source repository, defaults to a new random key (Borg 2.x+ only) ' ,
2019-06-23 04:32:27 +00:00
)
2022-08-12 21:53:20 +00:00
rcreate_group . add_argument (
2022-08-18 21:28:12 +00:00
' --append-only ' , action = ' store_true ' , help = ' Create an append-only repository ' ,
)
rcreate_group . add_argument (
' --storage-quota ' , help = ' Create a repository with a fixed storage quota ' ,
)
rcreate_group . add_argument (
' --make-parent-dirs ' ,
action = ' store_true ' ,
help = ' Create any missing parent directories of the repository directory ' ,
2019-06-23 04:32:27 +00:00
)
2022-08-12 21:53:20 +00:00
rcreate_group . add_argument (
' -h ' , ' --help ' , action = ' help ' , help = ' Show this help message and exit '
)
2019-06-23 04:32:27 +00:00
2022-08-19 06:06:51 +00:00
transfer_parser = subparsers . add_parser (
' transfer ' ,
aliases = SUBPARSER_ALIASES [ ' transfer ' ] ,
2022-08-19 06:33:05 +00:00
help = ' Transfer archives from one repository to another, optionally upgrading the transferred data (Borg 2.0+ only) ' ,
description = ' Transfer archives from one repository to another, optionally upgrading the transferred data (Borg 2.0+ only) ' ,
2022-08-19 06:06:51 +00:00
add_help = False ,
)
transfer_group = transfer_parser . add_argument_group ( ' transfer arguments ' )
transfer_group . add_argument (
' --repository ' ,
help = ' Path of existing destination repository to transfer archives to, defaults to the configured repository if there is only one ' ,
)
transfer_group . add_argument (
' --source-repository ' ,
help = ' Path of existing source repository to transfer archives from ' ,
required = True ,
)
transfer_group . add_argument (
' --archive ' ,
help = ' Name of single archive to transfer (or " latest " ), defaults to transferring all archives ' ,
)
transfer_group . add_argument (
' --upgrader ' ,
2023-04-01 16:40:32 +00:00
help = ' Upgrader type used to convert the transferred data, e.g. " From12To20 " to upgrade data from Borg 1.2 to 2.0 format, defaults to no conversion ' ,
2022-08-19 06:06:51 +00:00
)
2023-02-27 07:22:23 +00:00
transfer_group . add_argument (
' --progress ' ,
default = False ,
action = ' store_true ' ,
help = ' Display progress as each archive is transferred ' ,
)
2022-08-19 06:06:51 +00:00
transfer_group . add_argument (
' -a ' ,
2022-10-04 05:50:37 +00:00
' --match-archives ' ,
2022-08-19 06:06:51 +00:00
' --glob-archives ' ,
2022-10-04 05:50:37 +00:00
metavar = ' PATTERN ' ,
help = ' Only transfer archives with names matching this pattern ' ,
2022-08-19 06:06:51 +00:00
)
transfer_group . add_argument (
' --sort-by ' , metavar = ' KEYS ' , help = ' Comma-separated list of sorting keys '
)
transfer_group . add_argument (
' --first ' ,
metavar = ' N ' ,
help = ' Only transfer first N archives after other filters are applied ' ,
)
transfer_group . add_argument (
' --last ' , metavar = ' N ' , help = ' Only transfer last N archives after other filters are applied '
)
transfer_group . add_argument (
' -h ' , ' --help ' , action = ' help ' , help = ' Show this help message and exit '
)
2019-06-23 04:32:27 +00:00
prune_parser = subparsers . add_parser (
' prune ' ,
aliases = SUBPARSER_ALIASES [ ' prune ' ] ,
2022-02-09 22:33:12 +00:00
help = ' Prune archives according to the retention policy (with Borg 1.2+, run compact afterwards to actually free space) ' ,
description = ' Prune archives according to the retention policy (with Borg 1.2+, run compact afterwards to actually free space) ' ,
2019-06-23 04:32:27 +00:00
add_help = False ,
)
prune_group = prune_parser . add_argument_group ( ' prune arguments ' )
2023-03-15 16:39:54 +00:00
prune_group . add_argument (
' --repository ' ,
help = ' Path of specific existing repository to prune (must be already specified in a borgmatic configuration file) ' ,
)
2019-06-23 04:32:27 +00:00
prune_group . add_argument (
' --stats ' ,
dest = ' stats ' ,
default = False ,
action = ' store_true ' ,
help = ' Display statistics of archive ' ,
)
2020-01-11 15:38:07 +00:00
prune_group . add_argument (
2022-08-21 21:25:16 +00:00
' --list ' , dest = ' list_archives ' , action = ' store_true ' , help = ' List archives kept/pruned '
2020-01-11 15:38:07 +00:00
)
2019-06-23 04:32:27 +00:00
prune_group . add_argument ( ' -h ' , ' --help ' , action = ' help ' , help = ' Show this help message and exit ' )
2022-02-08 07:29:44 +00:00
compact_parser = subparsers . add_parser (
' compact ' ,
aliases = SUBPARSER_ALIASES [ ' compact ' ] ,
2022-12-23 22:12:48 +00:00
help = ' Compact segments to free space (Borg 1.2+, borgmatic 1.5.23+ only) ' ,
description = ' Compact segments to free space (Borg 1.2+, borgmatic 1.5.23+ only) ' ,
2022-02-08 07:29:44 +00:00
add_help = False ,
)
compact_group = compact_parser . add_argument_group ( ' compact arguments ' )
2023-03-16 15:13:45 +00:00
compact_group . add_argument (
' --repository ' ,
help = ' Path of specific existing repository to compact (must be already specified in a borgmatic configuration file) ' ,
)
2022-02-08 07:29:44 +00:00
compact_group . add_argument (
' --progress ' ,
dest = ' progress ' ,
default = False ,
action = ' store_true ' ,
help = ' Display progress as each segment is compacted ' ,
)
compact_group . add_argument (
' --cleanup-commits ' ,
dest = ' cleanup_commits ' ,
default = False ,
action = ' store_true ' ,
2022-08-12 22:46:33 +00:00
help = ' Cleanup commit-only 17-byte segment files left behind by Borg 1.1 (flag in Borg 1.2 only) ' ,
2022-02-08 07:29:44 +00:00
)
compact_group . add_argument (
' --threshold ' ,
type = int ,
dest = ' threshold ' ,
help = ' Minimum saved space percentage threshold for compacting a segment, defaults to 10 ' ,
)
2022-02-08 20:05:02 +00:00
compact_group . add_argument (
' -h ' , ' --help ' , action = ' help ' , help = ' Show this help message and exit '
)
2022-02-08 07:29:44 +00:00
2019-06-23 04:32:27 +00:00
create_parser = subparsers . add_parser (
' create ' ,
aliases = SUBPARSER_ALIASES [ ' create ' ] ,
2022-08-18 04:14:58 +00:00
help = ' Create an archive (actually perform a backup) ' ,
description = ' Create an archive (actually perform a backup) ' ,
2019-06-23 04:32:27 +00:00
add_help = False ,
)
create_group = create_parser . add_argument_group ( ' create arguments ' )
2023-03-16 17:15:49 +00:00
create_group . add_argument (
' --repository ' ,
help = ' Path of specific existing repository to backup to (must be already specified in a borgmatic configuration file) ' ,
)
2019-06-23 04:32:27 +00:00
create_group . add_argument (
' --progress ' ,
dest = ' progress ' ,
default = False ,
action = ' store_true ' ,
2020-01-24 19:27:16 +00:00
help = ' Display progress for each file as it is backed up ' ,
2019-06-23 04:32:27 +00:00
)
create_group . add_argument (
' --stats ' ,
dest = ' stats ' ,
default = False ,
action = ' store_true ' ,
help = ' Display statistics of archive ' ,
)
2020-01-11 15:38:07 +00:00
create_group . add_argument (
2022-08-21 21:25:16 +00:00
' --list ' , ' --files ' , dest = ' list_files ' , action = ' store_true ' , help = ' Show per-file details '
2020-01-11 15:38:07 +00:00
)
2019-06-23 04:32:27 +00:00
create_group . add_argument (
' --json ' , dest = ' json ' , default = False , action = ' store_true ' , help = ' Output results as JSON '
)
create_group . add_argument ( ' -h ' , ' --help ' , action = ' help ' , help = ' Show this help message and exit ' )
check_parser = subparsers . add_parser (
' check ' ,
aliases = SUBPARSER_ALIASES [ ' check ' ] ,
help = ' Check archives for consistency ' ,
description = ' Check archives for consistency ' ,
add_help = False ,
)
check_group = check_parser . add_argument_group ( ' check arguments ' )
2023-03-16 12:34:52 +00:00
check_group . add_argument (
' --repository ' ,
help = ' Path of specific existing repository to check (must be already specified in a borgmatic configuration file) ' ,
)
2020-01-24 19:27:16 +00:00
check_group . add_argument (
' --progress ' ,
dest = ' progress ' ,
default = False ,
action = ' store_true ' ,
help = ' Display progress for each file as it is checked ' ,
)
2019-12-05 00:07:00 +00:00
check_group . add_argument (
' --repair ' ,
dest = ' repair ' ,
default = False ,
action = ' store_true ' ,
2022-05-29 02:29:33 +00:00
help = ' Attempt to repair any inconsistencies found (for interactive use) ' ,
2019-12-05 00:07:00 +00:00
)
2019-09-19 18:43:53 +00:00
check_group . add_argument (
' --only ' ,
metavar = ' CHECK ' ,
choices = ( ' repository ' , ' archives ' , ' data ' , ' extract ' ) ,
dest = ' only ' ,
action = ' append ' ,
2022-05-28 21:42:19 +00:00
help = ' Run a particular consistency check (repository, archives, data, or extract) instead of configured checks (subject to configured frequency, can specify flag multiple times) ' ,
2019-09-19 18:43:53 +00:00
)
2022-05-29 02:29:33 +00:00
check_group . add_argument (
' --force ' ,
default = False ,
action = ' store_true ' ,
help = ' Ignore configured check frequencies and run checks unconditionally ' ,
)
2019-06-23 04:32:27 +00:00
check_group . add_argument ( ' -h ' , ' --help ' , action = ' help ' , help = ' Show this help message and exit ' )
extract_parser = subparsers . add_parser (
' extract ' ,
aliases = SUBPARSER_ALIASES [ ' extract ' ] ,
2019-10-31 19:57:36 +00:00
help = ' Extract files from a named archive to the current directory ' ,
2019-06-23 04:32:27 +00:00
description = ' Extract a named archive to the current directory ' ,
add_help = False ,
)
extract_group = extract_parser . add_argument_group ( ' extract arguments ' )
extract_group . add_argument (
' --repository ' ,
2019-06-25 17:46:55 +00:00
help = ' Path of repository to extract, defaults to the configured repository if there is only one ' ,
2019-06-23 04:32:27 +00:00
)
2020-01-30 00:59:02 +00:00
extract_group . add_argument (
' --archive ' , help = ' Name of archive to extract (or " latest " ) ' , required = True
)
2019-06-23 04:32:27 +00:00
extract_group . add_argument (
2019-11-01 17:00:26 +00:00
' --path ' ,
2019-06-23 04:32:27 +00:00
' --restore-path ' ,
2019-10-31 19:57:36 +00:00
metavar = ' PATH ' ,
2019-06-23 04:32:27 +00:00
nargs = ' + ' ,
2019-11-01 17:00:26 +00:00
dest = ' paths ' ,
help = ' Paths to extract from archive, defaults to the entire archive ' ,
)
extract_group . add_argument (
' --destination ' ,
metavar = ' PATH ' ,
dest = ' destination ' ,
help = ' Directory to extract files into, defaults to the current directory ' ,
2019-06-23 04:32:27 +00:00
)
2020-06-06 21:57:14 +00:00
extract_group . add_argument (
' --strip-components ' ,
2023-03-09 18:09:16 +00:00
type = lambda number : number if number == ' all ' else int ( number ) ,
2020-06-06 21:57:14 +00:00
metavar = ' NUMBER ' ,
2023-03-09 18:09:16 +00:00
help = ' Number of leading path components to remove from each extracted path or " all " to strip all leading path components. Skip paths with fewer elements ' ,
2020-06-06 21:57:14 +00:00
)
2019-06-23 04:32:27 +00:00
extract_group . add_argument (
' --progress ' ,
dest = ' progress ' ,
default = False ,
action = ' store_true ' ,
2020-01-24 19:27:16 +00:00
help = ' Display progress for each file as it is extracted ' ,
2019-06-23 04:32:27 +00:00
)
extract_group . add_argument (
' -h ' , ' --help ' , action = ' help ' , help = ' Show this help message and exit '
)
2020-07-23 04:53:55 +00:00
export_tar_parser = subparsers . add_parser (
' export-tar ' ,
aliases = SUBPARSER_ALIASES [ ' export-tar ' ] ,
help = ' Export an archive to a tar-formatted file or stream ' ,
description = ' Export an archive to a tar-formatted file or stream ' ,
add_help = False ,
)
export_tar_group = export_tar_parser . add_argument_group ( ' export-tar arguments ' )
export_tar_group . add_argument (
' --repository ' ,
help = ' Path of repository to export from, defaults to the configured repository if there is only one ' ,
)
export_tar_group . add_argument (
' --archive ' , help = ' Name of archive to export (or " latest " ) ' , required = True
)
export_tar_group . add_argument (
' --path ' ,
metavar = ' PATH ' ,
nargs = ' + ' ,
dest = ' paths ' ,
help = ' Paths to export from archive, defaults to the entire archive ' ,
)
export_tar_group . add_argument (
' --destination ' ,
metavar = ' PATH ' ,
dest = ' destination ' ,
2022-08-21 21:25:16 +00:00
help = ' Path to destination export tar file, or " - " for stdout (but be careful about dirtying output with --verbosity or --list) ' ,
2020-07-23 04:53:55 +00:00
required = True ,
)
export_tar_group . add_argument (
' --tar-filter ' , help = ' Name of filter program to pipe data through '
)
export_tar_group . add_argument (
2022-08-21 21:25:16 +00:00
' --list ' , ' --files ' , dest = ' list_files ' , action = ' store_true ' , help = ' Show per-file details '
2020-07-23 04:53:55 +00:00
)
export_tar_group . add_argument (
' --strip-components ' ,
type = int ,
metavar = ' NUMBER ' ,
dest = ' strip_components ' ,
help = ' Number of leading path components to remove from each exported path. Skip paths with fewer elements ' ,
)
export_tar_group . add_argument (
' -h ' , ' --help ' , action = ' help ' , help = ' Show this help message and exit '
)
2019-11-25 22:56:20 +00:00
mount_parser = subparsers . add_parser (
' mount ' ,
aliases = SUBPARSER_ALIASES [ ' mount ' ] ,
help = ' Mount files from a named archive as a FUSE filesystem ' ,
description = ' Mount a named archive as a FUSE filesystem ' ,
add_help = False ,
)
mount_group = mount_parser . add_argument_group ( ' mount arguments ' )
mount_group . add_argument (
' --repository ' ,
help = ' Path of repository to use, defaults to the configured repository if there is only one ' ,
)
2020-01-30 00:59:02 +00:00
mount_group . add_argument ( ' --archive ' , help = ' Name of archive to mount (or " latest " ) ' )
2019-11-25 22:56:20 +00:00
mount_group . add_argument (
' --mount-point ' ,
metavar = ' PATH ' ,
dest = ' mount_point ' ,
help = ' Path where filesystem is to be mounted ' ,
required = True ,
)
mount_group . add_argument (
' --path ' ,
metavar = ' PATH ' ,
nargs = ' + ' ,
dest = ' paths ' ,
help = ' Paths to mount from archive, defaults to the entire archive ' ,
)
mount_group . add_argument (
' --foreground ' ,
dest = ' foreground ' ,
default = False ,
action = ' store_true ' ,
help = ' Stay in foreground until ctrl-C is pressed ' ,
)
mount_group . add_argument ( ' --options ' , dest = ' options ' , help = ' Extra Borg mount options ' )
mount_group . add_argument ( ' -h ' , ' --help ' , action = ' help ' , help = ' Show this help message and exit ' )
umount_parser = subparsers . add_parser (
' umount ' ,
aliases = SUBPARSER_ALIASES [ ' umount ' ] ,
help = ' Unmount a FUSE filesystem that was mounted with " borgmatic mount " ' ,
description = ' Unmount a mounted FUSE filesystem ' ,
add_help = False ,
)
umount_group = umount_parser . add_argument_group ( ' umount arguments ' )
umount_group . add_argument (
' --mount-point ' ,
metavar = ' PATH ' ,
dest = ' mount_point ' ,
help = ' Path of filesystem to unmount ' ,
required = True ,
)
umount_group . add_argument ( ' -h ' , ' --help ' , action = ' help ' , help = ' Show this help message and exit ' )
2019-10-31 19:57:36 +00:00
restore_parser = subparsers . add_parser (
' restore ' ,
aliases = SUBPARSER_ALIASES [ ' restore ' ] ,
help = ' Restore database dumps from a named archive ' ,
description = ' Restore database dumps from a named archive. (To extract files instead, use " borgmatic extract " .) ' ,
add_help = False ,
)
restore_group = restore_parser . add_argument_group ( ' restore arguments ' )
restore_group . add_argument (
' --repository ' ,
help = ' Path of repository to restore from, defaults to the configured repository if there is only one ' ,
)
2020-01-30 00:59:02 +00:00
restore_group . add_argument (
' --archive ' , help = ' Name of archive to restore from (or " latest " ) ' , required = True
)
2019-10-31 19:57:36 +00:00
restore_group . add_argument (
' --database ' ,
metavar = ' NAME ' ,
nargs = ' + ' ,
dest = ' databases ' ,
2023-03-07 22:08:35 +00:00
help = " Names of databases to restore from archive, defaults to all databases. Note that any databases to restore must be defined in borgmatic ' s configuration " ,
2019-10-31 19:57:36 +00:00
)
restore_group . add_argument (
' -h ' , ' --help ' , action = ' help ' , help = ' Show this help message and exit '
)
2022-08-15 22:04:40 +00:00
rlist_parser = subparsers . add_parser (
' rlist ' ,
aliases = SUBPARSER_ALIASES [ ' rlist ' ] ,
help = ' List repository ' ,
description = ' List the archives in a repository ' ,
add_help = False ,
)
rlist_group = rlist_parser . add_argument_group ( ' rlist arguments ' )
rlist_group . add_argument (
' --repository ' , help = ' Path of repository to list, defaults to the configured repositories ' ,
)
rlist_group . add_argument (
' --short ' , default = False , action = ' store_true ' , help = ' Output only archive names '
)
rlist_group . add_argument ( ' --format ' , help = ' Format for archive listing ' )
rlist_group . add_argument (
' --json ' , default = False , action = ' store_true ' , help = ' Output results as JSON '
)
rlist_group . add_argument (
' -P ' , ' --prefix ' , help = ' Only list archive names starting with this prefix '
)
rlist_group . add_argument (
2022-10-04 05:50:37 +00:00
' -a ' ,
' --match-archives ' ,
' --glob-archives ' ,
metavar = ' PATTERN ' ,
help = ' Only list archive names matching this pattern ' ,
2022-08-15 22:04:40 +00:00
)
rlist_group . add_argument (
' --sort-by ' , metavar = ' KEYS ' , help = ' Comma-separated list of sorting keys '
)
rlist_group . add_argument (
' --first ' , metavar = ' N ' , help = ' List first N archives after other filters are applied '
)
rlist_group . add_argument (
' --last ' , metavar = ' N ' , help = ' List last N archives after other filters are applied '
)
rlist_group . add_argument ( ' -h ' , ' --help ' , action = ' help ' , help = ' Show this help message and exit ' )
2019-06-23 04:32:27 +00:00
list_parser = subparsers . add_parser (
' list ' ,
aliases = SUBPARSER_ALIASES [ ' list ' ] ,
2022-08-15 22:04:40 +00:00
help = ' List archive ' ,
description = ' List the files in an archive or search for a file across archives ' ,
2019-06-23 04:32:27 +00:00
add_help = False ,
)
list_group = list_parser . add_argument_group ( ' list arguments ' )
list_group . add_argument (
2022-08-15 22:04:40 +00:00
' --repository ' ,
help = ' Path of repository containing archive to list, defaults to the configured repositories ' ,
2019-06-23 04:32:27 +00:00
)
2022-08-15 22:04:40 +00:00
list_group . add_argument ( ' --archive ' , help = ' Name of the archive to list (or " latest " ) ' )
2019-12-08 22:07:02 +00:00
list_group . add_argument (
' --path ' ,
metavar = ' PATH ' ,
nargs = ' + ' ,
dest = ' paths ' ,
2022-06-03 22:12:14 +00:00
help = ' Paths or patterns to list from a single selected archive (via " --archive " ), defaults to listing the entire archive ' ,
)
list_group . add_argument (
' --find ' ,
metavar = ' PATH ' ,
nargs = ' + ' ,
dest = ' find_paths ' ,
help = ' Partial paths or patterns to search for and list across multiple archives ' ,
2019-12-08 22:07:02 +00:00
)
2019-06-23 04:32:27 +00:00
list_group . add_argument (
2022-08-15 22:04:40 +00:00
' --short ' , default = False , action = ' store_true ' , help = ' Output only path names '
2019-06-25 17:18:30 +00:00
)
list_group . add_argument ( ' --format ' , help = ' Format for file listing ' )
list_group . add_argument (
' --json ' , default = False , action = ' store_true ' , help = ' Output results as JSON '
)
list_group . add_argument (
' -P ' , ' --prefix ' , help = ' Only list archive names starting with this prefix '
)
list_group . add_argument (
2022-10-04 05:50:37 +00:00
' -a ' ,
' --match-archives ' ,
' --glob-archives ' ,
metavar = ' PATTERN ' ,
help = ' Only list archive names matching this pattern ' ,
2019-06-25 17:18:30 +00:00
)
2019-10-13 22:58:11 +00:00
list_group . add_argument (
' --successful ' ,
2022-06-03 22:12:14 +00:00
default = True ,
2019-10-13 22:58:11 +00:00
action = ' store_true ' ,
2022-08-15 22:40:28 +00:00
help = ' Deprecated; no effect. Newer versions of Borg shows successful (non-checkpoint) archives by default. ' ,
2019-10-13 22:58:11 +00:00
)
2019-06-25 17:18:30 +00:00
list_group . add_argument (
' --sort-by ' , metavar = ' KEYS ' , help = ' Comma-separated list of sorting keys '
)
list_group . add_argument (
' --first ' , metavar = ' N ' , help = ' List first N archives after other filters are applied '
)
list_group . add_argument (
2019-10-13 21:46:28 +00:00
' --last ' , metavar = ' N ' , help = ' List last N archives after other filters are applied '
2019-06-25 17:18:30 +00:00
)
list_group . add_argument (
' -e ' , ' --exclude ' , metavar = ' PATTERN ' , help = ' Exclude paths matching the pattern '
)
list_group . add_argument (
' --exclude-from ' , metavar = ' FILENAME ' , help = ' Exclude paths from exclude file, one per line '
)
list_group . add_argument ( ' --pattern ' , help = ' Include or exclude paths matching a pattern ' )
list_group . add_argument (
2019-10-23 05:42:36 +00:00
' --patterns-from ' ,
2019-06-25 17:18:30 +00:00
metavar = ' FILENAME ' ,
help = ' Include or exclude paths matching patterns from pattern file, one per line ' ,
2019-06-23 04:32:27 +00:00
)
list_group . add_argument ( ' -h ' , ' --help ' , action = ' help ' , help = ' Show this help message and exit ' )
2022-08-13 06:06:56 +00:00
rinfo_parser = subparsers . add_parser (
' rinfo ' ,
aliases = SUBPARSER_ALIASES [ ' rinfo ' ] ,
help = ' Show repository summary information such as disk space used ' ,
description = ' Show repository summary information such as disk space used ' ,
add_help = False ,
)
rinfo_group = rinfo_parser . add_argument_group ( ' rinfo arguments ' )
rinfo_group . add_argument (
' --repository ' ,
help = ' Path of repository to show info for, defaults to the configured repository if there is only one ' ,
)
rinfo_group . add_argument (
' --json ' , dest = ' json ' , default = False , action = ' store_true ' , help = ' Output results as JSON '
)
rinfo_group . add_argument ( ' -h ' , ' --help ' , action = ' help ' , help = ' Show this help message and exit ' )
2019-06-23 04:32:27 +00:00
info_parser = subparsers . add_parser (
' info ' ,
aliases = SUBPARSER_ALIASES [ ' info ' ] ,
2022-08-13 06:06:56 +00:00
help = ' Show archive summary information such as disk space used ' ,
description = ' Show archive summary information such as disk space used ' ,
2019-06-23 04:32:27 +00:00
add_help = False ,
)
info_group = info_parser . add_argument_group ( ' info arguments ' )
2019-06-25 17:46:55 +00:00
info_group . add_argument (
' --repository ' ,
2022-08-13 06:06:56 +00:00
help = ' Path of repository containing archive to show info for, defaults to the configured repository if there is only one ' ,
2019-06-25 17:46:55 +00:00
)
2020-01-30 00:59:02 +00:00
info_group . add_argument ( ' --archive ' , help = ' Name of archive to show info for (or " latest " ) ' )
2019-06-23 04:32:27 +00:00
info_group . add_argument (
' --json ' , dest = ' json ' , default = False , action = ' store_true ' , help = ' Output results as JSON '
)
2019-06-25 17:46:55 +00:00
info_group . add_argument (
' -P ' , ' --prefix ' , help = ' Only show info for archive names starting with this prefix '
)
info_group . add_argument (
' -a ' ,
2022-10-04 05:50:37 +00:00
' --match-archives ' ,
2019-06-25 17:46:55 +00:00
' --glob-archives ' ,
2022-10-04 05:50:37 +00:00
metavar = ' PATTERN ' ,
help = ' Only show info for archive names matching this pattern ' ,
2019-06-25 17:46:55 +00:00
)
info_group . add_argument (
' --sort-by ' , metavar = ' KEYS ' , help = ' Comma-separated list of sorting keys '
)
info_group . add_argument (
' --first ' ,
metavar = ' N ' ,
help = ' Show info for first N archives after other filters are applied ' ,
)
info_group . add_argument (
2020-10-11 22:04:15 +00:00
' --last ' , metavar = ' N ' , help = ' Show info for last N archives after other filters are applied '
2019-06-25 17:46:55 +00:00
)
2019-06-23 04:32:27 +00:00
info_group . add_argument ( ' -h ' , ' --help ' , action = ' help ' , help = ' Show this help message and exit ' )
2022-10-04 20:42:18 +00:00
break_lock_parser = subparsers . add_parser (
' break-lock ' ,
aliases = SUBPARSER_ALIASES [ ' break-lock ' ] ,
help = ' Break the repository and cache locks left behind by Borg aborting ' ,
description = ' Break Borg repository and cache locks left behind by Borg aborting ' ,
add_help = False ,
)
break_lock_group = break_lock_parser . add_argument_group ( ' break-lock arguments ' )
break_lock_group . add_argument (
' --repository ' ,
help = ' Path of repository to break the lock for, defaults to the configured repository if there is only one ' ,
)
2022-10-12 17:52:32 +00:00
break_lock_group . add_argument (
' -h ' , ' --help ' , action = ' help ' , help = ' Show this help message and exit '
)
2022-10-04 20:42:18 +00:00
2021-06-18 03:41:44 +00:00
borg_parser = subparsers . add_parser (
' borg ' ,
aliases = SUBPARSER_ALIASES [ ' borg ' ] ,
help = ' Run an arbitrary Borg command ' ,
2023-03-07 22:08:35 +00:00
description = " Run an arbitrary Borg command based on borgmatic ' s configuration " ,
2021-06-18 03:41:44 +00:00
add_help = False ,
)
borg_group = borg_parser . add_argument_group ( ' borg arguments ' )
borg_group . add_argument (
' --repository ' ,
help = ' Path of repository to pass to Borg, defaults to the configured repositories ' ,
)
borg_group . add_argument ( ' --archive ' , help = ' Name of archive to pass to Borg (or " latest " ) ' )
borg_group . add_argument (
' -- ' ,
metavar = ' OPTION ' ,
dest = ' options ' ,
nargs = ' + ' ,
help = ' Options to pass to Borg, command first ( " create " , " list " , etc). " -- " is optional. To specify the repository or the archive, you must use --repository or --archive instead of providing them here. ' ,
)
borg_group . add_argument ( ' -h ' , ' --help ' , action = ' help ' , help = ' Show this help message and exit ' )
2022-05-26 17:27:53 +00:00
return top_level_parser , subparsers
def parse_arguments ( * unparsed_arguments ) :
'''
Given command - line arguments with which this script was invoked , parse the arguments and return
them as a dict mapping from subparser name ( or " global " ) to an argparse . Namespace instance .
'''
top_level_parser , subparsers = make_parsers ( )
2021-06-18 03:41:44 +00:00
arguments , remaining_arguments = parse_subparser_arguments (
unparsed_arguments , subparsers . choices
)
arguments [ ' global ' ] = top_level_parser . parse_args ( remaining_arguments )
2019-06-23 04:32:27 +00:00
if arguments [ ' global ' ] . excludes_filename :
raise ValueError (
2022-08-17 22:36:19 +00:00
' The --excludes flag has been replaced with exclude_patterns in configuration. '
2019-06-23 04:32:27 +00:00
)
2023-02-27 01:05:56 +00:00
if ' create ' in arguments and arguments [ ' create ' ] . list_files and arguments [ ' create ' ] . progress :
raise ValueError (
' With the create action, only one of --list (--files) and --progress flags can be used. '
)
2019-06-23 04:32:27 +00:00
if (
2022-08-13 06:06:56 +00:00
( ' list ' in arguments and ' rinfo ' in arguments and arguments [ ' list ' ] . json )
or ( ' list ' in arguments and ' info ' in arguments and arguments [ ' list ' ] . json )
or ( ' rinfo ' in arguments and ' info ' in arguments and arguments [ ' rinfo ' ] . json )
2019-06-23 04:32:27 +00:00
) :
2022-08-17 22:36:19 +00:00
raise ValueError ( ' With the --json flag, multiple actions cannot be used together. ' )
2022-08-12 21:53:20 +00:00
2022-08-19 06:06:51 +00:00
if (
' transfer ' in arguments
and arguments [ ' transfer ' ] . archive
2022-10-04 05:50:37 +00:00
and arguments [ ' transfer ' ] . match_archives
2022-08-19 06:06:51 +00:00
) :
raise ValueError (
' With the transfer action, only one of --archive and --glob-archives flags can be used. '
)
2022-08-17 22:36:19 +00:00
if ' info ' in arguments and (
( arguments [ ' info ' ] . archive and arguments [ ' info ' ] . prefix )
2022-10-04 05:50:37 +00:00
or ( arguments [ ' info ' ] . archive and arguments [ ' info ' ] . match_archives )
or ( arguments [ ' info ' ] . prefix and arguments [ ' info ' ] . match_archives )
2022-08-17 22:36:19 +00:00
) :
2022-08-12 21:53:20 +00:00
raise ValueError (
2022-10-04 05:50:37 +00:00
' With the info action, only one of --archive, --prefix, or --match-archives flags can be used. '
2022-08-12 21:53:20 +00:00
)
2019-06-23 04:32:27 +00:00
return arguments