diff --git a/borgmatic/actions/config/bootstrap.py b/borgmatic/actions/config/bootstrap.py index 5b32345..9254da6 100644 --- a/borgmatic/actions/config/bootstrap.py +++ b/borgmatic/actions/config/bootstrap.py @@ -12,6 +12,16 @@ logger = logging.getLogger(__name__) def get_config_paths(bootstrap_arguments, global_arguments, local_borg_version): + ''' + Given: + The bootstrap arguments, which include the repository and archive name, borgmatic source directory, + destination directory, and whether to strip components. + The global arguments, which include the dry run flag + and the local borg version, + Return: + The config paths from the manifest.json file in the borgmatic source directory after extracting it from the + repository. + ''' borgmatic_source_directory = ( bootstrap_arguments.borgmatic_source_directory or DEFAULT_BORGMATIC_SOURCE_DIRECTORY ) diff --git a/borgmatic/commands/arguments.py b/borgmatic/commands/arguments.py index db50674..c39198c 100644 --- a/borgmatic/commands/arguments.py +++ b/borgmatic/commands/arguments.py @@ -29,7 +29,9 @@ SUBPARSER_ALIASES = { def get_unparsable_arguments(remaining_subparser_arguments): - # Determine the remaining arguments that no subparsers have consumed. + ''' + Determine the remaining arguments that no subparsers have consumed. + ''' if remaining_subparser_arguments: remaining_arguments = [ argument @@ -590,7 +592,7 @@ def make_parsers(): 'bootstrap', aliases=SUBPARSER_ALIASES['config_bootstrap'], help='Extract the config files used to create a borgmatic repository', - description='Extract just the config files that were used to create a borgmatic repository during the "create" operation', + description='Extract config files that were used to create a borgmatic repository during the "create" operation', add_help=False, ) config_bootstrap_group = config_bootstrap_parser.add_argument_group( @@ -603,7 +605,7 @@ def make_parsers(): ) config_bootstrap_group.add_argument( '--borgmatic-source-directory', - help='Path that stores the config files used to create an archive, and additional source files used for temporary internal state like borgmatic database dumps. Defaults to ~/.borgmatic', + help='Path that stores the config files used to create an archive and additional source files used for temporary internal state like borgmatic database dumps. Defaults to ~/.borgmatic', ) config_bootstrap_group.add_argument( '--archive', @@ -980,15 +982,26 @@ def make_parsers(): None, None, metavar=None, dest='merged', parser_class=None ) - for name, subparser in subparsers.choices.items(): - merged_subparsers._name_parser_map[name] = subparser - - for name, subparser in config_subparsers.choices.items(): - merged_subparsers._name_parser_map[name] = subparser + merged_subparsers = merge_subparsers(subparsers, config_subparsers) return top_level_parser, merged_subparsers +def merge_subparsers(*subparsers): + ''' + Merge multiple subparsers into a single subparser. + ''' + merged_subparsers = argparse._SubParsersAction( + None, None, metavar=None, dest='merged', parser_class=None + ) + + for subparser in subparsers: + for name, subparser in subparser.choices.items(): + merged_subparsers._name_parser_map[name] = subparser + + return merged_subparsers + + def parse_arguments(*unparsed_arguments): ''' Given command-line arguments with which this script was invoked, parse the arguments and return diff --git a/borgmatic/commands/borgmatic.py b/borgmatic/commands/borgmatic.py index 766073c..4ad8136 100644 --- a/borgmatic/commands/borgmatic.py +++ b/borgmatic/commands/borgmatic.py @@ -645,6 +645,7 @@ def collect_configuration_run_summary_logs(configs, arguments): KeyError, ) as error: yield from log_error_records('Error running bootstrap', error) + return if not configs: diff --git a/tests/integration/commands/test_arguments.py b/tests/integration/commands/test_arguments.py index 8c96ac9..60fe884 100644 --- a/tests/integration/commands/test_arguments.py +++ b/tests/integration/commands/test_arguments.py @@ -538,24 +538,17 @@ def test_merging_two_subparser_collections_merges_their_choices(): top_level_parser = argparse.ArgumentParser() subparsers = top_level_parser.add_subparsers() - subparser1 = subparsers.add_parser('subparser1') subparser2 = subparsers.add_parser('subparser2') - subsubparsers = subparser2.add_subparsers() - subsubparser1 = subsubparsers.add_parser('subsubparser1') merged_subparsers = argparse._SubParsersAction( None, None, metavar=None, dest='merged', parser_class=None ) - for name, subparser in subparsers.choices.items(): - merged_subparsers._name_parser_map[name] = subparser - - for name, subparser in subsubparsers.choices.items(): - merged_subparsers._name_parser_map[name] = subparser + merged_subparsers = module.merge_subparsers(subparsers, subsubparsers) assert merged_subparsers.choices == { 'subparser1': subparser1,