From 4600767d294d892ce52cb0af3b24e324a3df4818 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Tue, 3 Nov 2020 13:54:10 -0700 Subject: [PATCH] patman: Refactor how the default subcommand works At present patman tries to assume a default subcommand of 'send', to maintain backwards compatibility. However it does not cope with arguments added to the default command, so for example 'patman -t' does not work. Update the logic to handle this. Also update the CC command to use 'send' explicitly, since otherwise patman gets confused with the patch-filename argument. Signed-off-by: Simon Glass --- tools/patman/func_test.py | 2 +- tools/patman/gitutil.py | 10 ++++---- tools/patman/main.py | 59 +++++++++++++++++++++++++---------------------- 3 files changed, 38 insertions(+), 33 deletions(-) diff --git a/tools/patman/func_test.py b/tools/patman/func_test.py index e2adf32..5933fcf 100644 --- a/tools/patman/func_test.py +++ b/tools/patman/func_test.py @@ -248,7 +248,7 @@ class TestFunctional(unittest.TestCase): self.assertEqual(' Cc: %s' % rick, next(lines)) expected = ('Git command: git send-email --annotate ' '--in-reply-to="%s" --to "u-boot@lists.denx.de" ' - '--cc "%s" --cc-cmd "%s --cc-cmd %s" %s %s' + '--cc "%s" --cc-cmd "%s send --cc-cmd %s" %s %s' % (in_reply_to, stefan, sys.argv[0], cc_file, cover_fname, ' '.join(args))) self.assertEqual(expected, tools.ToUnicode(next(lines))) diff --git a/tools/patman/gitutil.py b/tools/patman/gitutil.py index 3a2366bc..31fb3b2 100644 --- a/tools/patman/gitutil.py +++ b/tools/patman/gitutil.py @@ -455,21 +455,21 @@ def EmailPatches(series, cover_fname, args, dry_run, raise_on_error, cc_fname, >>> EmailPatches(series, 'cover', ['p1', 'p2'], True, True, 'cc-fname', \ False, alias) 'git send-email --annotate --to "f.bloggs@napier.co.nz" --cc \ -"m.poppins@cloud.net" --cc-cmd "./patman --cc-cmd cc-fname" cover p1 p2' +"m.poppins@cloud.net" --cc-cmd "./patman send --cc-cmd cc-fname" cover p1 p2' >>> EmailPatches(series, None, ['p1'], True, True, 'cc-fname', False, \ alias) 'git send-email --annotate --to "f.bloggs@napier.co.nz" --cc \ -"m.poppins@cloud.net" --cc-cmd "./patman --cc-cmd cc-fname" p1' +"m.poppins@cloud.net" --cc-cmd "./patman send --cc-cmd cc-fname" p1' >>> series['cc'] = ['all'] >>> EmailPatches(series, 'cover', ['p1', 'p2'], True, True, 'cc-fname', \ True, alias) 'git send-email --annotate --to "this-is-me@me.com" --cc-cmd "./patman \ ---cc-cmd cc-fname" cover p1 p2' +send --cc-cmd cc-fname" cover p1 p2' >>> EmailPatches(series, 'cover', ['p1', 'p2'], True, True, 'cc-fname', \ False, alias) 'git send-email --annotate --to "f.bloggs@napier.co.nz" --cc \ "f.bloggs@napier.co.nz" --cc "j.bloggs@napier.co.nz" --cc \ -"m.poppins@cloud.net" --cc-cmd "./patman --cc-cmd cc-fname" cover p1 p2' +"m.poppins@cloud.net" --cc-cmd "./patman send --cc-cmd cc-fname" cover p1 p2' # Restore argv[0] since we clobbered it. >>> sys.argv[0] = _old_argv0 @@ -500,7 +500,7 @@ def EmailPatches(series, cover_fname, args, dry_run, raise_on_error, cc_fname, cmd += to cmd += cc - cmd += ['--cc-cmd', '"%s --cc-cmd %s"' % (sys.argv[0], cc_fname)] + cmd += ['--cc-cmd', '"%s send --cc-cmd %s"' % (sys.argv[0], cc_fname)] if cover_fname: cmd.append(cover_fname) cmd += args diff --git a/tools/patman/main.py b/tools/patman/main.py index c7f4255..e0e03a4 100755 --- a/tools/patman/main.py +++ b/tools/patman/main.py @@ -28,26 +28,30 @@ from patman import terminal from patman import test_util from patman import test_checkpatch -def AddCommonArgs(parser): - parser.add_argument('-b', '--branch', type=str, - help="Branch to process (by default, the current branch)") - parser.add_argument('-c', '--count', dest='count', type=int, - default=-1, help='Automatically create patches from top n commits') - parser.add_argument('-e', '--end', type=int, default=0, - help='Commits to skip at end of patch list') - parser.add_argument('-D', '--debug', action='store_true', - help='Enabling debugging (provides a full traceback on error)') - parser.add_argument('-s', '--start', dest='start', type=int, - default=0, help='Commit to start creating patches from (0 = HEAD)') - 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 = ArgumentParser(epilog=epilog) +parser.add_argument('-b', '--branch', type=str, + help="Branch to process (by default, the current branch)") +parser.add_argument('-c', '--count', dest='count', type=int, + default=-1, help='Automatically create patches from top n commits') +parser.add_argument('-e', '--end', type=int, default=0, + help='Commits to skip at end of patch list') +parser.add_argument('-D', '--debug', action='store_true', + help='Enabling debugging (provides a full traceback on error)') +parser.add_argument('-p', '--project', default=project.DetectProject(), + help="Project name; affects default option values and " + "aliases [default: %(default)s]") +parser.add_argument('-s', '--start', dest='start', type=int, + default=0, help='Commit to start creating patches from (0 = HEAD)') +parser.add_argument('-v', '--verbose', action='store_true', dest='verbose', + default=False, help='Verbose output of errors and warnings') +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') send = subparsers.add_parser('send') -send.add_argument('-H', '--full-help', action='store_true', dest='full_help', - default=False, help='Display the README file') send.add_argument('-i', '--ignore-errors', action='store_true', dest='ignore_errors', default=False, help='Send patches email even if patch errors are found') @@ -58,15 +62,10 @@ send.add_argument('-m', '--no-maintainers', action='store_false', help="Don't cc the file maintainers automatically") 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('-p', '--project', default=project.DetectProject(), - help="Project name; affects default option values and " - "aliases [default: %(default)s]") send.add_argument('-r', '--in-reply-to', type=str, action='store', help="Message ID that this series is in reply to") send.add_argument('-t', '--ignore-bad-tags', action='store_true', default=False, help='Ignore bad tags / aliases') -send.add_argument('-v', '--verbose', action='store_true', dest='verbose', - default=False, help='Verbose output of errors and warnings') send.add_argument('-T', '--thread', action='store_true', dest='thread', default=False, help='Create patches as a single thread') send.add_argument('--cc-cmd', dest='cc_cmd', type=str, action='store', @@ -81,14 +80,12 @@ send.add_argument('--no-tags', action='store_false', dest='process_tags', default=True, help="Don't process subject tags as aliases") send.add_argument('--smtp-server', type=str, help="Specify the SMTP server to 'git send-email'") -AddCommonArgs(send) send.add_argument('patchfiles', nargs='*') 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") -AddCommonArgs(test_parser) status = subparsers.add_parser('status', help='Check status of patches in patchwork') @@ -98,16 +95,24 @@ 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') -AddCommonArgs(status) # Parse options twice: first to get the project and second to handle -# defaults properly (which depends on project). +# defaults properly (which depends on project) +# Use parse_known_args() in case 'cmd' is omitted argv = sys.argv[1:] -if len(argv) < 1 or argv[0].startswith('-'): - argv = ['send'] + argv -args = parser.parse_args(argv) +args, rest = parser.parse_known_args(argv) if hasattr(args, 'project'): - settings.Setup(gitutil, send, args.project, '') + settings.Setup(gitutil, parser, args.project, '') + 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) +else: + # 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) if __name__ != "__main__": -- 2.7.4