@@ -26,6 +26,7 @@ ALIASES = {
'status': ['st'],
'patchwork': ['pw'],
'upstream': ['us'],
+ 'workflow': ['wf'],
# Subcommand aliases
'archive': ['ar'],
@@ -35,6 +36,7 @@ ALIASES = {
'open': ['o'],
'progress': ['p', 'pr', 'prog'],
'rm-version': ['rmv'],
+ 'todo-list': ['tl'],
'unarchive': ['unar'],
}
@@ -476,6 +478,32 @@ def add_upstream_subparser(subparsers):
return upstream
+def add_workflow_subparser(subparsers):
+ """Add the 'workflow' subparser
+
+ Args:
+ subparsers (argparse action): Subparser parent
+
+ Return:
+ ArgumentParser: workflow subparser
+ """
+ workflow = subparsers.add_parser('workflow', aliases=ALIASES['workflow'],
+ help='Manage workflow items')
+ workflow_subparsers = workflow.add_subparsers(dest='subcmd')
+ todo = workflow_subparsers.add_parser('todo')
+ todo.add_argument('-s', '--series', help='Name of series')
+ todo.add_argument('days', nargs='?', type=int, default=14,
+ help='Number of days until due (default: 14)')
+ todo.add_argument('--clear', action='store_true',
+ help='Clear the todo marker instead of setting it')
+
+ tlist = workflow_subparsers.add_parser('todo-list',
+ aliases=ALIASES['todo-list'])
+ tlist.add_argument('--all', action='store_true', dest='show_all',
+ help='Show all scheduled todos, not just due ones')
+ return workflow
+
+
def setup_parser():
"""Set up command-line parser
@@ -518,6 +546,7 @@ def setup_parser():
series = add_series_subparser(subparsers)
add_status_subparser(subparsers)
upstream = add_upstream_subparser(subparsers)
+ workflow = add_workflow_subparser(subparsers)
# Only add the 'test' action if the test data files are available.
if HAS_TESTS:
@@ -530,6 +559,7 @@ def setup_parser():
'series': series,
'patchwork': patchwork,
'upstream': upstream,
+ 'workflow': workflow,
}
return parsers
@@ -578,7 +608,7 @@ def parse_args(argv=None, config_fname=None, parsers=None):
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:
+ if args.cmd in ['series', 'upstream', 'patchwork', 'workflow'] and not args.subcmd:
parser.parse_args([args.cmd, '--help'])
return args
@@ -344,6 +344,33 @@ def patchwork(args, test_db=None, pwork=None):
finally:
cser.close_database()
+def do_workflow(args, test_db=None):
+ """Process a 'workflow' subcommand
+
+ Args:
+ args (Namespace): Arguments to process
+ test_db (str or None): Directory containing the test database, None to
+ use the normal one
+ """
+ from patman import cseries
+ from patman import workflow
+
+ cser = cseries.Cseries(test_db)
+ try:
+ cser.open_database()
+ if args.subcmd == 'todo':
+ if args.clear:
+ workflow.todo_clear(cser, args.series)
+ else:
+ workflow.todo(cser, args.series, args.days)
+ elif args.subcmd == 'todo-list':
+ workflow.todo_list(cser, args.show_all)
+ else:
+ raise ValueError(f"Unknown workflow subcommand '{args.subcmd}'")
+ finally:
+ cser.close_database()
+
+
def do_patman(args, test_db=None, pwork=None, cser=None):
"""Process a patman command
@@ -392,6 +419,8 @@ def do_patman(args, test_db=None, pwork=None, cser=None):
upstream(args, test_db)
elif args.cmd == 'patchwork':
patchwork(args, test_db, pwork)
+ elif args.cmd == 'workflow':
+ do_workflow(args, test_db)
except Exception as exc:
terminal.tprint(f'patman: {type(exc).__name__}: {exc}',
colour=terminal.Color.RED)
@@ -4273,3 +4273,23 @@ Date: .*
with terminal.capture() as (out, _):
cser.summary(None)
self.assertNotIn('[todo]', out.getvalue())
+
+ def test_workflow_todo_cmdline(self):
+ """Test todo via the command line"""
+ cser = self.get_cser()
+ with terminal.capture():
+ cser.add('first', 'my description', allow_unmarked=True)
+
+ # Test via command line
+ self.db_close()
+ with terminal.capture() as (out, _):
+ self.run_args('workflow', 'todo', '-s', 'first', '7')
+ self.assertIn('marked for todo', out.getvalue())
+
+ with terminal.capture() as (out, _):
+ self.run_args('workflow', 'todo', '-s', 'first', '--clear')
+ self.assertIn('Todo cleared', out.getvalue())
+
+ with terminal.capture() as (out, _):
+ self.run_args('wf', 'todo-list')
+ self.assertIn('No todos due', out.getvalue())