diff options
Diffstat (limited to 'tools/patman/cmdline.py')
| -rw-r--r-- | tools/patman/cmdline.py | 516 |
1 files changed, 0 insertions, 516 deletions
diff --git a/tools/patman/cmdline.py b/tools/patman/cmdline.py deleted file mode 100644 index 924f0ad4e42..00000000000 --- a/tools/patman/cmdline.py +++ /dev/null @@ -1,516 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0+ -# -# Copyright 2023 Google LLC -# - -"""Handles parsing of buildman arguments - -This creates the argument parser and uses it to parse the arguments passed in -""" - -import argparse -import os -import pathlib -import sys - -from u_boot_pylib import gitutil -from patman import project -from patman import settings - -PATMAN_DIR = pathlib.Path(__file__).parent -HAS_TESTS = os.path.exists(PATMAN_DIR / "func_test.py") - -# Aliases for subcommands -ALIASES = { - 'series': ['s', 'ser'], - 'status': ['st'], - 'patchwork': ['pw'], - 'upstream': ['us'], - - # Series aliases - 'archive': ['ar'], - 'autolink': ['au'], - 'gather': ['g'], - 'open': ['o'], - 'progress': ['p', 'pr', 'prog'], - 'rm-version': ['rmv'], - 'unarchive': ['unar'], - } - - -class ErrorCatchingArgumentParser(argparse.ArgumentParser): - def __init__(self, **kwargs): - self.exit_state = None - self.catch_error = False - super().__init__(**kwargs) - - def error(self, message): - if self.catch_error: - self.message = message - else: - super().error(message) - - def exit(self, status=0, message=None): - if self.catch_error: - self.exit_state = True - else: - super().exit(status, message) - - -def add_send_args(par): - """Add arguments for the 'send' command - - Arguments: - par (ArgumentParser): Parser to add to - """ - par.add_argument( - '-c', '--count', dest='count', type=int, default=-1, - help='Automatically create patches from top n commits') - par.add_argument( - '-e', '--end', type=int, default=0, - help='Commits to skip at end of patch list') - par.add_argument( - '-i', '--ignore-errors', action='store_true', - dest='ignore_errors', default=False, - help='Send patches email even if patch errors are found') - par.add_argument( - '-l', '--limit-cc', dest='limit', type=int, default=None, - help='Limit the cc list to LIMIT entries [default: %(default)s]') - par.add_argument( - '-m', '--no-maintainers', action='store_false', - dest='add_maintainers', default=True, - help="Don't cc the file maintainers automatically") - default_arg = None - top_level = gitutil.get_top_level() - if top_level: - default_arg = os.path.join(top_level, 'scripts', - 'get_maintainer.pl') + ' --norolestats' - par.add_argument( - '--get-maintainer-script', dest='get_maintainer_script', type=str, - action='store', - default=default_arg, - help='File name of the get_maintainer.pl (or compatible) script.') - par.add_argument( - '-r', '--in-reply-to', type=str, action='store', - help="Message ID that this series is in reply to") - par.add_argument( - '-s', '--start', dest='start', type=int, default=0, - help='Commit to start creating patches from (0 = HEAD)') - par.add_argument( - '-t', '--ignore-bad-tags', action='store_true', default=False, - help='Ignore bad tags / aliases (default=warn)') - par.add_argument( - '--no-binary', action='store_true', dest='ignore_binary', - default=False, - help="Do not output contents of changes in binary files") - par.add_argument( - '--no-check', action='store_false', dest='check_patch', default=True, - help="Don't check for patch compliance") - par.add_argument( - '--tree', dest='check_patch_use_tree', default=False, - action='store_true', - help=("Set `tree` to True. If `tree` is False then we'll pass " - "'--no-tree' to checkpatch (default: tree=%(default)s)")) - par.add_argument( - '--no-tree', dest='check_patch_use_tree', action='store_false', - help="Set `tree` to False") - par.add_argument( - '--no-tags', action='store_false', dest='process_tags', default=True, - help="Don't process subject tags as aliases") - par.add_argument( - '--no-signoff', action='store_false', dest='add_signoff', - default=True, help="Don't add Signed-off-by to patches") - par.add_argument( - '--smtp-server', type=str, - help="Specify the SMTP server to 'git send-email'") - par.add_argument( - '--keep-change-id', action='store_true', - help='Preserve Change-Id tags in patches to send.') - - -def _add_show_comments(parser): - parser.add_argument('-c', '--show-comments', action='store_true', - help='Show comments from each patch') - - -def _add_show_cover_comments(parser): - parser.add_argument('-C', '--show-cover-comments', action='store_true', - help='Show comments from the cover letter') - - -def add_patchwork_subparser(subparsers): - """Add the 'patchwork' subparser - - Args: - subparsers (argparse action): Subparser parent - - Return: - ArgumentParser: patchwork subparser - """ - patchwork = subparsers.add_parser( - 'patchwork', aliases=ALIASES['patchwork'], - help='Manage patchwork connection') - patchwork.defaults_cmds = [ - ['set-project', 'U-Boot'], - ] - patchwork_subparsers = patchwork.add_subparsers(dest='subcmd') - patchwork_subparsers.add_parser('get-project') - uset = patchwork_subparsers.add_parser('set-project') - uset.add_argument( - 'project_name', help="Patchwork project name, e.g. 'U-Boot'") - return patchwork - - -def add_series_subparser(subparsers): - """Add the 'series' subparser - - Args: - subparsers (argparse action): Subparser parent - - Return: - ArgumentParser: series subparser - """ - def _add_allow_unmarked(parser): - parser.add_argument('-M', '--allow-unmarked', action='store_true', - default=False, - help="Don't require commits to be marked") - - def _add_mark(parser): - parser.add_argument( - '-m', '--mark', action='store_true', - help='Mark unmarked commits with a Change-Id field') - - def _add_update(parser): - parser.add_argument('-u', '--update', action='store_true', - help='Update the branch commit') - - def _add_wait(parser, default_s): - """Add a -w option to a parser - - Args: - parser (ArgumentParser): Parser to adjust - default_s (int): Default value to use, in seconds - """ - parser.add_argument( - '-w', '--autolink-wait', type=int, default=default_s, - help='Seconds to wait for patchwork to get a sent series') - - def _upstream_add(parser): - parser.add_argument('-U', '--upstream', help='Commit to end before') - - def _add_gather(parser): - parser.add_argument( - '-G', '--no-gather-tags', dest='gather_tags', default=True, - action='store_false', - help="Don't gather review/test tags / update local series") - - series = subparsers.add_parser('series', aliases=ALIASES['series'], - help='Manage series of patches') - series.defaults_cmds = [ - ['set-link', 'fred'], - ] - series.add_argument( - '-n', '--dry-run', action='store_true', dest='dry_run', default=False, - help="Do a dry run (create but don't email patches)") - series.add_argument('-s', '--series', help='Name of series') - series.add_argument('-V', '--version', type=int, - help='Version number to link') - series_subparsers = series.add_subparsers(dest='subcmd') - - # This causes problem at present, perhaps due to the 'defaults' handling in - # settings - # series_subparsers.required = True - - add = series_subparsers.add_parser('add') - add.add_argument('-D', '--desc', - help='Series description / cover-letter title') - add.add_argument( - '-f', '--force-version', action='store_true', - help='Change the Series-version on a series to match its branch') - _add_mark(add) - _add_allow_unmarked(add) - _upstream_add(add) - - series_subparsers.add_parser('archive', aliases=ALIASES['archive']) - - auto = series_subparsers.add_parser('autolink', - aliases=ALIASES['autolink']) - _add_update(auto) - _add_wait(auto, 0) - - aall = series_subparsers.add_parser('autolink-all') - aall.add_argument('-a', '--link-all-versions', action='store_true', - help='Link all series versions, not just the latest') - aall.add_argument('-r', '--replace-existing', action='store_true', - help='Replace existing links') - _add_update(aall) - - series_subparsers.add_parser('dec') - - gat = series_subparsers.add_parser('gather', aliases=ALIASES['gather']) - _add_gather(gat) - _add_show_comments(gat) - _add_show_cover_comments(gat) - - sall = series_subparsers.add_parser('gather-all') - sall.add_argument( - '-a', '--gather-all-versions', action='store_true', - help='Gather tags from all series versions, not just the latest') - _add_gather(sall) - _add_show_comments(sall) - _add_show_cover_comments(sall) - - series_subparsers.add_parser('get-link') - series_subparsers.add_parser('inc') - series_subparsers.add_parser('ls') - - mar = series_subparsers.add_parser('mark') - mar.add_argument('-m', '--allow-marked', action='store_true', - default=False, - help="Don't require commits to be unmarked") - - series_subparsers.add_parser('open', aliases=ALIASES['open']) - pat = series_subparsers.add_parser( - 'patches', epilog='Show a list of patches and optional details') - pat.add_argument('-t', '--commit', action='store_true', - help='Show the commit and diffstat') - pat.add_argument('-p', '--patch', action='store_true', - help='Show the patch body') - - prog = series_subparsers.add_parser('progress', - aliases=ALIASES['progress']) - prog.add_argument('-a', '--show-all-versions', action='store_true', - help='Show all series versions, not just the latest') - prog.add_argument('-l', '--list-patches', action='store_true', - help='List patch subject and status') - - ren = series_subparsers.add_parser('rename') - ren.add_argument('-N', '--new-name', help='New name for the series') - - series_subparsers.add_parser('rm') - series_subparsers.add_parser('rm-version', aliases=ALIASES['rm-version']) - - scan = series_subparsers.add_parser('scan') - _add_mark(scan) - _add_allow_unmarked(scan) - _upstream_add(scan) - - ssend = series_subparsers.add_parser('send') - add_send_args(ssend) - ssend.add_argument( - '--no-autolink', action='store_false', default=True, dest='autolink', - help='Monitor patchwork after sending so the series can be autolinked') - _add_wait(ssend, 120) - - setl = series_subparsers.add_parser('set-link') - _add_update(setl) - - setl.add_argument( - 'link', help='Link to use, i.e. patchwork series number (e.g. 452329)') - stat = series_subparsers.add_parser('status', aliases=ALIASES['status']) - _add_show_comments(stat) - _add_show_cover_comments(stat) - - series_subparsers.add_parser('summary') - - series_subparsers.add_parser('unarchive', aliases=ALIASES['unarchive']) - - unm = series_subparsers.add_parser('unmark') - _add_allow_unmarked(unm) - - ver = series_subparsers.add_parser( - 'version-change', help='Change a version to a different version') - ver.add_argument('--new-version', type=int, - help='New version number to change this one too') - - return series - - -def add_send_subparser(subparsers): - """Add the 'send' subparser - - Args: - subparsers (argparse action): Subparser parent - - Return: - ArgumentParser: send subparser - """ - send = subparsers.add_parser( - 'send', help='Format, check and email patches (default command)') - send.add_argument( - '-b', '--branch', type=str, - help="Branch to process (by default, the current branch)") - send.add_argument( - '-n', '--dry-run', action='store_true', dest='dry_run', - default=False, help="Do a dry run (create but don't email patches)") - send.add_argument( - '--cc-cmd', dest='cc_cmd', type=str, action='store', - default=None, help='Output cc list for patch file (used by git)') - add_send_args(send) - send.add_argument('patchfiles', nargs='*') - return send - - -def add_status_subparser(subparsers): - """Add the 'status' subparser - - Args: - subparsers (argparse action): Subparser parent - - Return: - ArgumentParser: status subparser - """ - status = subparsers.add_parser('status', aliases=ALIASES['status'], - help='Check status of patches in patchwork') - _add_show_comments(status) - status.add_argument( - '-d', '--dest-branch', type=str, - help='Name of branch to create with collected responses') - status.add_argument('-f', '--force', action='store_true', - help='Force overwriting an existing branch') - status.add_argument('-T', '--single-thread', action='store_true', - help='Disable multithreading when reading patchwork') - return status - - -def add_upstream_subparser(subparsers): - """Add the 'status' subparser - - Args: - subparsers (argparse action): Subparser parent - - Return: - ArgumentParser: status subparser - """ - upstream = subparsers.add_parser('upstream', aliases=ALIASES['upstream'], - help='Manage upstream destinations') - upstream.defaults_cmds = [ - ['add', 'us', 'http://fred'], - ['delete', 'us'], - ] - upstream_subparsers = upstream.add_subparsers(dest='subcmd') - uadd = upstream_subparsers.add_parser('add') - uadd.add_argument('remote_name', - help="Git remote name used for this upstream, e.g. 'us'") - uadd.add_argument( - 'url', help='URL to use for this upstream, e.g. ' - "'https://gitlab.denx.de/u-boot/u-boot.git'") - udel = upstream_subparsers.add_parser('delete') - udel.add_argument( - 'remote_name', - help="Git remote name used for this upstream, e.g. 'us'") - upstream_subparsers.add_parser('list') - udef = upstream_subparsers.add_parser('default') - udef.add_argument('-u', '--unset', action='store_true', - help='Unset the default upstream') - udef.add_argument('remote_name', nargs='?', - help="Git remote name used for this upstream, e.g. 'us'") - return upstream - - -def setup_parser(): - """Set up command-line parser - - Returns: - argparse.Parser object - """ - epilog = '''Create patches from commits in a branch, check them and email - them as specified by tags you place in the commits. Use -n to do a dry - run first.''' - - parser = ErrorCatchingArgumentParser(epilog=epilog) - parser.add_argument( - '-D', '--debug', action='store_true', - help='Enabling debugging (provides a full traceback on error)') - parser.add_argument( - '-N', '--no-capture', action='store_true', - help='Disable capturing of console output in tests') - parser.add_argument('-p', '--project', default=project.detect_project(), - help="Project name; affects default option values and " - "aliases [default: %(default)s]") - parser.add_argument('-P', '--patchwork-url', - default='https://patchwork.ozlabs.org', - help='URL of patchwork server [default: %(default)s]') - parser.add_argument( - '-T', '--thread', action='store_true', dest='thread', - default=False, help='Create patches as a single thread') - parser.add_argument( - '-v', '--verbose', action='store_true', dest='verbose', default=False, - help='Verbose output of errors and warnings') - parser.add_argument( - '-X', '--test-preserve-dirs', action='store_true', - help='Preserve and display test-created directories') - parser.add_argument( - '-H', '--full-help', action='store_true', dest='full_help', - default=False, help='Display the README file') - - subparsers = parser.add_subparsers(dest='cmd') - add_send_subparser(subparsers) - patchwork = add_patchwork_subparser(subparsers) - series = add_series_subparser(subparsers) - add_status_subparser(subparsers) - upstream = add_upstream_subparser(subparsers) - - # Only add the 'test' action if the test data files are available. - if HAS_TESTS: - test_parser = subparsers.add_parser('test', help='Run tests') - test_parser.add_argument('testname', type=str, default=None, nargs='?', - help="Specify the test to run") - - parsers = { - 'main': parser, - 'series': series, - 'patchwork': patchwork, - 'upstream': upstream, - } - return parsers - - -def parse_args(argv=None, config_fname=None, parsers=None): - """Parse command line arguments from sys.argv[] - - Args: - argv (str or None): Arguments to process, or None to use sys.argv[1:] - config_fname (str): Config file to read, or None for default, or False - for an empty config - - Returns: - tuple containing: - options: command line options - args: command lin arguments - """ - if not parsers: - parsers = setup_parser() - parser = parsers['main'] - - # Parse options twice: first to get the project and second to handle - # defaults properly (which depends on project) - # Use parse_known_args() in case 'cmd' is omitted - if not argv: - argv = sys.argv[1:] - - args, rest = parser.parse_known_args(argv) - if hasattr(args, 'project'): - settings.Setup(parser, args.project, argv, config_fname) - args, rest = parser.parse_known_args(argv) - - # If we have a command, it is safe to parse all arguments - if args.cmd: - args = parser.parse_args(argv) - elif not args.full_help: - # No command, so insert it after the known arguments and before the ones - # that presumably relate to the 'send' subcommand - nargs = len(rest) - argv = argv[:-nargs] + ['send'] + rest - args = parser.parse_args(argv) - - # Resolve aliases - for full, aliases in ALIASES.items(): - if args.cmd in aliases: - args.cmd = full - if 'subcmd' in args and args.subcmd in aliases: - args.subcmd = full - if args.cmd in ['series', 'upstream', 'patchwork'] and not args.subcmd: - parser.parse_args([args.cmd, '--help']) - - return args |
