def test_get_default_config_paths_includes_absolute_user_config_path(): flexmock(module.os, environ={ 'XDG_CONFIG_HOME': None, 'HOME': '/home/user' }) config_paths = module.get_default_config_paths() assert '/home/user/.config/borgmatic/config.yaml' in config_paths
def test_get_default_config_paths_prefers_xdg_config_home_for_user_config_path( ): flexmock(module.os, environ={ 'XDG_CONFIG_HOME': '/home/user/.etc', 'HOME': '/home/user' }) config_paths = module.get_default_config_paths() assert '/home/user/.etc/borgmatic/config.yaml' in config_paths
def parse_arguments(*arguments): ''' Given command-line arguments with which this script was invoked, parse the arguments and return them as an ArgumentParser instance. ''' config_paths = collect.get_default_config_paths() parser = ArgumentParser(description='Validate borgmatic configuration file(s).') parser.add_argument( '-c', '--config', nargs='+', dest='config_paths', default=config_paths, help='Configuration filenames or directories, defaults to: {}'.format( ' '.join(config_paths) ), ) return parser.parse_args(arguments)
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. ''' config_paths = collect.get_default_config_paths() global_parser = ArgumentParser(add_help=False) global_group = global_parser.add_argument_group('global arguments') global_group.add_argument( '-c', '--config', nargs='*', dest='config_paths', default=config_paths, help='Configuration filenames or directories, defaults to: {}'.format( ' '.join(config_paths)), ) 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, choices=range(0, 3), default=0, help= 'Display verbose progress to the console (from none to lots: 0, 1, or 2)', ) global_group.add_argument( '--syslog-verbosity', type=int, choices=range(0, 3), default=0, help= 'Display verbose progress to syslog (from none to lots: 0, 1, or 2). Ignored when console is interactive', ) 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=''' A simple wrapper script for the Borg backup software that creates and prunes backups. If none of the action options are given, then borgmatic defaults to: prune, create, and check archives. ''', parents=[global_parser], ) subparsers = top_level_parser.add_subparsers( title='actions', metavar='', help= 'Specify zero or more actions. Defaults to prune, create, and check. Use --help with action for details:', ) init_parser = subparsers.add_parser( 'init', aliases=SUBPARSER_ALIASES['init'], help='Initialize an empty Borg repository', description='Initialize an empty Borg repository', add_help=False, ) init_group = init_parser.add_argument_group('init arguments') init_group.add_argument( '-e', '--encryption', dest='encryption_mode', help='Borg repository encryption mode', required=True, ) init_group.add_argument( '--append-only', dest='append_only', action='store_true', help='Create an append-only repository', ) init_group.add_argument( '--storage-quota', dest='storage_quota', help='Create a repository with a fixed storage quota', ) init_group.add_argument('-h', '--help', action='help', help='Show this help message and exit') prune_parser = subparsers.add_parser( 'prune', aliases=SUBPARSER_ALIASES['prune'], help='Prune archives according to the retention policy', description='Prune archives according to the retention policy', add_help=False, ) prune_group = prune_parser.add_argument_group('prune arguments') prune_group.add_argument( '--stats', dest='stats', default=False, action='store_true', help='Display statistics of archive', ) prune_group.add_argument('-h', '--help', action='help', help='Show this help message and exit') create_parser = subparsers.add_parser( 'create', aliases=SUBPARSER_ALIASES['create'], help='Create archives (actually perform backups)', description='Create archives (actually perform backups)', add_help=False, ) create_group = create_parser.add_argument_group('create arguments') create_group.add_argument( '--progress', dest='progress', default=False, action='store_true', help='Display progress for each file as it is processed', ) create_group.add_argument( '--stats', dest='stats', default=False, action='store_true', help='Display statistics of archive', ) 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') check_group.add_argument( '--only', metavar='CHECK', choices=('repository', 'archives', 'data', 'extract'), dest='only', action='append', help= 'Run a particular consistency check (repository, archives, data, or extract) instead of configured checks; can specify flag multiple times', ) 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'], help='Extract a named archive to the current directory', 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', help= 'Path of repository to extract, defaults to the configured repository if there is only one', ) extract_group.add_argument('--archive', help='Name of archive to operate on', required=True) extract_group.add_argument( '--restore-path', nargs='+', dest='restore_paths', help='Paths to restore from archive, defaults to the entire archive', ) extract_group.add_argument( '--progress', dest='progress', default=False, action='store_true', help='Display progress for each file as it is processed', ) extract_group.add_argument('-h', '--help', action='help', help='Show this help message and exit') list_parser = subparsers.add_parser( 'list', aliases=SUBPARSER_ALIASES['list'], help='List archives', description='List archives or the contents of an archive', add_help=False, ) list_group = list_parser.add_argument_group('list arguments') list_group.add_argument( '--repository', help= 'Path of repository to list, defaults to the configured repository if there is only one', ) list_group.add_argument('--archive', help='Name of archive to list') list_group.add_argument('--short', default=False, action='store_true', help='Output only archive or path names') 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('-a', '--glob-archives', metavar='GLOB', help='Only list archive names matching this glob') list_group.add_argument( '--successful', default=False, action='store_true', help='Only list archive names of successful (non-checkpoint) backups', ) 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( '--last', metavar='N', help='List last N archives after other filters are applied') 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( '--patterns-from', metavar='FILENAME', help= 'Include or exclude paths matching patterns from pattern file, one per line', ) list_group.add_argument('-h', '--help', action='help', help='Show this help message and exit') info_parser = subparsers.add_parser( 'info', aliases=SUBPARSER_ALIASES['info'], help='Display summary information on archives', description='Display summary information on archives', add_help=False, ) info_group = info_parser.add_argument_group('info arguments') info_group.add_argument( '--repository', help= 'Path of repository to show info for, defaults to the configured repository if there is only one', ) info_group.add_argument('--archive', help='Name of archive to show info for') info_group.add_argument('--json', dest='json', default=False, action='store_true', help='Output results as JSON') info_group.add_argument( '-P', '--prefix', help='Only show info for archive names starting with this prefix') info_group.add_argument( '-a', '--glob-archives', metavar='GLOB', help='Only show info for archive names matching this glob', ) 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( '--last', metavar='N', help='Show info for first N archives after other filters are applied') info_group.add_argument('-h', '--help', action='help', help='Show this help message and exit') arguments = parse_subparser_arguments(unparsed_arguments, subparsers) arguments['global'] = parse_global_arguments(unparsed_arguments, top_level_parser, subparsers) if arguments['global'].excludes_filename: raise ValueError( 'The --excludes option has been replaced with exclude_patterns in configuration' ) if 'init' in arguments and arguments['global'].dry_run: raise ValueError( 'The init action cannot be used with the --dry-run option') if 'list' in arguments and arguments['list'].glob_archives and arguments[ 'list'].successful: raise ValueError( 'The --glob-archives and --successful options cannot be used together' ) if ('list' in arguments and 'info' in arguments and arguments['list'].json and arguments['info'].json): raise ValueError( 'With the --json option, list and info actions cannot be used together' ) return arguments
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. ''' config_paths = collect.get_default_config_paths(expand_home=True) unexpanded_config_paths = collect.get_default_config_paths( expand_home=False) global_parser = ArgumentParser(add_help=False) global_group = global_parser.add_argument_group('global arguments') global_group.add_argument( '-c', '--config', nargs='*', dest='config_paths', default=config_paths, help='Configuration filenames or directories, defaults to: {}'.format( ' '.join(unexpanded_config_paths)), ) 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, choices=range(-1, 3), default=0, help= 'Display verbose progress to the console (from only errors to very verbose: -1, 0, 1, or 2)', ) global_group.add_argument( '--syslog-verbosity', type=int, choices=range(-1, 3), default=0, 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', ) global_group.add_argument( '--log-file-verbosity', type=int, choices=range(-1, 3), default=0, 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', ) global_group.add_argument( '--monitoring-verbosity', type=int, choices=range(-1, 3), default=0, help= 'Log verbose progress to monitoring integrations that support logging (from only errors to very verbose: -1, 0, 1, or 2)', ) global_group.add_argument( '--log-file', type=str, default=None, help='Write log messages to this file instead of syslog', ) global_group.add_argument( '--override', metavar='SECTION.OPTION=VALUE', nargs='+', dest='overrides', help= 'One or more configuration file options to override with specified values', ) 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=''' Simple, configuration-driven backup software for servers and workstations. If none of the action options are given, then borgmatic defaults to: prune, create, and check archives. ''', parents=[global_parser], ) subparsers = top_level_parser.add_subparsers( title='actions', metavar='', help= 'Specify zero or more actions. Defaults to prune, create, and check. Use --help with action for details:', ) init_parser = subparsers.add_parser( 'init', aliases=SUBPARSER_ALIASES['init'], help='Initialize an empty Borg repository', description='Initialize an empty Borg repository', add_help=False, ) init_group = init_parser.add_argument_group('init arguments') init_group.add_argument( '-e', '--encryption', dest='encryption_mode', help='Borg repository encryption mode', required=True, ) init_group.add_argument( '--append-only', dest='append_only', action='store_true', help='Create an append-only repository', ) init_group.add_argument( '--storage-quota', dest='storage_quota', help='Create a repository with a fixed storage quota', ) init_group.add_argument('-h', '--help', action='help', help='Show this help message and exit') prune_parser = subparsers.add_parser( 'prune', aliases=SUBPARSER_ALIASES['prune'], help='Prune archives according to the retention policy', description='Prune archives according to the retention policy', add_help=False, ) prune_group = prune_parser.add_argument_group('prune arguments') prune_group.add_argument( '--stats', dest='stats', default=False, action='store_true', help='Display statistics of archive', ) prune_group.add_argument('--files', dest='files', default=False, action='store_true', help='Show per-file details') prune_group.add_argument('-h', '--help', action='help', help='Show this help message and exit') create_parser = subparsers.add_parser( 'create', aliases=SUBPARSER_ALIASES['create'], help='Create archives (actually perform backups)', description='Create archives (actually perform backups)', add_help=False, ) create_group = create_parser.add_argument_group('create arguments') create_group.add_argument( '--progress', dest='progress', default=False, action='store_true', help='Display progress for each file as it is backed up', ) create_group.add_argument( '--stats', dest='stats', default=False, action='store_true', help='Display statistics of archive', ) create_group.add_argument('--files', dest='files', default=False, action='store_true', help='Show per-file details') 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') check_group.add_argument( '--progress', dest='progress', default=False, action='store_true', help='Display progress for each file as it is checked', ) check_group.add_argument( '--repair', dest='repair', default=False, action='store_true', help= 'Attempt to repair any inconsistencies found (experimental and only for interactive use)', ) check_group.add_argument( '--only', metavar='CHECK', choices=('repository', 'archives', 'data', 'extract'), dest='only', action='append', help= 'Run a particular consistency check (repository, archives, data, or extract) instead of configured checks; can specify flag multiple times', ) 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'], help='Extract files from a named archive to the current directory', 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', help= 'Path of repository to extract, defaults to the configured repository if there is only one', ) extract_group.add_argument('--archive', help='Name of archive to extract (or "latest")', required=True) extract_group.add_argument( '--path', '--restore-path', metavar='PATH', nargs='+', 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', ) extract_group.add_argument( '--progress', dest='progress', default=False, action='store_true', help='Display progress for each file as it is extracted', ) extract_group.add_argument('-h', '--help', action='help', help='Show this help message and exit') 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', ) mount_group.add_argument('--archive', help='Name of archive to mount (or "latest")') 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') 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', ) restore_group.add_argument( '--archive', help='Name of archive to restore from (or "latest")', required=True) restore_group.add_argument( '--database', metavar='NAME', nargs='+', dest='databases', 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', ) restore_group.add_argument('-h', '--help', action='help', help='Show this help message and exit') list_parser = subparsers.add_parser( 'list', aliases=SUBPARSER_ALIASES['list'], help='List archives', description='List archives or the contents of an archive', add_help=False, ) list_group = list_parser.add_argument_group('list arguments') list_group.add_argument( '--repository', help= 'Path of repository to list, defaults to the configured repository if there is only one', ) list_group.add_argument('--archive', help='Name of archive to list (or "latest")') list_group.add_argument( '--path', metavar='PATH', nargs='+', dest='paths', help='Paths to list from archive, defaults to the entire archive', ) list_group.add_argument('--short', default=False, action='store_true', help='Output only archive or path names') 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('-a', '--glob-archives', metavar='GLOB', help='Only list archive names matching this glob') list_group.add_argument( '--successful', default=False, action='store_true', help='Only list archive names of successful (non-checkpoint) backups', ) 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( '--last', metavar='N', help='List last N archives after other filters are applied') 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( '--patterns-from', metavar='FILENAME', help= 'Include or exclude paths matching patterns from pattern file, one per line', ) list_group.add_argument('-h', '--help', action='help', help='Show this help message and exit') info_parser = subparsers.add_parser( 'info', aliases=SUBPARSER_ALIASES['info'], help='Display summary information on archives', description='Display summary information on archives', add_help=False, ) info_group = info_parser.add_argument_group('info arguments') info_group.add_argument( '--repository', help= 'Path of repository to show info for, defaults to the configured repository if there is only one', ) info_group.add_argument( '--archive', help='Name of archive to show info for (or "latest")') info_group.add_argument('--json', dest='json', default=False, action='store_true', help='Output results as JSON') info_group.add_argument( '-P', '--prefix', help='Only show info for archive names starting with this prefix') info_group.add_argument( '-a', '--glob-archives', metavar='GLOB', help='Only show info for archive names matching this glob', ) 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( '--last', metavar='N', help='Show info for first N archives after other filters are applied') info_group.add_argument('-h', '--help', action='help', help='Show this help message and exit') arguments = parse_subparser_arguments(unparsed_arguments, subparsers) arguments['global'] = parse_global_arguments(unparsed_arguments, top_level_parser, subparsers) if arguments['global'].excludes_filename: raise ValueError( 'The --excludes option has been replaced with exclude_patterns in configuration' ) if 'init' in arguments and arguments['global'].dry_run: raise ValueError( 'The init action cannot be used with the --dry-run option') if 'list' in arguments and arguments['list'].glob_archives and arguments[ 'list'].successful: raise ValueError( 'The --glob-archives and --successful options cannot be used together' ) if ('list' in arguments and 'info' in arguments and arguments['list'].json and arguments['info'].json): raise ValueError( 'With the --json option, list and info actions cannot be used together' ) return arguments
def parse_arguments(*arguments): ''' Given command-line arguments with which this script was invoked, parse the arguments and return them as an argparse.ArgumentParser instance. ''' config_paths = collect.get_default_config_paths() parser = ArgumentParser(description=''' A simple wrapper script for the Borg backup software that creates and prunes backups. If none of the --prune, --create, or --check options are given, then borgmatic defaults to all three: prune, create, and check archives. ''') parser.add_argument( '-c', '--config', nargs='+', dest='config_paths', default=config_paths, help='Configuration filenames or directories, defaults to: {}'.format( ' '.join(config_paths)), ) parser.add_argument( '--excludes', dest='excludes_filename', help='Deprecated in favor of exclude_patterns within configuration', ) parser.add_argument('-I', '--init', dest='init', action='store_true', help='Initialize an empty Borg repository') parser.add_argument( '-e', '--encryption', dest='encryption_mode', help='Borg repository encryption mode (for use with --init)', ) parser.add_argument( '--append-only', dest='append_only', action='store_true', help='Create an append-only repository (for use with --init)', ) parser.add_argument( '--storage-quota', dest='storage_quota', help= 'Create a repository with a fixed storage quota (for use with --init)', ) parser.add_argument( '-p', '--prune', dest='prune', action='store_true', help='Prune archives according to the retention policy', ) parser.add_argument( '-C', '--create', dest='create', action='store_true', help='Create archives (actually perform backups)', ) parser.add_argument('-k', '--check', dest='check', action='store_true', help='Check archives for consistency') parser.add_argument('-l', '--list', dest='list', action='store_true', help='List archives') parser.add_argument( '-i', '--info', dest='info', action='store_true', help='Display summary information on archives', ) parser.add_argument( '--progress', dest='progress', default=False, action='store_true', help= 'Display progress with --create option for each file as it is backed up', ) parser.add_argument( '--stats', dest='stats', default=False, action='store_true', help='Display statistics of archive with --create or --prune option', ) parser.add_argument( '--json', dest='json', default=False, action='store_true', help= 'Output results from the --create, --list, or --info options as json', ) parser.add_argument( '-n', '--dry-run', dest='dry_run', action='store_true', help= 'Go through the motions, but do not actually write to any repositories', ) parser.add_argument( '-v', '--verbosity', type=int, choices=range(0, 3), default=0, help='Display verbose progress (1 for some, 2 for lots)', ) parser.add_argument( '--version', dest='version', default=False, action='store_true', help='Display installed version number of borgmatic and exit', ) args = parser.parse_args(arguments) if args.excludes_filename: raise ValueError( 'The --excludes option has been replaced with exclude_patterns in configuration' ) if (args.encryption_mode or args.append_only or args.storage_quota) and not args.init: raise ValueError( 'The --encryption, --append-only, and --storage-quota options can only be used with the --init option' ) if args.init and args.dry_run: raise ValueError( 'The --init option cannot be used with the --dry-run option') if args.init and not args.encryption_mode: raise ValueError( 'The --encryption option is required with the --init option') if args.progress and not args.create: raise ValueError( 'The --progress option can only be used with the --create option') if args.stats and not (args.create or args.prune): raise ValueError( 'The --stats option can only be used with the --create or --prune options' ) if args.json and not (args.create or args.list or args.info): raise ValueError( 'The --json option can only be used with the --create, --list, or --info options' ) if args.json and args.list and args.info: raise ValueError( 'With the --json option, options --list and --info cannot be used together' ) # If any of the action flags are explicitly requested, leave them as-is. Otherwise, assume # defaults: Mutate the given arguments to enable the default actions. if args.init or args.prune or args.create or args.check or args.list or args.info: return args args.prune = True args.create = True args.check = True return args
def parse_arguments(*arguments): ''' Given command-line arguments with which this script was invoked, parse the arguments and return them as an ArgumentParser instance. ''' config_paths = collect.get_default_config_paths() parser = ArgumentParser(description=''' A simple wrapper script for the Borg backup software that creates and prunes backups. If none of the --prune, --create, or --check options are given, then borgmatic defaults to all three: prune, create, and check archives. ''') parser.add_argument( '-c', '--config', nargs='+', dest='config_paths', default=config_paths, help='Configuration filenames or directories, defaults to: {}'.format( ' '.join(config_paths)), ) parser.add_argument( '--excludes', dest='excludes_filename', help='Deprecated in favor of exclude_patterns within configuration', ) parser.add_argument( '-p', '--prune', dest='prune', action='store_true', help='Prune archives according to the retention policy', ) parser.add_argument( '-C', '--create', dest='create', action='store_true', help='Create archives (actually perform backups)', ) parser.add_argument( '-k', '--check', dest='check', action='store_true', help='Check archives for consistency', ) parser.add_argument( '-l', '--list', dest='list', action='store_true', help='List archives', ) parser.add_argument( '-i', '--info', dest='info', action='store_true', help='Display summary information on archives', ) parser.add_argument( '--json', dest='json', default=False, action='store_true', help='Output results from the --list option as json', ) parser.add_argument( '-n', '--dry-run', dest='dry_run', action='store_true', help= 'Go through the motions, but do not actually write to any repositories', ) parser.add_argument( '-v', '--verbosity', type=int, help='Display verbose progress (1 for some, 2 for lots)', ) args = parser.parse_args(arguments) if args.json and not (args.list or args.info): raise ValueError( 'The --json option can only be used with the --list or --info options' ) if args.json and args.list and args.info: raise ValueError( 'With the --json option, options --list and --info cannot be used together' ) # If any of the action flags are explicitly requested, leave them as-is. Otherwise, assume # defaults: Mutate the given arguments to enable the default actions. if args.prune or args.create or args.check or args.list or args.info: return args args.prune = True args.create = True args.check = True return args
def test_get_default_config_paths_includes_absolute_user_config_path(): flexmock(module.os, environ={'XDG_CONFIG_HOME': None, 'HOME': '/home/user'}) config_paths = module.get_default_config_paths() assert '/home/user/.config/borgmatic/config.yaml' in config_paths
def test_get_default_config_paths_prefers_xdg_config_home_for_user_config_path(): flexmock(module.os, environ={'XDG_CONFIG_HOME': '/home/user/.etc', 'HOME': '/home/user'}) config_paths = module.get_default_config_paths() assert '/home/user/.etc/borgmatic/config.yaml' in config_paths
def test_get_default_config_paths_does_not_expand_home_when_false(): flexmock(module.os, environ={'HOME': '/home/user'}) config_paths = module.get_default_config_paths(expand_home=False) assert '$HOME/.config/borgmatic/config.yaml' in config_paths
def parse_arguments(*arguments): ''' Given command-line arguments with which this script was invoked, parse the arguments and return them as an argparse.ArgumentParser instance. ''' config_paths = collect.get_default_config_paths() parser = ArgumentParser( description=''' A simple wrapper script for the Borg backup software that creates and prunes backups. If none of the action options are given, then borgmatic defaults to: prune, create, and check archives. ''', add_help=False, ) actions_group = parser.add_argument_group('actions') actions_group.add_argument( '-I', '--init', dest='init', action='store_true', help='Initialize an empty Borg repository' ) actions_group.add_argument( '-p', '--prune', dest='prune', action='store_true', help='Prune archives according to the retention policy', ) actions_group.add_argument( '-C', '--create', dest='create', action='store_true', help='Create archives (actually perform backups)', ) actions_group.add_argument( '-k', '--check', dest='check', action='store_true', help='Check archives for consistency' ) actions_group.add_argument( '-x', '--extract', dest='extract', action='store_true', help='Extract a named archive to the current directory', ) actions_group.add_argument( '-l', '--list', dest='list', action='store_true', help='List archives' ) actions_group.add_argument( '-i', '--info', dest='info', action='store_true', help='Display summary information on archives', ) init_group = parser.add_argument_group('options for --init') init_group.add_argument( '-e', '--encryption', dest='encryption_mode', help='Borg repository encryption mode' ) init_group.add_argument( '--append-only', dest='append_only', action='store_true', help='Create an append-only repository', ) init_group.add_argument( '--storage-quota', dest='storage_quota', help='Create a repository with a fixed storage quota', ) prune_group = parser.add_argument_group('options for --prune') stats_argument = prune_group.add_argument( '--stats', dest='stats', default=False, action='store_true', help='Display statistics of archive', ) create_group = parser.add_argument_group('options for --create') progress_argument = create_group.add_argument( '--progress', dest='progress', default=False, action='store_true', help='Display progress for each file as it is processed', ) create_group._group_actions.append(stats_argument) json_argument = create_group.add_argument( '--json', dest='json', default=False, action='store_true', help='Output results as JSON' ) extract_group = parser.add_argument_group('options for --extract') repository_argument = extract_group.add_argument( '--repository', help='Path of repository to use, defaults to the configured repository if there is only one', ) archive_argument = extract_group.add_argument('--archive', help='Name of archive to operate on') extract_group.add_argument( '--restore-path', nargs='+', dest='restore_paths', help='Paths to restore from archive, defaults to the entire archive', ) extract_group._group_actions.append(progress_argument) list_group = parser.add_argument_group('options for --list') list_group._group_actions.append(repository_argument) list_group._group_actions.append(archive_argument) list_group._group_actions.append(json_argument) info_group = parser.add_argument_group('options for --info') info_group._group_actions.append(json_argument) common_group = parser.add_argument_group('common options') common_group.add_argument( '-c', '--config', nargs='+', dest='config_paths', default=config_paths, help='Configuration filenames or directories, defaults to: {}'.format( ' '.join(config_paths) ), ) common_group.add_argument( '--excludes', dest='excludes_filename', help='Deprecated in favor of exclude_patterns within configuration', ) common_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', ) common_group.add_argument( '-v', '--verbosity', type=int, choices=range(0, 3), default=0, help='Display verbose progress (1 for some, 2 for lots)', ) common_group.add_argument( '--version', dest='version', default=False, action='store_true', help='Display installed version number of borgmatic and exit', ) common_group.add_argument('--help', action='help', help='Show this help information and exit') args = parser.parse_args(arguments) if args.excludes_filename: raise ValueError( 'The --excludes option has been replaced with exclude_patterns in configuration' ) if (args.encryption_mode or args.append_only or args.storage_quota) and not args.init: raise ValueError( 'The --encryption, --append-only, and --storage-quota options can only be used with the --init option' ) if args.init and args.dry_run: raise ValueError('The --init option cannot be used with the --dry-run option') if args.init and not args.encryption_mode: raise ValueError('The --encryption option is required with the --init option') if not args.extract: if not args.list: if args.repository: raise ValueError( 'The --repository option can only be used with the --extract and --list options' ) if args.archive: raise ValueError( 'The --archive option can only be used with the --extract and --list options' ) if args.restore_paths: raise ValueError('The --restore-path option can only be used with the --extract option') if args.extract and not args.archive: raise ValueError('The --archive option is required with the --extract option') if args.progress and not (args.create or args.extract): raise ValueError( 'The --progress option can only be used with the --create and --extract options' ) if args.json and not (args.create or args.list or args.info): raise ValueError( 'The --json option can only be used with the --create, --list, or --info options' ) if args.json and args.list and args.info: raise ValueError( 'With the --json option, options --list and --info cannot be used together' ) # If any of the action flags are explicitly requested, leave them as-is. Otherwise, assume # defaults: Mutate the given arguments to enable the default actions. if ( not args.init and not args.prune and not args.create and not args.check and not args.extract and not args.list and not args.info ): args.prune = True args.create = True args.check = True if args.stats and not (args.create or args.prune): raise ValueError('The --stats option can only be used when creating or pruning archives') return args