patman: Implement the series subcommand
Add a command to support management of series. These are local branches
which may have been sent to the mailing list, so may appear on the
patchwork server.
The new functionality uses a database, stored in a local file.
Various operations are supported:
- add a new series
- send a series and automatically link it with patchwork
- 'increment' the version, to prepare to send an updated series
- gather review/test tags from patchwork
- check on progress, i.e. patches which are received new tags or
comments
- show comments on patches and cover letters
Signed-off-by: Simon Glass <sjg@chromium.org>
diff --git a/tools/patman/cmdline.py b/tools/patman/cmdline.py
index 18434af..10ed1b1 100644
--- a/tools/patman/cmdline.py
+++ b/tools/patman/cmdline.py
@@ -22,10 +22,21 @@
# Aliases for subcommands
ALIASES = {
+ 'series': ['s', 'ser'],
'status': ['st'],
'patchwork': ['pw'],
+
+ # 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
@@ -120,6 +131,11 @@
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
@@ -143,6 +159,171 @@
'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
@@ -230,6 +411,7 @@
subparsers = parser.add_subparsers(dest='cmd')
add_send_subparser(subparsers)
patchwork = add_patchwork_subparser(subparsers)
+ series = add_series_subparser(subparsers)
add_status_subparser(subparsers)
# Only add the 'test' action if the test data files are available.
@@ -240,6 +422,7 @@
parsers = {
'main': parser,
+ 'series': series,
'patchwork': patchwork,
}
return parsers