From bb60b25399c89def1bfe289a019ec83a8cc08155 Mon Sep 17 00:00:00 2001 From: Divyansh Singh Date: Fri, 2 Jun 2023 02:04:35 +0530 Subject: [PATCH] merge subparsers and refactor --- borgmatic/actions/bootstrap.py | 2 +- borgmatic/commands/arguments.py | 42 +++++++++++++++++++++------------ borgmatic/commands/borgmatic.py | 19 ++++++++------- 3 files changed, 39 insertions(+), 24 deletions(-) diff --git a/borgmatic/actions/bootstrap.py b/borgmatic/actions/bootstrap.py index 46ba53f..3a480dd 100644 --- a/borgmatic/actions/bootstrap.py +++ b/borgmatic/actions/bootstrap.py @@ -70,7 +70,7 @@ def run_bootstrap(bootstrap_arguments, global_arguments, local_borg_version): local_borg_version, global_arguments, extract_to_stdout=False, - destination_path=bootstrap_arguments.destination, + destination_path=bootstrap_arguments.destination or '/', strip_components=bootstrap_arguments.strip_components, progress=bootstrap_arguments.progress, ) diff --git a/borgmatic/commands/arguments.py b/borgmatic/commands/arguments.py index 3ad8725..a66f0ed 100644 --- a/borgmatic/commands/arguments.py +++ b/borgmatic/commands/arguments.py @@ -1,3 +1,4 @@ +import argparse import collections from argparse import Action, ArgumentParser @@ -73,18 +74,15 @@ def parse_subparser_arguments(unparsed_arguments, subparsers): if item in subparsers: remaining_arguments.remove(item) - if canonical_name not in subcommand_parsers_mapping: - arguments[canonical_name] = parsed - else: - arguments[canonical_name] = None + arguments[canonical_name] = None if canonical_name in subcommand_parsers_mapping else parsed for argument in arguments: - if arguments[argument] == None: - for subcommand in subcommand_parsers_mapping[argument]: - if subcommand not in arguments: - raise ValueError("Missing subcommand for {}. Expected one of {}".format( - argument, subcommand_parsers_mapping[argument] - )) + if not arguments[argument]: + if not any(subcommand in arguments for subcommand in subcommand_parsers_mapping[argument]): + raise ValueError("Missing subcommand for {}. Expected one of {}".format( + argument, subcommand_parsers_mapping[argument] + )) + # If no actions are explicitly requested, assume defaults. if not arguments and '--help' not in unparsed_arguments and '-h' not in unparsed_arguments: @@ -948,7 +946,17 @@ def make_parsers(): ) borg_group.add_argument('-h', '--help', action='help', help='Show this help message and exit') - return top_level_parser, subparsers, config_subparsers + 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 + subparser._name_parser_map = merged_subparsers._name_parser_map + + for name, subparser in config_subparsers.choices.items(): + merged_subparsers._name_parser_map[name] = subparser + subparser._name_parser_map = merged_subparsers._name_parser_map + + return top_level_parser, merged_subparsers def parse_arguments(*unparsed_arguments): @@ -956,14 +964,18 @@ 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, config_subparsers = make_parsers() + top_level_parser, subparsers = make_parsers() - subparser_choices = subparsers.choices.copy() - subparser_choices.update(config_subparsers.choices) arguments, remaining_arguments = parse_subparser_arguments( - unparsed_arguments, subparser_choices + unparsed_arguments, subparsers.choices ) + + if 'bootstrap' in arguments.keys() and len(arguments.keys()) > 1: + raise ValueError( + 'The bootstrap action cannot be combined with other actions. Please run it separately.' + ) + arguments['global'] = top_level_parser.parse_args(remaining_arguments) if arguments['global'].excludes_filename: diff --git a/borgmatic/commands/borgmatic.py b/borgmatic/commands/borgmatic.py index ccc6ccf..7aaf570 100644 --- a/borgmatic/commands/borgmatic.py +++ b/borgmatic/commands/borgmatic.py @@ -617,7 +617,7 @@ def collect_configuration_run_summary_logs(configs, arguments): if 'extract' in arguments or 'mount' in arguments: validate.guard_single_repository_selected(repository, configs) - if 'config' not in arguments: + if 'bootstrap' not in arguments: validate.guard_configuration_contains_repository(repository, configs) except ValueError as error: yield from log_error_records(str(error)) @@ -626,14 +626,17 @@ def collect_configuration_run_summary_logs(configs, arguments): if 'bootstrap' in arguments: # no configuration file is needed for bootstrap local_borg_version = borg_version.local_borg_version({}, 'borg') - borgmatic.actions.bootstrap.run_bootstrap(arguments['bootstrap'], arguments['global'], local_borg_version) - yield logging.makeLogRecord( - dict( - levelno=logging.INFO, - levelname='INFO', - msg='Bootstrap successful', + try: + borgmatic.actions.bootstrap.run_bootstrap(arguments['bootstrap'], arguments['global'], local_borg_version) + yield logging.makeLogRecord( + dict( + levelno=logging.INFO, + levelname='INFO', + msg='Bootstrap successful', + ) ) - ) + except (CalledProcessError, ValueError, OSError) as error: + yield from log_error_records('Error running bootstrap', error) return if not configs: