blob: d6496c0cb7802947f6bf1ae753efc613b49164e2 [file] [log] [blame]
Simon Glass22ce6412023-11-04 10:25:20 -06001# SPDX-License-Identifier: GPL-2.0+
2#
3# Copyright 2023 Google LLC
4#
5
6"""Handles parsing of buildman arguments
7
8This creates the argument parser and uses it to parse the arguments passed in
9"""
10
11import argparse
12import os
13import pathlib
14import sys
15
16from patman import gitutil
17from patman import project
18from patman import settings
19
20PATMAN_DIR = pathlib.Path(__file__).parent
21HAS_TESTS = os.path.exists(PATMAN_DIR / "func_test.py")
22
23def parse_args():
24 """Parse command line arguments from sys.argv[]
25
26 Returns:
27 tuple containing:
28 options: command line options
29 args: command lin arguments
30 """
31 epilog = '''Create patches from commits in a branch, check them and email
32 them as specified by tags you place in the commits. Use -n to do a dry
33 run first.'''
34
35 parser = argparse.ArgumentParser(epilog=epilog)
36 parser.add_argument('-b', '--branch', type=str,
37 help="Branch to process (by default, the current branch)")
38 parser.add_argument('-c', '--count', dest='count', type=int,
39 default=-1, help='Automatically create patches from top n commits')
40 parser.add_argument('-e', '--end', type=int, default=0,
41 help='Commits to skip at end of patch list')
42 parser.add_argument('-D', '--debug', action='store_true',
43 help='Enabling debugging (provides a full traceback on error)')
44 parser.add_argument('-p', '--project', default=project.detect_project(),
45 help="Project name; affects default option values and "
46 "aliases [default: %(default)s]")
47 parser.add_argument('-P', '--patchwork-url',
48 default='https://patchwork.ozlabs.org',
49 help='URL of patchwork server [default: %(default)s]')
50 parser.add_argument('-s', '--start', dest='start', type=int,
51 default=0, help='Commit to start creating patches from (0 = HEAD)')
52 parser.add_argument(
53 '-v', '--verbose', action='store_true', dest='verbose', default=False,
54 help='Verbose output of errors and warnings')
55 parser.add_argument(
56 '-H', '--full-help', action='store_true', dest='full_help',
57 default=False, help='Display the README file')
58
59 subparsers = parser.add_subparsers(dest='cmd')
60 send = subparsers.add_parser(
61 'send', help='Format, check and email patches (default command)')
62 send.add_argument('-i', '--ignore-errors', action='store_true',
63 dest='ignore_errors', default=False,
64 help='Send patches email even if patch errors are found')
65 send.add_argument('-l', '--limit-cc', dest='limit', type=int, default=None,
66 help='Limit the cc list to LIMIT entries [default: %(default)s]')
67 send.add_argument('-m', '--no-maintainers', action='store_false',
68 dest='add_maintainers', default=True,
69 help="Don't cc the file maintainers automatically")
70 send.add_argument(
71 '--get-maintainer-script', dest='get_maintainer_script', type=str,
72 action='store',
73 default=os.path.join(gitutil.get_top_level(), 'scripts',
74 'get_maintainer.pl') + ' --norolestats',
75 help='File name of the get_maintainer.pl (or compatible) script.')
76 send.add_argument('-n', '--dry-run', action='store_true', dest='dry_run',
77 default=False, help="Do a dry run (create but don't email patches)")
78 send.add_argument('-r', '--in-reply-to', type=str, action='store',
79 help="Message ID that this series is in reply to")
80 send.add_argument('-t', '--ignore-bad-tags', action='store_true',
81 default=False,
82 help='Ignore bad tags / aliases (default=warn)')
83 send.add_argument('-T', '--thread', action='store_true', dest='thread',
84 default=False, help='Create patches as a single thread')
85 send.add_argument('--cc-cmd', dest='cc_cmd', type=str, action='store',
86 default=None, help='Output cc list for patch file (used by git)')
87 send.add_argument('--no-binary', action='store_true', dest='ignore_binary',
88 default=False,
89 help="Do not output contents of changes in binary files")
90 send.add_argument('--no-check', action='store_false', dest='check_patch',
91 default=True,
92 help="Don't check for patch compliance")
93 send.add_argument(
94 '--tree', dest='check_patch_use_tree', default=False,
95 action='store_true',
96 help=("Set `tree` to True. If `tree` is False then we'll pass "
97 "'--no-tree' to checkpatch (default: tree=%(default)s)"))
98 send.add_argument('--no-tree', dest='check_patch_use_tree',
99 action='store_false', help="Set `tree` to False")
100 send.add_argument(
101 '--no-tags', action='store_false', dest='process_tags', default=True,
102 help="Don't process subject tags as aliases")
103 send.add_argument('--no-signoff', action='store_false', dest='add_signoff',
104 default=True, help="Don't add Signed-off-by to patches")
105 send.add_argument('--smtp-server', type=str,
106 help="Specify the SMTP server to 'git send-email'")
107 send.add_argument('--keep-change-id', action='store_true',
108 help='Preserve Change-Id tags in patches to send.')
109
110 send.add_argument('patchfiles', nargs='*')
111
112 # Only add the 'test' action if the test data files are available.
113 if HAS_TESTS:
114 test_parser = subparsers.add_parser('test', help='Run tests')
115 test_parser.add_argument('testname', type=str, default=None, nargs='?',
116 help="Specify the test to run")
117
118 status = subparsers.add_parser('status',
119 help='Check status of patches in patchwork')
120 status.add_argument('-C', '--show-comments', action='store_true',
121 help='Show comments from each patch')
122 status.add_argument(
123 '-d', '--dest-branch', type=str,
124 help='Name of branch to create with collected responses')
125 status.add_argument('-f', '--force', action='store_true',
126 help='Force overwriting an existing branch')
127
128 # Parse options twice: first to get the project and second to handle
129 # defaults properly (which depends on project)
130 # Use parse_known_args() in case 'cmd' is omitted
131 argv = sys.argv[1:]
132 args, rest = parser.parse_known_args(argv)
133 if hasattr(args, 'project'):
134 settings.Setup(parser, args.project)
135 args, rest = parser.parse_known_args(argv)
136
137 # If we have a command, it is safe to parse all arguments
138 if args.cmd:
139 args = parser.parse_args(argv)
140 else:
141 # No command, so insert it after the known arguments and before the ones
142 # that presumably relate to the 'send' subcommand
143 nargs = len(rest)
144 argv = argv[:-nargs] + ['send'] + rest
145 args = parser.parse_args(argv)
146
147 return args