From a6b37a7b802a03dbaab0b764b1637c5f894d9d40 Mon Sep 17 00:00:00 2001
From: Tomas Kopecek <tkopecek@redhat.com>
Date: Dec 10 2019 09:19:04 +0000
Subject: [PATCH 1/7] unify return values for permission denied


Fixes: https://pagure.io/koji/issue/1776

---

diff --git a/cli/koji_cli/commands.py b/cli/koji_cli/commands.py
index 931d51b..10c1754 100644
--- a/cli/koji_cli/commands.py
+++ b/cli/koji_cli/commands.py
@@ -65,8 +65,8 @@ def handle_add_group(goptions, session, args):
 
     activate_session(session, goptions)
     if not (session.hasPerm('admin') or session.hasPerm('tag')):
-        print("This action requires tag or admin privileges")
-        return 1
+        parser.error(_("This action requires tag or admin privileges"))
+        assert False  # pragma: no cover
 
     dsttag = session.getTag(tag)
     if not dsttag:
@@ -96,8 +96,8 @@ def handle_block_group(goptions, session, args):
 
     activate_session(session, goptions)
     if not (session.hasPerm('admin') or session.hasPerm('tag')):
-        print("This action requires tag or admin privileges")
-        return 1
+        parser.error(_("This action requires tag or admin privileges"))
+        assert False  # pragma: no cover
 
     dsttag = session.getTag(tag)
     if not dsttag:
@@ -143,7 +143,7 @@ def handle_remove_group(goptions, session, args):
 
 def handle_assign_task(goptions, session, args):
     "[admin] Assign a task to a host"
-    usage = _('usage: %prog assign-task task_id hostname')
+    usage = _('usage: %prog assign-task <task_id> <hostname>')
     usage += _('\n(Specify the --help global option for a list of other help options)')
     parser = OptionParser(usage=usage)
     parser.add_option('-f', '--force', action='store_true', default=False,
@@ -170,8 +170,8 @@ def handle_assign_task(goptions, session, args):
 
     activate_session(session, goptions)
     if not session.hasPerm('admin'):
-        print("This action requires admin privileges")
-        return 1
+        parser.error(_("This action requires admin privileges"))
+        assert False  # pragma: no cover
 
     ret = session.assignTask(task_id, hostname, force)
     if ret:
@@ -3409,6 +3409,7 @@ def handle_clone_tag(goptions, session, args):
 
     if not options.test and not (session.hasPerm('admin') or session.hasPerm('tag')):
         parser.error(_("This action requires tag or admin privileges"))
+        assert False  # pragma: no cover
 
     if args[0] == args[1]:
         parser.error(_('Source and destination tags must be different.'))
@@ -3861,8 +3862,8 @@ def handle_add_target(goptions, session, args):
         dest_tag = name
     activate_session(session, goptions)
     if not (session.hasPerm('admin') or session.hasPerm('target')):
-        print("This action requires target or admin privileges")
-        return 1
+        parser.error(_("This action requires target or admin privileges"))
+        assert False  # pragma: no cover
 
     chkbuildtag = session.getTag(build_tag)
     chkdesttag = session.getTag(dest_tag)
@@ -3896,8 +3897,8 @@ def handle_edit_target(goptions, session, args):
     activate_session(session, goptions)
 
     if not (session.hasPerm('admin') or session.hasPerm('target')):
-        print("This action requires target or admin privileges")
-        return
+        parser.error(_("This action requires target or admin privileges"))
+        assert False  # pragma: no cover
 
     targetInfo = session.getBuildTarget(args[0])
     if targetInfo == None:
@@ -3939,8 +3940,8 @@ def handle_remove_target(goptions, session, args):
     activate_session(session, goptions)
 
     if not (session.hasPerm('admin') or session.hasPerm('target')):
-        print("This action requires target or admin privileges")
-        return
+        parser.error(_("This action requires target or admin privileges"))
+        assert False  # pragma: no cover
 
     target = args[0]
     target_info = session.getBuildTarget(target)
@@ -3964,8 +3965,8 @@ def handle_remove_tag(goptions, session, args):
     activate_session(session, goptions)
 
     if not (session.hasPerm('admin') or session.hasPerm('tag')):
-        print("This action requires tag or admin privileges")
-        return
+        parser.error(_("This action requires tag or admin privileges"))
+        assert False  # pragma: no cover
 
     tag = args[0]
     tag_info = session.getTag(tag)
@@ -4964,8 +4965,8 @@ def handle_add_tag(goptions, session, args):
         assert False  # pragma: no cover
     activate_session(session, goptions)
     if not (session.hasPerm('admin') or session.hasPerm('tag')):
-        print("This action requires tag or admin privileges")
-        return
+        parser.error(_("This action requires tag or admin privileges"))
+        assert False  # pragma: no cover
     opts = {}
     if options.parent:
         opts['parent'] = options.parent
diff --git a/tests/test_cli/test_add_group.py b/tests/test_cli/test_add_group.py
index c14ea65..a045647 100644
--- a/tests/test_cli/test_add_group.py
+++ b/tests/test_cli/test_add_group.py
@@ -1,21 +1,27 @@
 from __future__ import absolute_import
 
 import mock
-import os
 import six
-import sys
 try:
     import unittest2 as unittest
 except ImportError:
     import unittest
 
 from koji_cli.commands import handle_add_group
+from . import utils
 
-class TestAddGroup(unittest.TestCase):
+class TestAddGroup(utils.CliTestCase):
 
     # Show long diffs in error output...
     maxDiff = None
 
+    def setUp(self):
+        self.error_format = """Usage: %s add-group <tag> <group>
+(Specify the --help global option for a list of other help options)
+
+%s: error: {message}
+""" % (self.progname, self.progname)
+
     @mock.patch('sys.stdout', new_callable=six.StringIO)
     @mock.patch('koji_cli.commands.activate_session')
     def test_handle_add_group(self, activate_session_mock, stdout):
@@ -89,19 +95,13 @@ class TestAddGroup(unittest.TestCase):
         session = mock.MagicMock()
 
         # Run it and check immediate output
-        with self.assertRaises(SystemExit) as cm:
-            rv = handle_add_group(options, session, arguments)
-        actual_stdout = stdout.getvalue()
-        actual_stderr = stderr.getvalue()
-        expected_stdout = ''
-        progname = os.path.basename(sys.argv[0]) or 'koji'
-        expected_stderr = """Usage: %s add-group <tag> <group>
-(Specify the --help global option for a list of other help options)
-
-%s: error: Please specify a tag name and a group name
-""" % (progname, progname)
-        self.assertMultiLineEqual(actual_stdout, expected_stdout)
-        self.assertMultiLineEqual(actual_stderr, expected_stderr)
+        self.assert_system_exit(
+            handle_add_group,
+            options, session, arguments,
+            stdout='',
+            stderr=self.format_error_message("Please specify a tag name and a group name"),
+            exit_code=2,
+            activate_session=None)
 
         # Finally, assert that things were called as we expected.
         activate_session_mock.assert_not_called()
@@ -109,10 +109,6 @@ class TestAddGroup(unittest.TestCase):
         session.getTag.assert_not_called()
         session.getTagGroups.assert_not_called()
         session.groupListAdd.assert_not_called()
-        if isinstance(cm.exception, int):
-            self.assertEqual(cm.exception, 2)
-        else:
-            self.assertEqual(cm.exception.code, 2)
 
     @mock.patch('sys.stdout', new_callable=six.StringIO)
     @mock.patch('koji_cli.commands.activate_session')
@@ -127,10 +123,13 @@ class TestAddGroup(unittest.TestCase):
         session.hasPerm.return_value = False
 
         # Run it and check immediate output
-        rv = handle_add_group(options, session, arguments)
-        actual = stdout.getvalue()
-        expected = 'This action requires tag or admin privileges\n'
-        self.assertMultiLineEqual(actual, expected)
+        self.assert_system_exit(
+            handle_add_group,
+            options, session, arguments,
+            stdout='',
+            stderr=self.format_error_message('This action requires tag or admin privileges'),
+            activate_session=None,
+            exit_code=2)
 
         # Finally, assert that things were called as we expected.
         activate_session_mock.assert_called_once_with(session, options)
@@ -139,7 +138,6 @@ class TestAddGroup(unittest.TestCase):
         session.getTag.assert_not_called()
         session.getTagGroups.assert_not_called()
         session.groupListAdd.assert_not_called()
-        self.assertEqual(rv, 1)
 
     @mock.patch('sys.stdout', new_callable=six.StringIO)
     @mock.patch('koji_cli.commands.activate_session')
diff --git a/tests/test_cli/test_add_tag.py b/tests/test_cli/test_add_tag.py
index 824941f..72f4a96 100644
--- a/tests/test_cli/test_add_tag.py
+++ b/tests/test_cli/test_add_tag.py
@@ -44,10 +44,13 @@ class TestAddTag(utils.CliTestCase):
             activate_session=None)
 
         # Case 2. not admin account
-        expected = "This action requires tag or admin privileges\n"
         session.hasPerm.return_value = None
-        handle_add_tag(options, session, ['test-tag'])
-        self.assert_console_message(stdout, expected)
+        self.assert_system_exit(
+            handle_add_tag,
+            options, session, ['test-tag'],
+            stdout='',
+            stderr=self.format_error_message("This action requires tag or admin privileges"),
+        )
 
         # Case 3. options test
         arguments = ['test-tag',
diff --git a/tests/test_cli/test_assign_task.py b/tests/test_cli/test_assign_task.py
index 90fce7e..c68ef79 100644
--- a/tests/test_cli/test_assign_task.py
+++ b/tests/test_cli/test_assign_task.py
@@ -10,13 +10,21 @@ except ImportError:
 
 import koji
 from koji_cli.commands import handle_assign_task
+from . import utils
 
 
-class TestAssignTask(unittest.TestCase):
+class TestAssignTask(utils.CliTestCase):
 
     # Show long diffs in error output...
     maxDiff = None
 
+    def setUp(self):
+        self.error_format = """Usage: %s assign-task <task_id> <hostname>
+(Specify the --help global option for a list of other help options)
+
+%s: error: {message}
+""" % (self.progname, self.progname)
+
     @mock.patch('sys.stdout', new_callable=six.StringIO)
     @mock.patch('koji_cli.commands.activate_session')
     def test_handle_assign_task(
@@ -43,10 +51,11 @@ class TestAssignTask(unittest.TestCase):
         arguments.append("--force")
         session.getHost.return_value = hostname
         session.hasPerm.return_value = False
-        handle_assign_task(options, session, arguments)
-        actual = stdout.getvalue()
-        expected = "This action requires admin privileges\n"
-        self.assertMultiLineEqual(actual, expected)
+        self.assert_system_exit(
+            handle_assign_task,
+            options, session, arguments,
+            stderr=self.format_error_message("This action requires admin privileges")
+        )
 
         # Clean stdout buffer
         stdout.truncate(0)
@@ -82,33 +91,24 @@ class TestAssignTask(unittest.TestCase):
             self, activate_session_mock, stderr, stdout):
         arguments = []
         options = mock.MagicMock()
-        progname = os.path.basename(sys.argv[0]) or 'koji'
 
         # Mock out the xmlrpc server
         session = mock.MagicMock()
 
         # Run it and check immediate output
-        with self.assertRaises(SystemExit) as cm:
-            handle_assign_task(options, session, arguments)
-        actual_stdout = stdout.getvalue()
-        actual_stderr = stderr.getvalue()
-        expected_stdout = ''
-        expected_stderr = """Usage: %s assign-task task_id hostname
-(Specify the --help global option for a list of other help options)
-
-%s: error: please specify a task id and a hostname
-""" % (progname, progname)
-        self.assertMultiLineEqual(actual_stdout, expected_stdout)
-        self.assertMultiLineEqual(actual_stderr, expected_stderr)
+        self.assert_system_exit(
+            handle_assign_task,
+            options, session, arguments,
+            stdout='',
+            stderr=self.format_error_message('please specify a task id and a hostname'),
+            activate_session=None,
+            exit_code=2
+        )
 
         # Finally, assert that things were called as we expected.
         activate_session_mock.assert_not_called()
         session.hasHost.assert_not_called()
         session.addHost.assert_not_called()
-        if isinstance(cm.exception, int):
-            self.assertEqual(cm.exception, 2)
-        else:
-            self.assertEqual(cm.exception.code, 2)
 
 
 if __name__ == '__main__':
diff --git a/tests/test_cli/test_block_group.py b/tests/test_cli/test_block_group.py
index feee8f9..de83739 100644
--- a/tests/test_cli/test_block_group.py
+++ b/tests/test_cli/test_block_group.py
@@ -117,12 +117,16 @@ class TestBlockGroup(utils.CliTestCase):
                 session,
                 args,
                 stderr=expected,
-                activate_session=None)
+                activate_session=None,
+                exit_code=2)
 
         # if we don't have 'admin' permission
         session.hasPerm.return_value = False
-        rv = handle_block_group(options, session, ['tag', 'grp'])
-        self.assert_console_message(
-            stdout, 'This action requires tag or admin privileges\n')
-        self.assertEqual(rv, 1)
+        self.assert_system_exit(
+            handle_block_group,
+            options, session, ['tag', 'grp'],
+            stderr=self.format_error_message('This action requires tag or admin privileges'),
+            stdout='',
+            exit_code=2,
+            activate_session=None)
         activate_session_mock.assert_called_with(session, options)

From 8c4bec61c967aedf5fcd169f116add5f1562fa08 Mon Sep 17 00:00:00 2001
From: Tomas Kopecek <tkopecek@redhat.com>
Date: Dec 10 2019 09:19:04 +0000
Subject: [PATCH 2/7] remove asserts


they shouldn't be needed if parser.error is used everywhere

---

diff --git a/cli/koji_cli/commands.py b/cli/koji_cli/commands.py
index 10c1754..68321b0 100644
--- a/cli/koji_cli/commands.py
+++ b/cli/koji_cli/commands.py
@@ -59,14 +59,12 @@ def handle_add_group(goptions, session, args):
     (options, args) = parser.parse_args(args)
     if len(args) != 2:
         parser.error(_("Please specify a tag name and a group name"))
-        assert False  # pragma: no cover
     tag = args[0]
     group = args[1]
 
     activate_session(session, goptions)
     if not (session.hasPerm('admin') or session.hasPerm('tag')):
         parser.error(_("This action requires tag or admin privileges"))
-        assert False  # pragma: no cover
 
     dsttag = session.getTag(tag)
     if not dsttag:
@@ -90,14 +88,12 @@ def handle_block_group(goptions, session, args):
     (options, args) = parser.parse_args(args)
     if len(args) != 2:
         parser.error(_("Please specify a tag name and a group name"))
-        assert False  # pragma: no cover
     tag = args[0]
     group = args[1]
 
     activate_session(session, goptions)
     if not (session.hasPerm('admin') or session.hasPerm('tag')):
         parser.error(_("This action requires tag or admin privileges"))
-        assert False  # pragma: no cover
 
     dsttag = session.getTag(tag)
     if not dsttag:
@@ -121,7 +117,6 @@ def handle_remove_group(goptions, session, args):
     (options, args) = parser.parse_args(args)
     if len(args) != 2:
         parser.error(_("Please specify a tag name and a group name"))
-        assert False  # pragma: no cover
     tag = args[0]
     group = args[1]
 
@@ -171,7 +166,6 @@ def handle_assign_task(goptions, session, args):
     activate_session(session, goptions)
     if not session.hasPerm('admin'):
         parser.error(_("This action requires admin privileges"))
-        assert False  # pragma: no cover
 
     ret = session.assignTask(task_id, hostname, force)
     if ret:
@@ -189,7 +183,6 @@ def handle_add_host(goptions, session, args):
     (options, args) = parser.parse_args(args)
     if len(args) < 2:
         parser.error(_("Please specify a hostname and at least one arch"))
-        assert False  # pragma: no cover
     host = args[0]
     activate_session(session, goptions)
     id = session.getHost(host)
@@ -260,7 +253,6 @@ def handle_add_host_to_channel(goptions, session, args):
     (options, args) = parser.parse_args(args)
     if not options.list and len(args) != 2:
         parser.error(_("Please specify a hostname and a channel"))
-        assert False  # pragma: no cover
     activate_session(session, goptions)
     if options.list:
         for channel in session.listChannels():
@@ -291,7 +283,6 @@ def handle_remove_host_from_channel(goptions, session, args):
     (options, args) = parser.parse_args(args)
     if len(args) != 2:
         parser.error(_("Please specify a hostname and a channel"))
-        assert False  # pragma: no cover
     host = args[0]
     activate_session(session, goptions)
     hostinfo = session.getHost(host)
@@ -317,7 +308,6 @@ def handle_remove_channel(goptions, session, args):
     (options, args) = parser.parse_args(args)
     if len(args) != 1:
         parser.error(_("Incorrect number of arguments"))
-        assert False  # pragma: no cover
     activate_session(session, goptions)
     cinfo = session.getChannel(args[0])
     if not cinfo:
@@ -334,7 +324,6 @@ def handle_rename_channel(goptions, session, args):
     (options, args) = parser.parse_args(args)
     if len(args) != 2:
         parser.error(_("Incorrect number of arguments"))
-        assert False  # pragma: no cover
     activate_session(session, goptions)
     cinfo = session.getChannel(args[0])
     if not cinfo:
@@ -354,10 +343,8 @@ def handle_add_pkg(goptions, session, args):
     (options, args) = parser.parse_args(args)
     if len(args) < 2:
         parser.error(_("Please specify a tag and at least one package"))
-        assert False  # pragma: no cover
     if not options.owner:
         parser.error(_("Please specify an owner for the package(s)"))
-        assert False  # pragma: no cover
     if not session.getUser(options.owner):
         print("User %s does not exist" % options.owner)
         return 1
@@ -399,7 +386,6 @@ def handle_block_pkg(goptions, session, args):
     (options, args) = parser.parse_args(args)
     if len(args) < 2:
         parser.error(_("Please specify a tag and at least one package"))
-        assert False  # pragma: no cover
     activate_session(session, goptions)
     tag = args[0]
     # check if list of packages exists for that tag already
@@ -436,7 +422,6 @@ def handle_remove_pkg(goptions, session, args):
     (options, args) = parser.parse_args(args)
     if len(args) < 2:
         parser.error(_("Please specify a tag and at least one package"))
-        assert False  # pragma: no cover
     activate_session(session, goptions)
     tag = args[0]
     opts = {}
@@ -487,7 +472,6 @@ def handle_build(options, session, args):
     (build_opts, args) = parser.parse_args(args)
     if len(args) != 2:
         parser.error(_("Exactly two arguments (a build target and a SCM URL or srpm file) are required"))
-        assert False  # pragma: no cover
     if build_opts.arch_override and not build_opts.scratch:
         parser.error(_("--arch_override is only allowed for --scratch builds"))
     activate_session(session, options)
@@ -556,7 +540,6 @@ def handle_chain_build(options, session, args):
     (build_opts, args) = parser.parse_args(args)
     if len(args) < 2:
         parser.error(_("At least two arguments (a build target and a SCM URL) are required"))
-        assert False  # pragma: no cover
     activate_session(session, options)
     target = args[0]
     build_target = session.getBuildTarget(target)
@@ -806,7 +789,6 @@ def handle_maven_chain(options, session, args):
     (build_opts, args) = parser.parse_args(args)
     if len(args) < 2:
         parser.error(_("Two arguments (a build target and a config file) are required"))
-        assert False  # pragma: no cover
     activate_session(session, options)
     target = args[0]
     build_target = session.getBuildTarget(target)
@@ -853,7 +835,6 @@ def handle_resubmit(goptions, session, args):
     (options, args) = parser.parse_args(args)
     if len(args) != 1:
         parser.error(_("Please specify a single task ID"))
-        assert False  # pragma: no cover
     activate_session(session, goptions)
     taskID = int(args[0])
     if not options.quiet:
@@ -881,7 +862,6 @@ def handle_call(goptions, session, args):
     (options, args) = parser.parse_args(args)
     if len(args) < 1:
         parser.error(_("Please specify the name of the XML-RPC method"))
-        assert False  # pragma: no cover
     if options.kwargs:
         options.python = True
     if options.python and ast is None:
@@ -1017,7 +997,6 @@ def anon_handle_mock_config(goptions, session, args):
             opts['repoid'] = repo['id']
     else:
         parser.error(_("Please specify one of: --tag, --target, --task, --buildroot"))
-        assert False  # pragma: no cover
     if options.name:
         name = options.name
     else:
@@ -1125,7 +1104,6 @@ def handle_restart_hosts(options, session, args):
 
     if len(args) > 0:
         parser.error(_("restart-hosts does not accept arguments"))
-        assert False  # pragma: no cover
 
     activate_session(session, options)
 
@@ -1175,7 +1153,6 @@ def handle_import(goptions, session, args):
     (options, args) = parser.parse_args(args)
     if len(args) < 1:
         parser.error(_("At least one package must be specified"))
-        assert False  # pragma: no cover
     if options.src_epoch in ('None', 'none', '(none)'):
         options.src_epoch = None
     elif options.src_epoch:
@@ -1183,7 +1160,6 @@ def handle_import(goptions, session, args):
             options.src_epoch = int(options.src_epoch)
         except (ValueError, TypeError):
             parser.error(_("Invalid value for epoch: %s") % options.src_epoch)
-            assert False  # pragma: no cover
     activate_session(session, goptions)
     to_import = {}
     for path in args:
@@ -1326,10 +1302,8 @@ def handle_import_cg(goptions, session, args):
     (options, args) = parser.parse_args(args)
     if len(args) < 2:
         parser.error(_("Please specify metadata files directory"))
-        assert False  # pragma: no cover
     if json is None:
         parser.error(_("Unable to find json module"))
-        assert False  # pragma: no cover
     activate_session(session, goptions)
     metadata = json.load(open(args[0], 'r'))
     if 'output' not in metadata:
@@ -1379,7 +1353,6 @@ def handle_import_comps(goptions, session, args):
     (local_options, args) = parser.parse_args(args)
     if len(args) != 2:
         parser.error(_("Incorrect number of arguments"))
-        assert False  # pragma: no cover
     activate_session(session, goptions)
     # check if the tag exists
     dsttag = session.getTag(args[1])
@@ -1479,7 +1452,6 @@ def handle_import_sig(goptions, session, args):
     (options, args) = parser.parse_args(args)
     if len(args) < 1:
         parser.error(_("At least one package must be specified"))
-        assert False  # pragma: no cover
     for path in args:
         if not os.path.exists(path):
             parser.error(_("No such file: %s") % path)
@@ -1538,10 +1510,8 @@ def handle_write_signed_rpm(goptions, session, args):
     (options, args) = parser.parse_args(args)
     if len(args) < 1:
         parser.error(_("A signature key must be specified"))
-        assert False  # pragma: no cover
     if len(args) < 2 and not (options.all or options.buildid):
         parser.error(_("At least one RPM must be specified"))
-        assert False  # pragma: no cover
     key = args.pop(0)
     activate_session(session, goptions)
     if options.all:
@@ -1643,7 +1613,6 @@ def handle_prune_signed_copies(options, session, args):
         binfo = session.getBuild(options.build)
         if not binfo:
             parser.error('No such build: %s' % options.build)
-            assert False  # pragma: no cover
         builds = [("%(name)s-%(version)s-%(release)s" % binfo, binfo)]
     total_files = 0
     total_space = 0
@@ -1991,7 +1960,6 @@ def handle_list_permissions(goptions, session, args):
     (options, args) = parser.parse_args(args)
     if len(args) > 0:
         parser.error(_("This command takes no arguments"))
-        assert False  # pragma: no cover
     activate_session(session, goptions)
     if options.user:
         user = session.getUser(options.user)
@@ -2181,30 +2149,24 @@ def handle_import_archive(options, session, args):
 
     if not len(args) > 1:
         parser.error(_("You must specify a build ID or N-V-R and an archive to import"))
-        assert False  # pragma: no cover
 
     activate_session(session, options)
 
     if not suboptions.type:
         parser.error(_("You must specify an archive type"))
-        assert False  # pragma: no cover
     if suboptions.type == 'maven':
         if not (session.hasPerm('maven-import') or session.hasPerm('admin')):
             parser.error(_("This action requires the maven-import privilege"))
-            assert False  # pragma: no cover
         if not suboptions.type_info:
             parser.error(_("--type-info must point to a .pom file when importing Maven archives"))
-            assert False  # pragma: no cover
         pom_info = koji.parse_pom(suboptions.type_info)
         maven_info = koji.pom_to_maven_info(pom_info)
         suboptions.type_info = maven_info
     elif suboptions.type == 'win':
         if not (session.hasPerm('win-import') or session.hasPerm('admin')):
             parser.error(_("This action requires the win-import privilege"))
-            assert False  # pragma: no cover
         if not suboptions.type_info:
             parser.error(_("--type-info must be specified"))
-            assert False  # pragma: no cover
         type_info = suboptions.type_info.split(':', 2)
         if len(type_info) < 2:
             parser.error(_("--type-info must be in relpath:platforms[:flags] format"))
@@ -2217,15 +2179,12 @@ def handle_import_archive(options, session, args):
     elif suboptions.type == 'image':
         if not (session.hasPerm('image-import') or session.hasPerm('admin')):
             parser.error(_("This action requires the image-import privilege"))
-            assert False  # pragma: no cover
         if not suboptions.type_info:
             parser.error(_("--type-info must be specified"))
-            assert False  # pragma: no cover
         image_info = {'arch': suboptions.type_info}
         suboptions.type_info = image_info
     else:
         parser.error(_("Unsupported archive type: %s" % suboptions.type))
-        assert False  # pragma: no cover
 
     buildinfo = session.getBuild(arg_filter(args[0]))
     if not buildinfo:
@@ -2277,7 +2236,6 @@ def handle_grant_permission(goptions, session, args):
     (options, args) = parser.parse_args(args)
     if len(args) < 2:
         parser.error(_("Please specify a permission and at least one user"))
-        assert False  # pragma: no cover
     activate_session(session, goptions)
     perm = args[0]
     names = args[1:]
@@ -2286,7 +2244,6 @@ def handle_grant_permission(goptions, session, args):
         user = session.getUser(n)
         if user is None:
             parser.error(_("No such user: %s" % n))
-            assert False  # pragma: no cover
         users.append(user)
     kwargs = {}
     if options.new:
@@ -2303,7 +2260,6 @@ def handle_revoke_permission(goptions, session, args):
     (options, args) = parser.parse_args(args)
     if len(args) < 2:
         parser.error(_("Please specify a permission and at least one user"))
-        assert False  # pragma: no cover
     activate_session(session, goptions)
     perm = args[0]
     names = args[1:]
@@ -2312,7 +2268,6 @@ def handle_revoke_permission(goptions, session, args):
         user = session.getUser(n)
         if user is None:
             parser.error(_("No such user: %s" % n))
-            assert False  # pragma: no cover
         users.append(user)
     for user in users:
         session.revokePermission(user['name'], perm)
@@ -2327,14 +2282,12 @@ def handle_grant_cg_access(goptions, session, args):
     (options, args) = parser.parse_args(args)
     if len(args) != 2:
         parser.error(_("Please specify a user and content generator"))
-        assert False  # pragma: no cover
     activate_session(session, goptions)
     user = args[0]
     cg = args[1]
     uinfo = session.getUser(user)
     if uinfo is None:
         parser.error(_("No such user: %s" % user))
-        assert False  # pragma: no cover
     kwargs = {}
     if options.new:
         kwargs['create'] = True
@@ -2349,14 +2302,12 @@ def handle_revoke_cg_access(goptions, session, args):
     (options, args) = parser.parse_args(args)
     if len(args) != 2:
         parser.error(_("Please specify a user and content generator"))
-        assert False  # pragma: no cover
     activate_session(session, goptions)
     user = args[0]
     cg = args[1]
     uinfo = session.getUser(user)
     if uinfo is None:
         parser.error(_("No such user: %s" % user))
-        assert False  # pragma: no cover
     session.revokeCGAccess(uinfo['name'], cg)
 
 
@@ -2374,18 +2325,15 @@ def anon_handle_latest_build(goptions, session, args):
     (options, args) = parser.parse_args(args)
     if len(args) == 0:
         parser.error(_("A tag name must be specified"))
-        assert False  # pragma: no cover
     activate_session(session, goptions)
     if options.all:
         if len(args) > 1:
             parser.error(_("A package name may not be combined with --all"))
-            assert False  # pragma: no cover
         # Set None as the package argument
         args.append(None)
     else:
         if len(args) < 2:
             parser.error(_("A tag name and package name must be specified"))
-            assert False  # pragma: no cover
     pathinfo = koji.PathInfo()
 
     for pkg in args[1:]:
@@ -2443,7 +2391,6 @@ def anon_handle_list_api(goptions, session, args):
     (options, args) = parser.parse_args(args)
     if len(args) != 0:
         parser.error(_("This command takes no arguments"))
-        assert False  # pragma: no cover
     activate_session(session, goptions)
     tmplist = [(x['name'], x) for x in session._listapi()]
     tmplist.sort()
@@ -2488,10 +2435,8 @@ def anon_handle_list_tagged(goptions, session, args):
     (options, args) = parser.parse_args(args)
     if len(args) == 0:
         parser.error(_("A tag name must be specified"))
-        assert False  # pragma: no cover
     elif len(args) > 2:
         parser.error(_("Only one package name may be specified"))
-        assert False  # pragma: no cover
     activate_session(session, goptions)
     pathinfo = koji.PathInfo()
     package = None
@@ -2589,7 +2534,6 @@ def anon_handle_list_buildroot(goptions, session, args):
     (options, args) = parser.parse_args(args)
     if len(args) != 1:
         parser.error(_("Incorrect number of arguments"))
-        assert False  # pragma: no cover
     activate_session(session, goptions)
     buildrootID = int(args[0])
     opts = {}
@@ -2619,7 +2563,6 @@ def anon_handle_list_untagged(goptions, session, args):
     (options, args) = parser.parse_args(args)
     if len(args) > 1:
         parser.error(_("Only one package name may be specified"))
-        assert False  # pragma: no cover
     activate_session(session, goptions)
     package = None
     if len(args) > 0:
@@ -2685,7 +2628,6 @@ def anon_handle_list_groups(goptions, session, args):
     (options, args) = parser.parse_args(args)
     if len(args) < 1 or len(args) > 2:
         parser.error(_("Incorrect number of arguments"))
-        assert False  # pragma: no cover
     opts = {}
     if options.incl_blocked:
         opts['incl_blocked'] = True
@@ -2723,7 +2665,6 @@ def handle_add_group_pkg(goptions, session, args):
     (options, args) = parser.parse_args(args)
     if len(args) < 3:
         parser.error(_("You must specify a tag name, group name, and one or more package names"))
-        assert False  # pragma: no cover
     tag = args[0]
     group = args[1]
     activate_session(session, goptions)
@@ -2741,7 +2682,6 @@ def handle_block_group_pkg(goptions, session, args):
     (options, args) = parser.parse_args(args)
     if len(args) < 3:
         parser.error(_("You must specify a tag name, group name, and one or more package names"))
-        assert False  # pragma: no cover
     tag = args[0]
     group = args[1]
     activate_session(session, goptions)
@@ -2757,7 +2697,6 @@ def handle_unblock_group_pkg(goptions, session, args):
     (options, args) = parser.parse_args(args)
     if len(args) < 3:
         parser.error(_("You must specify a tag name, group name, and one or more package names"))
-        assert False  # pragma: no cover
     tag = args[0]
     group = args[1]
     activate_session(session, goptions)
@@ -2773,7 +2712,6 @@ def handle_add_group_req(goptions, session, args):
     (options, args) = parser.parse_args(args)
     if len(args) != 3:
         parser.error(_("You must specify a tag name and two group names"))
-        assert False  # pragma: no cover
     tag = args[0]
     group = args[1]
     req = args[2]
@@ -2789,7 +2727,6 @@ def handle_block_group_req(goptions, session, args):
     (options, args) = parser.parse_args(args)
     if len(args) != 3:
         parser.error(_("You must specify a tag name and two group names"))
-        assert False  # pragma: no cover
     tag = args[0]
     group = args[1]
     req = args[2]
@@ -2805,7 +2742,6 @@ def handle_unblock_group_req(goptions, session, args):
     (options, args) = parser.parse_args(args)
     if len(args) != 3:
         parser.error(_("You must specify a tag name and two group names"))
-        assert False  # pragma: no cover
     tag = args[0]
     group = args[1]
     req = args[2]
@@ -2875,7 +2811,6 @@ def anon_handle_list_hosts(goptions, session, args):
         channel = session.getChannel(options.channel)
         if not channel:
             parser.error(_('Unknown channel: %s' % options.channel))
-            assert False  # pragma: no cover
         opts['channelID'] = channel['id']
     if options.ready is not None:
         opts['ready'] = options.ready
@@ -2947,20 +2882,17 @@ def anon_handle_list_pkgs(goptions, session, args):
     (options, args) = parser.parse_args(args)
     if len(args) != 0:
         parser.error(_("This command takes no arguments"))
-        assert False  # pragma: no cover
     activate_session(session, goptions)
     opts = {}
     if options.owner:
         user = session.getUser(options.owner)
         if user is None:
             parser.error(_("Invalid user"))
-            assert False  # pragma: no cover
         opts['userID'] = user['id']
     if options.tag:
         tag = session.getTag(options.tag)
         if tag is None:
             parser.error(_("Invalid tag"))
-            assert False  # pragma: no cover
         opts['tagID'] = tag['id']
     if options.package:
         opts['pkgID'] = options.package
@@ -3042,7 +2974,6 @@ def anon_handle_list_builds(goptions, session, args):
     (options, args) = parser.parse_args(args)
     if len(args) != 0:
         parser.error(_("This command takes no arguments"))
-        assert False  # pragma: no cover
     activate_session(session, goptions)
     opts = {}
     for key in ('type', 'prefix'):
@@ -3056,7 +2987,6 @@ def anon_handle_list_builds(goptions, session, args):
             package = session.getPackageID(options.package)
             if package is None:
                 parser.error(_("Invalid package"))
-                assert False  # pragma: no cover
             opts['packageID'] = package
     if options.owner:
         try:
@@ -3065,7 +2995,6 @@ def anon_handle_list_builds(goptions, session, args):
             user = session.getUser(options.owner)
             if user is None:
                 parser.error(_("Invalid owner"))
-                assert False  # pragma: no cover
             opts['userID'] = user['id']
     if options.volume:
         try:
@@ -3078,21 +3007,18 @@ def anon_handle_list_builds(goptions, session, args):
                     volumeID = volume['id']
             if volumeID is None:
                 parser.error(_("Invalid volume"))
-                assert False  # pragma: no cover
             opts['volumeID'] = volumeID
     if options.state:
         try:
             state = int(options.state)
             if state > 4 or state < 0:
                 parser.error(_("Invalid state"))
-                assert False  # pragma: no cover
             opts['state'] = state
         except ValueError:
             try:
                 opts['state'] = koji.BUILD_STATES[options.state]
             except KeyError:
                 parser.error(_("Invalid state"))
-                assert False  # pragma: no cover
     for opt in ('before', 'after'):
         val = getattr(options, opt)
         if not val:
@@ -3121,14 +3047,12 @@ def anon_handle_list_builds(goptions, session, args):
         data = [session.getBuild(buildid)]
         if data is None:
             parser.error(_("Invalid build ID"))
-            assert False  # pragma: no cover
     else:
         # Check filter exists
         if any(opts):
             data = session.listBuilds(**opts)
         else:
             parser.error(_("Filter must be provided for list"))
-            assert False  # pragma: no cover
     if not options.sort_key:
         options.sort_key = ['nvr']
     data = sorted(data, key=lambda b: [b.get(k) for k in options.sort_key],
@@ -3154,7 +3078,6 @@ def anon_handle_rpminfo(goptions, session, args):
     (options, args) = parser.parse_args(args)
     if len(args) < 1:
         parser.error(_("Please specify an RPM"))
-        assert False  # pragma: no cover
     activate_session(session, goptions)
     for rpm in args:
         info = session.getRPM(rpm)
@@ -3223,7 +3146,6 @@ def anon_handle_buildinfo(goptions, session, args):
     (options, args) = parser.parse_args(args)
     if len(args) < 1:
         parser.error(_("Please specify a build"))
-        assert False  # pragma: no cover
     activate_session(session, goptions)
     for build in args:
         if build.isdigit():
@@ -3315,7 +3237,6 @@ def anon_handle_hostinfo(goptions, session, args):
     (options, args) = parser.parse_args(args)
     if len(args) < 1:
         parser.error(_("Please specify a host"))
-        assert False  # pragma: no cover
     activate_session(session, goptions)
     for host in args:
         if host.isdigit():
@@ -3404,12 +3325,10 @@ def handle_clone_tag(goptions, session, args):
 
     if len(args) != 2:
         parser.error(_("This command takes two arguments: <src-tag> <dst-tag>"))
-        assert False  # pragma: no cover
     activate_session(session, goptions)
 
     if not options.test and not (session.hasPerm('admin') or session.hasPerm('tag')):
         parser.error(_("This action requires tag or admin privileges"))
-        assert False  # pragma: no cover
 
     if args[0] == args[1]:
         parser.error(_('Source and destination tags must be different.'))
@@ -3849,10 +3768,8 @@ def handle_add_target(goptions, session, args):
     (options, args) = parser.parse_args(args)
     if len(args) < 2:
         parser.error(_("Please specify a target name, a build tag, and destination tag"))
-        assert False  # pragma: no cover
     elif len(args) > 3:
         parser.error(_("Incorrect number of arguments"))
-        assert False  # pragma: no cover
     name = args[0]
     build_tag = args[1]
     if len(args) > 2:
@@ -3863,7 +3780,6 @@ def handle_add_target(goptions, session, args):
     activate_session(session, goptions)
     if not (session.hasPerm('admin') or session.hasPerm('target')):
         parser.error(_("This action requires target or admin privileges"))
-        assert False  # pragma: no cover
 
     chkbuildtag = session.getTag(build_tag)
     chkdesttag = session.getTag(dest_tag)
@@ -3893,12 +3809,10 @@ def handle_edit_target(goptions, session, args):
 
     if len(args) != 1:
         parser.error(_("Please specify a build target"))
-        assert False  # pragma: no cover
     activate_session(session, goptions)
 
     if not (session.hasPerm('admin') or session.hasPerm('target')):
         parser.error(_("This action requires target or admin privileges"))
-        assert False  # pragma: no cover
 
     targetInfo = session.getBuildTarget(args[0])
     if targetInfo == None:
@@ -3936,12 +3850,10 @@ def handle_remove_target(goptions, session, args):
 
     if len(args) != 1:
         parser.error(_("Please specify a build target to remove"))
-        assert False  # pragma: no cover
     activate_session(session, goptions)
 
     if not (session.hasPerm('admin') or session.hasPerm('target')):
         parser.error(_("This action requires target or admin privileges"))
-        assert False  # pragma: no cover
 
     target = args[0]
     target_info = session.getBuildTarget(target)
@@ -3961,12 +3873,10 @@ def handle_remove_tag(goptions, session, args):
 
     if len(args) != 1:
         parser.error(_("Please specify a tag to remove"))
-        assert False  # pragma: no cover
     activate_session(session, goptions)
 
     if not (session.hasPerm('admin') or session.hasPerm('tag')):
         parser.error(_("This action requires tag or admin privileges"))
-        assert False  # pragma: no cover
 
     tag = args[0]
     tag_info = session.getTag(tag)
@@ -3988,7 +3898,6 @@ def anon_handle_list_targets(goptions, session, args):
     (options, args) = parser.parse_args(args)
     if len(args) != 0:
         parser.error(_("This command takes no arguments"))
-        assert False  # pragma: no cover
     activate_session(session, goptions)
 
     fmt = "%(name)-30s %(build_tag_name)-30s %(dest_tag_name)-30s"
@@ -4059,7 +3968,6 @@ def anon_handle_list_tag_inheritance(goptions, session, args):
     (options, args) = parser.parse_args(args)
     if len(args) != 1:
         parser.error(_("This command takes exctly one argument: a tag name or ID"))
-        assert False  # pragma: no cover
     activate_session(session, goptions)
     event = koji.util.eventFromOpts(session, options)
     if event:
@@ -4121,13 +4029,11 @@ def anon_handle_list_tags(goptions, session, args):
         pkginfo = session.getPackage(options.package)
         if not pkginfo:
             parser.error(_("Invalid package %s" % options.package))
-            assert False  # pragma: no cover
 
     if options.build:
         buildinfo = session.getBuild(options.build)
         if not buildinfo:
             parser.error(_("Invalid build %s" % options.build))
-            assert False  # pragma: no cover
 
     tags = session.listTags(buildinfo.get('id',None), pkginfo.get('id',None))
     tags.sort(key=lambda x: x['name'])
@@ -4171,7 +4077,6 @@ def anon_handle_list_tag_history(goptions, session, args):
     (options, args) = parser.parse_args(args)
     if len(args) != 0:
         parser.error(_("This command takes no arguments"))
-        assert False  # pragma: no cover
     kwargs = {}
     limited = False
     if options.package:
@@ -4489,7 +4394,6 @@ def anon_handle_list_history(goptions, session, args):
     (options, args) = parser.parse_args(args)
     if len(args) != 0:
         parser.error(_("This command takes no arguments"))
-        assert False  # pragma: no cover
     kwargs = {}
     limited = False
     for opt in ('before', 'after'):
@@ -4845,7 +4749,6 @@ def anon_handle_taskinfo(goptions, session, args):
     (options, args) = parser.parse_args(args)
     if len(args) < 1:
         parser.error(_("You must specify at least one task ID"))
-        assert False  # pragma: no cover
 
     activate_session(session, goptions)
 
@@ -4865,7 +4768,6 @@ def anon_handle_taginfo(goptions, session, args):
     (options, args) = parser.parse_args(args)
     if len(args) < 1:
         parser.error(_("Please specify a tag"))
-        assert False  # pragma: no cover
     activate_session(session, goptions)
     event = koji.util.eventFromOpts(session, options)
     event_opts = {}
@@ -4962,11 +4864,9 @@ def handle_add_tag(goptions, session, args):
     (options, args) = parser.parse_args(args)
     if len(args) != 1:
         parser.error(_("Please specify a name for the tag"))
-        assert False  # pragma: no cover
     activate_session(session, goptions)
     if not (session.hasPerm('admin') or session.hasPerm('tag')):
         parser.error(_("This action requires tag or admin privileges"))
-        assert False  # pragma: no cover
     opts = {}
     if options.parent:
         opts['parent'] = options.parent
@@ -5008,7 +4908,6 @@ def handle_edit_tag(goptions, session, args):
     (options, args) = parser.parse_args(args)
     if len(args) != 1:
         parser.error(_("Please specify a name for the tag"))
-        assert False  # pragma: no cover
     activate_session(session, goptions)
     tag = args[0]
     opts = {}
@@ -5057,7 +4956,6 @@ def handle_lock_tag(goptions, session, args):
     (options, args) = parser.parse_args(args)
     if len(args) < 1:
         parser.error(_("Please specify a tag"))
-        assert False  # pragma: no cover
     activate_session(session, goptions)
     pdata = session.getAllPerms()
     perm_ids = dict([(p['name'], p['id']) for p in pdata])
@@ -5106,7 +5004,6 @@ def handle_unlock_tag(goptions, session, args):
     (options, args) = parser.parse_args(args)
     if len(args) < 1:
         parser.error(_("Please specify a tag"))
-        assert False  # pragma: no cover
     activate_session(session, goptions)
     if options.glob:
         selected = []
@@ -5123,7 +5020,6 @@ def handle_unlock_tag(goptions, session, args):
             tag = session.getTag(name)
             if tag is None:
                 parser.error(_("No such tag: %s") % name)
-                assert False  # pragma: no cover
             selected.append(tag)
         selected = [session.getTag(name) for name in args]
     for tag in selected:
@@ -5157,7 +5053,6 @@ def handle_add_tag_inheritance(goptions, session, args):
 
     if len(args) != 2:
         parser.error(_("This command takes exctly two argument: a tag name or ID and that tag's new parent name or ID"))
-        assert False  # pragma: no cover
 
     activate_session(session, goptions)
 
@@ -5212,11 +5107,9 @@ def handle_edit_tag_inheritance(goptions, session, args):
 
     if len(args) < 1:
         parser.error(_("This command takes at least one argument: a tag name or ID"))
-        assert False  # pragma: no cover
 
     if len(args) > 3:
         parser.error(_("This command takes at most three argument: a tag name or ID, a parent tag name or ID, and a priority"))
-        assert False  # pragma: no cover
 
     activate_session(session, goptions)
 
@@ -5295,11 +5188,9 @@ def handle_remove_tag_inheritance(goptions, session, args):
 
     if len(args) < 1:
         parser.error(_("This command takes at least one argument: a tag name or ID"))
-        assert False  # pragma: no cover
 
     if len(args) > 3:
         parser.error(_("This command takes at most three argument: a tag name or ID, a parent tag name or ID, and a priority"))
-        assert False  # pragma: no cover
 
     activate_session(session, goptions)
 
@@ -5363,7 +5254,6 @@ def anon_handle_show_groups(goptions, session, args):
     (options, args) = parser.parse_args(args)
     if len(args) != 1:
         parser.error(_("Incorrect number of arguments"))
-        assert False  # pragma: no cover
     if options.incl_blocked and (options.comps or options.spec):
         parser.error(_("--show-blocked doesn't make sense for comps/spec output"))
     activate_session(session, goptions)
@@ -5400,7 +5290,6 @@ def anon_handle_list_external_repos(goptions, session, args):
     (options, args) = parser.parse_args(args)
     if len(args) > 0:
         parser.error(_("This command takes no arguments"))
-        assert False  # pragma: no cover
     activate_session(session, goptions)
     opts = {}
     event = koji.util.eventFromOpts(session, options)
@@ -5415,7 +5304,6 @@ def anon_handle_list_external_repos(goptions, session, args):
         if opts['repo_info']:
             if options.inherit:
                 parser.error(_("Can't select by repo when using --inherit"))
-                assert False  # pragma: no cover
         if options.inherit:
             del opts['repo_info']
             data = session.getExternalRepoList(**opts)
@@ -5512,7 +5400,6 @@ def handle_add_external_repo(goptions, session, args):
         print("Created external repo %(id)i" % rinfo)
     else:
         parser.error(_("Incorrect number of arguments"))
-        assert False  # pragma: no cover
     if options.tag:
         for tagpri in options.tag:
             tag, priority = _parse_tagpri(tagpri)
@@ -5539,8 +5426,6 @@ def handle_edit_external_repo(goptions, session, args):
     (options, args) = parser.parse_args(args)
     if len(args) != 1:
         parser.error(_("Incorrect number of arguments"))
-        parser.error(_("This command takes no arguments"))
-        assert False  # pragma: no cover
     opts = {}
     if options.url:
         opts['url'] = options.url
@@ -5562,7 +5447,6 @@ def handle_remove_external_repo(goptions, session, args):
     (options, args) = parser.parse_args(args)
     if len(args) < 1:
         parser.error(_("Incorrect number of arguments"))
-        assert False  # pragma: no cover
     activate_session(session, goptions)
     repo = args[0]
     tags = args[1:]
@@ -5573,7 +5457,6 @@ def handle_remove_external_repo(goptions, session, args):
         delete = False
         if tags:
             parser.error(_("Do not specify tags when using --alltags"))
-            assert False  # pragma: no cover
         if not current_tags:
             print(_("External repo %s not associated with any tags") % repo)
             return 0
@@ -5636,7 +5519,6 @@ def handle_spin_livecd(options, session, args):
         parser.error(_("Five arguments are required: a name, a version, an" +
                        " architecture, a build target, and a relative path to" +
                        " a kickstart file."))
-        assert False  # pragma: no cover
     if task_options.volid is not None and len(task_options.volid) > 32:
         parser.error(_('Volume ID has a maximum length of 32 characters'))
     return _build_image(options, task_options, session, args, 'livecd')
@@ -5695,7 +5577,6 @@ def handle_spin_livemedia(options, session, args):
         parser.error(_("Five arguments are required: a name, a version, a" +
                        " build target, an architecture, and a relative path to" +
                        " a kickstart file."))
-        assert False  # pragma: no cover
     if task_options.lorax_url is not None and task_options.lorax_dir is None:
         parser.error(_('The "--lorax_url" option requires that "--lorax_dir" '
                        'also be used.'))
@@ -5756,7 +5637,6 @@ def handle_spin_appliance(options, session, args):
         parser.error(_("Five arguments are required: a name, a version, " +
                        "an architecture, a build target, and a relative path" +
                        " to a kickstart file."))
-        assert False  # pragma: no cover
     return _build_image(options, task_options, session, args, 'appliance')
 
 
@@ -6211,7 +6091,6 @@ def handle_win_build(options, session, args):
     (build_opts, args) = parser.parse_args(args)
     if len(args) != 3:
         parser.error(_("Exactly three arguments (a build target, a SCM URL, and a VM name) are required"))
-        assert False  # pragma: no cover
     activate_session(session, options)
     target = args[0]
     if target.lower() == "none" and build_opts.repo_id:
@@ -6280,7 +6159,6 @@ def handle_cancel(goptions, session, args):
     (options, args) = parser.parse_args(args)
     if len(args) == 0:
         parser.error(_("You must specify at least one task id or build"))
-        assert False  # pragma: no cover
     activate_session(session, goptions)
     tlist = []
     blist = []
@@ -6293,7 +6171,6 @@ def handle_cancel(goptions, session, args):
                 blist.append(arg)
             except koji.GenericError:
                 parser.error(_("please specify only task ids (integer) or builds (n-v-r)"))
-                assert False  # pragma: no cover
     if tlist:
         opts = {}
         remote_fn = session.cancelTask
@@ -6319,11 +6196,9 @@ def handle_set_task_priority(goptions, session, args):
     (options, args) = parser.parse_args(args)
     if len(args) == 0:
         parser.error(_("You must specify at least one task id"))
-        assert False  # pragma: no cover
 
     if options.priority is None:
         parser.error(_("You must specify --priority"))
-        assert False  # pragma: no cover
     try:
         tasks = [int(a) for a in args]
     except ValueError:
@@ -6351,7 +6226,6 @@ def handle_list_tasks(goptions, session, args):
     (options, args) = parser.parse_args(args)
     if len(args) != 0:
         parser.error(_("This command takes no arguments"))
-        assert False  # pragma: no cover
 
     activate_session(session, goptions)
     tasklist = _list_tasks(options, session)
@@ -6376,7 +6250,6 @@ def handle_set_pkg_arches(goptions, session, args):
     (options, args) = parser.parse_args(args)
     if len(args) < 3:
         parser.error(_("Please specify an archlist, a tag, and at least one package"))
-        assert False  # pragma: no cover
     activate_session(session, goptions)
     arches = koji.parse_arches(args[0])
     tag = args[1]
@@ -6394,7 +6267,6 @@ def handle_set_pkg_owner(goptions, session, args):
     (options, args) = parser.parse_args(args)
     if len(args) < 3:
         parser.error(_("Please specify an owner, a tag, and at least one package"))
-        assert False  # pragma: no cover
     activate_session(session, goptions)
     owner = args[0]
     tag = args[1]
@@ -6415,10 +6287,8 @@ def handle_set_pkg_owner_global(goptions, session, args):
     if options.old_user:
         if len(args) < 1:
             parser.error(_("Please specify an owner"))
-            assert False  # pragma: no cover
     elif len(args) < 2:
         parser.error(_("Please specify an owner and at least one package"))
-        assert False  # pragma: no cover
     activate_session(session, goptions)
     owner = args[0]
     packages = args[1:]
@@ -6580,7 +6450,6 @@ def handle_tag_build(opts, session, args):
     (options, args) = parser.parse_args(args)
     if len(args) < 2:
         parser.error(_("This command takes at least two arguments: a tag name/ID and one or more package n-v-r's"))
-        assert False  # pragma: no cover
     activate_session(session, opts)
     tasks = []
     for pkg in args[1:]:
@@ -6610,7 +6479,6 @@ def handle_move_build(opts, session, args):
             parser.error(_("This command, with --all, takes at least three arguments: two tags and one or more package names"))
         else:
             parser.error(_("This command takes at least three arguments: two tags and one or more package n-v-r's"))
-        assert False  # pragma: no cover
     activate_session(session, opts)
     tasks = []
     builds = []
@@ -6658,10 +6526,8 @@ def handle_untag_build(goptions, session, args):
     if options.non_latest and options.force:
         if len(args) < 1:
             parser.error(_("Please specify a tag"))
-            assert False  # pragma: no cover
     elif len(args) < 2:
         parser.error(_("This command takes at least two arguments: a tag name/ID and one or more package n-v-r's"))
-        assert False  # pragma: no cover
     activate_session(session, goptions)
     tag = session.getTag(args[0])
     if not tag:
@@ -6723,7 +6589,6 @@ def handle_unblock_pkg(goptions, session, args):
     (options, args) = parser.parse_args(args)
     if len(args) < 2:
         parser.error(_("Please specify a tag and at least one package"))
-        assert False  # pragma: no cover
     activate_session(session, goptions)
     tag = args[0]
     with session.multicall(strict=True) as m:
@@ -6753,10 +6618,8 @@ def anon_handle_download_build(options, session, args):
     (suboptions, args) = parser.parse_args(args)
     if len(args) < 1:
         parser.error(_("Please specify a package N-V-R or build ID"))
-        assert False  # pragma: no cover
     elif len(args) > 1:
         parser.error(_("Only a single package N-V-R or build ID may be specified"))
-        assert False  # pragma: no cover
 
     activate_session(session, options)
     build = args[0]
@@ -7166,13 +7029,11 @@ def handle_regen_repo(options, session, args):
     (suboptions, args) = parser.parse_args(args)
     if len(args) == 0:
         parser.error(_("A tag name must be specified"))
-        assert False  # pragma: no cover
     elif len(args) > 1:
         if suboptions.target:
             parser.error(_("Only a single target may be specified"))
         else:
             parser.error(_("Only a single tag name may be specified"))
-        assert False  # pragma: no cover
     activate_session(session, options)
     tag = args[0]
     repo_opts = {}
@@ -7180,14 +7041,12 @@ def handle_regen_repo(options, session, args):
         info = session.getBuildTarget(tag)
         if not info:
             parser.error(_("No matching build target: " + tag))
-            assert False  # pragma: no cover
         tag = info['build_tag_name']
         info = session.getTag(tag, strict=True)
     else:
         info = session.getTag(tag)
         if not info:
             parser.error(_("No matching tag: " + tag))
-            assert False  # pragma: no cover
         tag = info['name']
         targets = session.getBuildTargets(buildTagID=info['id'])
         if not targets:
@@ -7353,10 +7212,8 @@ def anon_handle_search(options, session, args):
     (options, args) = parser.parse_args(args)
     if len(args) < 1:
         parser.error(_("Please specify search type"))
-        assert False  # pragma: no cover
     if len(args) < 2:
         parser.error(_("Please specify search pattern"))
-        assert False  # pragma: no cover
     type = args[0]
     if type not in _search_types:
         parser.error(_("Unknown search type: %s") % type)
@@ -7378,7 +7235,6 @@ def handle_moshimoshi(options, session, args):
     (opts, args) = parser.parse_args(args)
     if len(args) != 0:
         parser.error(_("This command takes no arguments"))
-        assert False  # pragma: no cover
     activate_session(session, options)
     u = session.getLoggedInUser()
     if not u:

From 6e1da3b90d323df206502c1a8ed10e3c28f33095 Mon Sep 17 00:00:00 2001
From: Tomas Kopecek <tkopecek@redhat.com>
Date: Dec 10 2019 09:19:04 +0000
Subject: [PATCH 3/7] fix translation strings


---

diff --git a/cli/koji_cli/commands.py b/cli/koji_cli/commands.py
index 68321b0..3d0ddc3 100644
--- a/cli/koji_cli/commands.py
+++ b/cli/koji_cli/commands.py
@@ -153,11 +153,11 @@ def handle_assign_task(goptions, session, args):
 
     taskinfo = session.getTaskInfo(task_id, request=False)
     if taskinfo is None:
-        raise koji.GenericError("No such task: %s" % task_id)
+        raise koji.GenericError(_("No such task: %s") % task_id)
 
     hostinfo = session.getHost(hostname)
     if hostinfo is None:
-        raise koji.GenericError("No such host: %s" % hostname)
+        raise koji.GenericError(_("No such host: %s") % hostname)
 
     force = False
     if options.force:
@@ -1898,7 +1898,7 @@ def handle_set_build_volume(goptions, session, args):
     parser.add_option("-v", "--verbose", action="store_true", help=_("Be verbose"))
     (options, args) = parser.parse_args(args)
     if len(args) < 2:
-        parser.error("You must provide a volume and at least one build")
+        parser.error(_("You must provide a volume and at least one build"))
     volinfo = session.getVolume(args[0])
     if not volinfo:
         print("No such volume: %s" % args[0])
@@ -1929,7 +1929,7 @@ def handle_add_volume(goptions, session, args):
     parser = OptionParser(usage=usage)
     (options, args) = parser.parse_args(args)
     if len(args) != 1:
-        parser.error("Command requires exactly one volume-name.")
+        parser.error(_("Command requires exactly one volume-name."))
     name = args[0]
     volinfo = session.getVolume(name)
     if volinfo:
@@ -6959,13 +6959,13 @@ def anon_handle_wait_repo(options, session, args):
     if suboptions.target:
         target_info = session.getBuildTarget(tag)
         if not target_info:
-            parser.error("Invalid build target: %s" % tag)
+            parser.error(_("Invalid build target: %s") % tag)
         tag = target_info['build_tag_name']
         tag_id = target_info['build_tag']
     else:
         tag_info = session.getTag(tag)
         if not tag_info:
-            parser.error("Invalid tag: %s" % tag)
+            parser.error(_("Invalid tag: %s") % tag)
         targets = session.getBuildTargets(buildTagID=tag_info['id'])
         if not targets:
             print("%(name)s is not a build tag for any target" % tag_info)
@@ -7344,7 +7344,7 @@ def handle_add_notification(goptions, session, args):
     activate_session(session, goptions)
 
     if options.user and not session.hasPerm('admin'):
-        parser.error("--user requires admin permission")
+        parser.error(_("--user requires admin permission"))
 
     if options.user:
         user_id = session.getUser(options.user)['id']
@@ -7354,7 +7354,7 @@ def handle_add_notification(goptions, session, args):
     if options.package:
         package_id = session.getPackageID(options.package)
         if package_id is None:
-            parser.error("Unknown package: %s" % options.package)
+            parser.error(_("Unknown package: %s") % options.package)
     else:
         package_id = None
 
@@ -7362,7 +7362,7 @@ def handle_add_notification(goptions, session, args):
         try:
             tag_id = session.getTagID(options.tag, strict=True)
         except koji.GenericError:
-            parser.error("Unknown tag: %s" % options.tag)
+            parser.error(_("Unknown tag: %s") % options.tag)
     else:
         tag_id = None
 
@@ -7427,7 +7427,7 @@ def handle_edit_notification(goptions, session, args):
     elif options.package:
         package_id = session.getPackageID(options.package)
         if package_id is None:
-            parser.error("Unknown package: %s" % options.package)
+            parser.error(_("Unknown package: %s") % options.package)
     else:
         package_id = old['package_id']
 
@@ -7437,7 +7437,7 @@ def handle_edit_notification(goptions, session, args):
         try:
             tag_id = session.getTagID(options.tag, strict=True)
         except koji.GenericError:
-            parser.error("Unknown tag: %s" % options.tag)
+            parser.error(_("Unknown tag: %s") % options.tag)
     else:
         tag_id = old['tag_id']
 
@@ -7469,7 +7469,7 @@ def handle_block_notification(goptions, session, args):
     activate_session(session, goptions)
 
     if options.user and not session.hasPerm('admin'):
-        parser.error("--user requires admin permission")
+        parser.error(_("--user requires admin permission"))
 
     if options.user:
         user_id = session.getUser(options.user, strict=True)['id']
@@ -7478,12 +7478,12 @@ def handle_block_notification(goptions, session, args):
         if logged_in_user:
             user_id = logged_in_user['id']
         else:
-            parser.error("Please login with authentication or specify --user")
+            parser.error(_("Please login with authentication or specify --user"))
 
     if options.package:
         package_id = session.getPackageID(options.package)
         if package_id is None:
-            parser.error("Unknown package: %s" % options.package)
+            parser.error(_("Unknown package: %s") % options.package)
     else:
         package_id = None
 
@@ -7491,7 +7491,7 @@ def handle_block_notification(goptions, session, args):
         try:
             tag_id = session.getTagID(options.tag, strict=True)
         except koji.GenericError:
-            parser.error("Unknown tag: %s" % options.tag)
+            parser.error(_("Unknown tag: %s") % options.tag)
     else:
         tag_id = None
 

From 4424eba25b940ffda4ca58c00515f5b7c8f93c82 Mon Sep 17 00:00:00 2001
From: Tomas Kopecek <tkopecek@redhat.com>
Date: Dec 10 2019 09:19:04 +0000
Subject: [PATCH 4/7] unify BNF options


---

diff --git a/cli/koji_cli/commands.py b/cli/koji_cli/commands.py
index 3d0ddc3..34ec496 100644
--- a/cli/koji_cli/commands.py
+++ b/cli/koji_cli/commands.py
@@ -176,7 +176,7 @@ def handle_assign_task(goptions, session, args):
 
 def handle_add_host(goptions, session, args):
     "[admin] Add a host"
-    usage = _("usage: %prog add-host [options] hostname arch [arch2 ...]")
+    usage = _("usage: %prog add-host [options] <hostname> <arch> [<arch> ...]")
     usage += _("\n(Specify the --help global option for a list of other help options)")
     parser = OptionParser(usage=usage)
     parser.add_option("--krb-principal", help=_("set a non-default kerberos principal for the host"))
@@ -200,7 +200,7 @@ def handle_add_host(goptions, session, args):
 
 def handle_edit_host(options, session, args):
     "[admin] Edit a host"
-    usage = _("usage: %prog edit-host hostname ... [options]")
+    usage = _("usage: %prog edit-host <hostname> ... [options]")
     usage += _("\n(Specify the --help global option for a list of other help options)")
     parser = OptionParser(usage=usage)
     parser.add_option("--arches", help=_("Space or comma-separated list of supported architectures"))
@@ -245,7 +245,7 @@ def handle_edit_host(options, session, args):
 
 def handle_add_host_to_channel(goptions, session, args):
     "[admin] Add a host to a channel"
-    usage = _("usage: %prog add-host-to-channel [options] hostname channel")
+    usage = _("usage: %prog add-host-to-channel [options] <hostname> <channel>")
     usage += _("\n(Specify the --help global option for a list of other help options)")
     parser = OptionParser(usage=usage)
     parser.add_option("--list", action="store_true", help=SUPPRESS_HELP)
@@ -277,7 +277,7 @@ def handle_add_host_to_channel(goptions, session, args):
 
 def handle_remove_host_from_channel(goptions, session, args):
     "[admin] Remove a host from a channel"
-    usage = _("usage: %prog remove-host-from-channel [options] hostname channel")
+    usage = _("usage: %prog remove-host-from-channel [options] <hostname> <channel>")
     usage += _("\n(Specify the --help global option for a list of other help options)")
     parser = OptionParser(usage=usage)
     (options, args) = parser.parse_args(args)
@@ -301,7 +301,7 @@ def handle_remove_host_from_channel(goptions, session, args):
 
 def handle_remove_channel(goptions, session, args):
     "[admin] Remove a channel entirely"
-    usage = _("usage: %prog remove-channel [options] channel")
+    usage = _("usage: %prog remove-channel [options] <channel>")
     usage += _("\n(Specify the --help global option for a list of other help options)")
     parser = OptionParser(usage=usage)
     parser.add_option("--force", action="store_true", help=_("force removal, if possible"))
@@ -318,7 +318,7 @@ def handle_remove_channel(goptions, session, args):
 
 def handle_rename_channel(goptions, session, args):
     "[admin] Rename a channel"
-    usage = _("usage: %prog rename-channel [options] old-name new-name")
+    usage = _("usage: %prog rename-channel [options] <old-name> <new-name>")
     usage += _("\n(Specify the --help global option for a list of other help options)")
     parser = OptionParser(usage=usage)
     (options, args) = parser.parse_args(args)
@@ -334,7 +334,7 @@ def handle_rename_channel(goptions, session, args):
 
 def handle_add_pkg(goptions, session, args):
     "[admin] Add a package to the listing for tag"
-    usage = _("usage: %prog add-pkg [options] tag package [package2 ...]")
+    usage = _("usage: %prog add-pkg [options] <tag> <package> [<package> ...]")
     usage += _("\n(Specify the --help global option for a list of other help options)")
     parser = OptionParser(usage=usage)
     parser.add_option("--force", action='store_true', help=_("Override blocks if necessary"))
@@ -379,7 +379,7 @@ def handle_add_pkg(goptions, session, args):
 
 def handle_block_pkg(goptions, session, args):
     "[admin] Block a package in the listing for tag"
-    usage = _("usage: %prog block-pkg [options] tag package [package2 ...]")
+    usage = _("usage: %prog block-pkg [options] <tag> <package> [<package> ...]")
     usage += _("\n(Specify the --help global option for a list of other help options)")
     parser = OptionParser(usage=usage)
     parser.add_option("--force", action='store_true', default=False, help=_("Override blocks and owner if necessary"))
@@ -415,7 +415,7 @@ def handle_block_pkg(goptions, session, args):
 
 def handle_remove_pkg(goptions, session, args):
     "[admin] Remove a package from the listing for tag"
-    usage = _("usage: %prog remove-pkg [options] tag package [package2 ...]")
+    usage = _("usage: %prog remove-pkg [options] <tag> <package> [<package> ...]")
     usage += _("\n(Specify the --help global option for a list of other help options)")
     parser = OptionParser(usage=usage)
     parser.add_option("--force", action='store_true', help=_("Override blocks if necessary"))
@@ -448,7 +448,7 @@ def handle_remove_pkg(goptions, session, args):
 
 def handle_build(options, session, args):
     "[build] Build a package from source"
-    usage = _("usage: %prog build [options] target <srpm path or scm url>")
+    usage = _("usage: %prog build [options] <target> <srpm path or scm url>")
     usage += _("\n(Specify the --help global option for a list of other help options)")
     parser = OptionParser(usage=usage)
     parser.add_option("--skip-tag", action="store_true",
@@ -603,7 +603,7 @@ def handle_chain_build(options, session, args):
 
 def handle_maven_build(options, session, args):
     "[build] Build a Maven package from source"
-    usage = _("usage: %prog maven-build [options] target URL")
+    usage = _("usage: %prog maven-build [options] <target> <URL>")
     usage += _("\n       %prog maven-build --ini=CONFIG... [options] target")
     usage += _("\n(Specify the --help global option for a list of other help options)")
     parser = OptionParser(usage=usage)
@@ -703,7 +703,7 @@ def handle_maven_build(options, session, args):
 
 def handle_wrapper_rpm(options, session, args):
     """[build] Build wrapper rpms for any archives associated with a build."""
-    usage = _("usage: %prog wrapper-rpm [options] target build-id|n-v-r URL")
+    usage = _("usage: %prog wrapper-rpm [options] <target> <build-id|n-v-r> <URL>")
     usage += _("\n(Specify the --help global option for a list of other help options)")
     parser = OptionParser(usage=usage)
     parser.add_option("--create-build", action="store_true", help=_("Create a new build to contain wrapper rpms"))
@@ -771,7 +771,7 @@ def handle_wrapper_rpm(options, session, args):
 
 def handle_maven_chain(options, session, args):
     "[build] Run a set of Maven builds in dependency order"
-    usage = _("usage: %prog maven-chain [options] target config...")
+    usage = _("usage: %prog maven-chain [options] <target> <config> [<config> ...]")
     usage += _("\n(Specify the --help global option for a list of other help options)")
     parser = OptionParser(usage=usage)
     parser.add_option("--skip-tag", action="store_true",
@@ -824,7 +824,7 @@ def handle_maven_chain(options, session, args):
 
 def handle_resubmit(goptions, session, args):
     """[build] Retry a canceled or failed task, using the same parameter as the original task."""
-    usage = _("usage: %prog resubmit [options] taskID")
+    usage = _("usage: %prog resubmit [options] <task_id>")
     usage += _("\n(Specify the --help global option for a list of other help options)")
     parser = OptionParser(usage=usage)
     parser.add_option("--nowait", action="store_true", help=_("Don't wait on task"))
@@ -853,7 +853,7 @@ def handle_resubmit(goptions, session, args):
 
 def handle_call(goptions, session, args):
     "Execute an arbitrary XML-RPC call"
-    usage = _("usage: %prog call [options] name [arg...]")
+    usage = _("usage: %prog call [options] <name> [<arg> ...]")
     usage += _("\n(Specify the --help global option for a list of other help options)")
     parser = OptionParser(usage=usage)
     parser.add_option("--python", action="store_true", help=_("Use python syntax for values"))
@@ -1021,7 +1021,7 @@ def anon_handle_mock_config(goptions, session, args):
 
 def handle_disable_host(goptions, session, args):
     "[admin] Mark one or more hosts as disabled"
-    usage = _("usage: %prog disable-host [options] hostname ...")
+    usage = _("usage: %prog disable-host [options] <hostname> [<hostname> ...]")
     usage += _("\n(Specify the --help global option for a list of other help options)")
     parser = OptionParser(usage=usage)
     parser.add_option("--comment", help=_("Comment indicating why the host(s) are being disabled"))
@@ -1052,7 +1052,7 @@ def handle_disable_host(goptions, session, args):
 
 def handle_enable_host(goptions, session, args):
     "[admin] Mark one or more hosts as enabled"
-    usage = _("usage: %prog enable-host [options] hostname ...")
+    usage = _("usage: %prog enable-host [options] <hostname> [<hostname> ...]")
     usage += _("\n(Specify the --help global option for a list of other help options)")
     parser = OptionParser(usage=usage)
     parser.add_option("--comment", help=_("Comment indicating why the host(s) are being enabled"))
@@ -1143,7 +1143,7 @@ def handle_restart_hosts(options, session, args):
 
 def handle_import(goptions, session, args):
     "[admin] Import externally built RPMs into the database"
-    usage = _("usage: %prog import [options] package [package...]")
+    usage = _("usage: %prog import [options] <package> [<package> ...]")
     usage += _("\n(Specify the --help global option for a list of other help options)")
     parser = OptionParser(usage=usage)
     parser.add_option("--link", action="store_true", help=_("Attempt to hardlink instead of uploading"))
@@ -1291,7 +1291,7 @@ def handle_import(goptions, session, args):
 
 def handle_import_cg(goptions, session, args):
     "[admin] Import external builds with rich metadata"
-    usage = _("usage: %prog import-cg [options] metadata_file files_dir")
+    usage = _("usage: %prog import-cg [options] <metadata_file> <files_dir>")
     usage += _("\n(Specify the --help global option for a list of other help options)")
     parser = OptionParser(usage=usage)
     parser.add_option("--noprogress", action="store_true",
@@ -1440,7 +1440,7 @@ def _import_comps_alt(session, filename, tag, options): # no cover 3.x
 
 def handle_import_sig(goptions, session, args):
     "[admin] Import signatures into the database"
-    usage = _("usage: %prog import-sig [options] package [package...]")
+    usage = _("usage: %prog import-sig [options] <package> [<package> ...]")
     usage += _("\n(Specify the --help global option for a list of other help options)")
     parser = OptionParser(usage=usage)
     parser.add_option("--with-unsigned", action="store_true",
@@ -1502,7 +1502,7 @@ def handle_import_sig(goptions, session, args):
 
 def handle_write_signed_rpm(goptions, session, args):
     "[admin] Write signed RPMs to disk"
-    usage = _("usage: %prog write-signed-rpm [options] <signature-key> n-v-r [n-v-r...]")
+    usage = _("usage: %prog write-signed-rpm [options] <signature-key> <n-v-r> [<n-v-r> ...]")
     usage += _("\n(Specify the --help global option for a list of other help options)")
     parser = OptionParser(usage=usage)
     parser.add_option("--all", action="store_true", help=_("Write out all RPMs signed with this key"))
@@ -1892,7 +1892,7 @@ def handle_prune_signed_copies(options, session, args):
 
 def handle_set_build_volume(goptions, session, args):
     "[admin] Move a build to a different volume"
-    usage = _("usage: %prog set-build-volume volume n-v-r [n-v-r ...]")
+    usage = _("usage: %prog set-build-volume <volume> <n-v-r> [<n-v-r> ...]")
     usage += _("\n(Specify the --help global option for a list of other help options)")
     parser = OptionParser(usage=usage)
     parser.add_option("-v", "--verbose", action="store_true", help=_("Be verbose"))
@@ -1924,7 +1924,7 @@ def handle_set_build_volume(goptions, session, args):
 
 def handle_add_volume(goptions, session, args):
     "[admin] Add a new storage volume"
-    usage = _("usage: %prog add-volume volume-name")
+    usage = _("usage: %prog add-volume <volume-name>")
     usage += _("\n(Specify the --help global option for a list of other help options)")
     parser = OptionParser(usage=usage)
     (options, args) = parser.parse_args(args)
@@ -1977,7 +1977,7 @@ def handle_list_permissions(goptions, session, args):
 
 def handle_add_user(goptions, session, args):
     "[admin] Add a user"
-    usage = _("usage: %prog add-user username [options]")
+    usage = _("usage: %prog add-user <username> [options]")
     usage += _("\n(Specify the --help global option for a list of other help options)")
     parser = OptionParser(usage=usage)
     parser.add_option("--principal", help=_("The Kerberos principal for this user"))
@@ -1999,7 +1999,7 @@ def handle_add_user(goptions, session, args):
 
 def handle_enable_user(goptions, session, args):
     "[admin] Enable logins by a user"
-    usage = _("usage: %prog enable-user username")
+    usage = _("usage: %prog enable-user <username>")
     usage += _("\n(Specify the --help global option for a list of other help options)")
     parser = OptionParser(usage=usage)
     (options, args) = parser.parse_args(args)
@@ -2014,7 +2014,7 @@ def handle_enable_user(goptions, session, args):
 
 def handle_disable_user(goptions, session, args):
     "[admin] Disable logins by a user"
-    usage = _("usage: %prog disable-user username")
+    usage = _("usage: %prog disable-user <username>")
     usage += _("\n(Specify the --help global option for a list of other help options)")
     parser = OptionParser(usage=usage)
     (options, args) = parser.parse_args(args)
@@ -2029,7 +2029,7 @@ def handle_disable_user(goptions, session, args):
 
 def handle_edit_user(goptions, session, args):
     "[admin] Alter user information"
-    usage = _("usage: %prog edit-user name [options]")
+    usage = _("usage: %prog edit-user <username> [options]")
     usage += _("\n(Specify the --help global option for a list of other help options)")
     parser = OptionParser(usage=usage)
     parser.add_option("--rename", help=_("Rename the user"))
@@ -2133,7 +2133,7 @@ def handle_list_signed(goptions, session, args):
 
 def handle_import_archive(options, session, args):
     "[admin] Import an archive file and associate it with a build"
-    usage = _("usage: %prog import-archive build-id|n-v-r /path/to/archive...")
+    usage = _("usage: %prog import-archive <build-id|n-v-r> <archive_path> [<archive_path2 ...]")
     usage += _("\n(Specify the --help global option for a list of other help options)")
     parser = OptionParser(usage=usage)
     parser.add_option("--noprogress", action="store_true",
@@ -2313,7 +2313,7 @@ def handle_revoke_cg_access(goptions, session, args):
 
 def anon_handle_latest_build(goptions, session, args):
     "[info] Print the latest builds for a tag"
-    usage = _("usage: %prog latest-build [options] tag package [package...]")
+    usage = _("usage: %prog latest-build [options] <tag> <package> [<package> ...]")
     usage += _("\n(Specify the --help global option for a list of other help options)")
     parser = OptionParser(usage=usage)
     parser.add_option("--arch", help=_("List all of the latest packages for this arch"))
@@ -2416,7 +2416,7 @@ def anon_handle_list_api(goptions, session, args):
 
 def anon_handle_list_tagged(goptions, session, args):
     "[info] List the builds or rpms in a tag"
-    usage = _("usage: %prog list-tagged [options] tag [package]")
+    usage = _("usage: %prog list-tagged [options] <tag> [<package>]")
     usage += _("\n(Specify the --help global option for a list of other help options)")
     parser = OptionParser(usage=usage)
     parser.add_option("--arch", action="append", default=[], help=_("List rpms for this arch"))
@@ -2525,7 +2525,7 @@ def anon_handle_list_tagged(goptions, session, args):
 
 def anon_handle_list_buildroot(goptions, session, args):
     "[info] List the rpms used in or built in a buildroot"
-    usage = _("usage: %prog list-buildroot [options] buildroot-id")
+    usage = _("usage: %prog list-buildroot [options] <buildroot-id>")
     usage += _("\n(Specify the --help global option for a list of other help options)")
     parser = OptionParser(usage=usage)
     parser.add_option("--paths", action="store_true", help=_("Show the file paths"))
@@ -2555,7 +2555,7 @@ def anon_handle_list_buildroot(goptions, session, args):
 
 def anon_handle_list_untagged(goptions, session, args):
     "[info] List untagged builds"
-    usage = _("usage: %prog list-untagged [options] [package]")
+    usage = _("usage: %prog list-untagged [options] [<package>]")
     usage += _("\n(Specify the --help global option for a list of other help options)")
     parser = OptionParser(usage=usage)
     parser.add_option("--paths", action="store_true", help=_("Show the file paths"))
@@ -2618,7 +2618,7 @@ def print_group_list_req_package(pkg):
 
 def anon_handle_list_groups(goptions, session, args):
     "[info] Print the group listings"
-    usage = _("usage: %prog list-groups [options] <tag> [group]")
+    usage = _("usage: %prog list-groups [options] <tag> [<group>]")
     usage += _("\n(Specify the --help global option for a list of other help options)")
     parser = OptionParser(usage=usage)
     parser.add_option("--event", type='int', metavar="EVENT#", help=_("query at event"))
@@ -2659,7 +2659,7 @@ def anon_handle_list_groups(goptions, session, args):
 
 def handle_add_group_pkg(goptions, session, args):
     "[admin] Add a package to a group's package listing"
-    usage = _("usage: %prog add-group-pkg [options] <tag> <group> <pkg> [<pkg>...]")
+    usage = _("usage: %prog add-group-pkg [options] <tag> <group> <pkg> [<pkg> ...]")
     usage += _("\n(Specify the --help global option for a list of other help options)")
     parser = OptionParser(usage=usage)
     (options, args) = parser.parse_args(args)
@@ -2674,7 +2674,7 @@ def handle_add_group_pkg(goptions, session, args):
 
 def handle_block_group_pkg(goptions, session, args):
     "[admin] Block a package from a group's package listing"
-    usage = _("usage: %prog block-group-pkg [options] <tag> <group> <pkg> [<pkg>...]")
+    usage = _("usage: %prog block-group-pkg [options] <tag> <group> <pkg> [<pkg> ...]")
     usage += '\n' + _("Note that blocking is propagated through the inheritance chain, so "
                       "it is not exactly the same as package removal.")
     usage += _("\n(Specify the --help global option for a list of other help options)")
@@ -2691,7 +2691,7 @@ def handle_block_group_pkg(goptions, session, args):
 
 def handle_unblock_group_pkg(goptions, session, args):
     "[admin] Unblock a package from a group's package listing"
-    usage = _("usage: %prog unblock-group-pkg [options] <tag> <group> <pkg> [<pkg>...]")
+    usage = _("usage: %prog unblock-group-pkg [options] <tag> <group> <pkg> [<pkg> ...]")
     usage += _("\n(Specify the --help global option for a list of other help options)")
     parser = OptionParser(usage=usage)
     (options, args) = parser.parse_args(args)
@@ -3762,7 +3762,7 @@ def handle_clone_tag(goptions, session, args):
 
 def handle_add_target(goptions, session, args):
     "[admin] Create a new build target"
-    usage = _("usage: %prog add-target name build-tag <dest-tag>")
+    usage = _("usage: %prog add-target <name> <build tag> <dest tag>")
     usage += _("\n(Specify the --help global option for a list of other help options)")
     parser = OptionParser(usage=usage)
     (options, args) = parser.parse_args(args)
@@ -3798,7 +3798,7 @@ def handle_add_target(goptions, session, args):
 
 def handle_edit_target(goptions, session, args):
     "[admin] Set the name, build_tag, and/or dest_tag of an existing build target to new values"
-    usage = _("usage: %prog edit-target [options] name")
+    usage = _("usage: %prog edit-target [options] <name>")
     usage += _("\n(Specify the --help global option for a list of other help options)")
     parser = OptionParser(usage=usage)
     parser.add_option("--rename", help=_("Specify new name for target"))
@@ -3843,7 +3843,7 @@ def handle_edit_target(goptions, session, args):
 
 def handle_remove_target(goptions, session, args):
     "[admin] Remove a build target"
-    usage = _("usage: %prog remove-target [options] name")
+    usage = _("usage: %prog remove-target [options] <name>")
     usage += _("\n(Specify the --help global option for a list of other help options)")
     parser = OptionParser(usage=usage)
     (options, args) = parser.parse_args(args)
@@ -3866,7 +3866,7 @@ def handle_remove_target(goptions, session, args):
 
 def handle_remove_tag(goptions, session, args):
     "[admin] Remove a tag"
-    usage = _("usage: %prog remove-tag [options] name")
+    usage = _("usage: %prog remove-tag [options] <name>")
     usage += _("\n(Specify the --help global option for a list of other help options)")
     parser = OptionParser(usage=usage)
     (options, args) = parser.parse_args(args)
@@ -4741,7 +4741,7 @@ def _printTaskInfo(session, task_id, topdir, level=0, recurse=True, verbose=True
 
 def anon_handle_taskinfo(goptions, session, args):
     """[info] Show information about a task"""
-    usage = _("usage: %prog taskinfo [options] taskID [taskID...]")
+    usage = _("usage: %prog taskinfo [options] <task_id> [<task_id> ...]")
     usage += _("\n(Specify the --help global option for a list of other help options)")
     parser = OptionParser(usage=usage)
     parser.add_option("-r", "--recurse", action="store_true", help=_("Show children of this task as well"))
@@ -4852,7 +4852,7 @@ def anon_handle_taginfo(goptions, session, args):
 
 def handle_add_tag(goptions, session, args):
     "[admin] Add a new tag to the database"
-    usage = _("usage: %prog add-tag [options] name")
+    usage = _("usage: %prog add-tag [options] <name>")
     usage += _("\n(Specify the --help global option for a list of other help options)")
     parser = OptionParser(usage=usage)
     parser.add_option("--parent", help=_("Specify parent"))
@@ -4888,7 +4888,7 @@ def handle_add_tag(goptions, session, args):
 
 def handle_edit_tag(goptions, session, args):
     "[admin] Alter tag information"
-    usage = _("usage: %prog edit-tag [options] name")
+    usage = _("usage: %prog edit-tag [options] <name>")
     usage += _("\n(Specify the --help global option for a list of other help options)")
     parser = OptionParser(usage=usage)
     parser.add_option("--arches", help=_("Specify arches"))
@@ -5039,7 +5039,7 @@ def handle_unlock_tag(goptions, session, args):
 
 def handle_add_tag_inheritance(goptions, session, args):
     """[admin] Add to a tag's inheritance"""
-    usage = _("usage: %prog add-tag-inheritance [options] tag parent-tag")
+    usage = _("usage: %prog add-tag-inheritance [options] <tag> <parent-tag>")
     usage += _("\n(Specify the --help global option for a list of other help options)")
     parser = OptionParser(usage=usage)
     parser.add_option("--priority", help=_("Specify priority"))
@@ -5095,7 +5095,7 @@ def handle_add_tag_inheritance(goptions, session, args):
 
 def handle_edit_tag_inheritance(goptions, session, args):
     """[admin] Edit tag inheritance"""
-    usage = _("usage: %prog edit-tag-inheritance [options] tag <parent> <priority>")
+    usage = _("usage: %prog edit-tag-inheritance [options] <tag> <parent> <priority>")
     usage += _("\n(Specify the --help global option for a list of other help options)")
     parser = OptionParser(usage=usage)
     parser.add_option("--priority", help=_("Specify a new priority"))
@@ -5181,7 +5181,7 @@ def handle_edit_tag_inheritance(goptions, session, args):
 
 def handle_remove_tag_inheritance(goptions, session, args):
     """[admin] Remove a tag inheritance link"""
-    usage = _("usage: %prog remove-tag-inheritance tag <parent> <priority>")
+    usage = _("usage: %prog remove-tag-inheritance <tag> <parent> <priority>")
     usage += _("\n(Specify the --help global option for a list of other help options)")
     parser = OptionParser(usage=usage)
     (options, args) = parser.parse_args(args)
@@ -5374,7 +5374,7 @@ def _parse_tagpri(tagpri):
 
 def handle_add_external_repo(goptions, session, args):
     "[admin] Create an external repo and/or add one to a tag"
-    usage = _("usage: %prog add-external-repo [options] name [url]")
+    usage = _("usage: %prog add-external-repo [options] <name> [<url>]")
     usage += _("\n(Specify the --help global option for a list of other help options)")
     parser = OptionParser(usage=usage)
     parser.add_option("-t", "--tag", action="append", metavar="TAG",
@@ -5418,7 +5418,7 @@ def handle_add_external_repo(goptions, session, args):
 
 def handle_edit_external_repo(goptions, session, args):
     "[admin] Edit data for an external repo"
-    usage = _("usage: %prog edit-external-repo name")
+    usage = _("usage: %prog edit-external-repo <name>")
     usage += _("\n(Specify the --help global option for a list of other help options)")
     parser = OptionParser(usage=usage)
     parser.add_option("--url",  help=_("Change the url"))
@@ -5439,7 +5439,7 @@ def handle_edit_external_repo(goptions, session, args):
 
 def handle_remove_external_repo(goptions, session, args):
     "[admin] Remove an external repo from a tag or tags, or remove entirely"
-    usage = _("usage: %prog remove-external-repo repo [tag ...]")
+    usage = _("usage: %prog remove-external-repo <repo> [<tag> ...]")
     usage += _("\n(Specify the --help global option for a list of other help options)")
     parser = OptionParser(usage=usage)
     parser.add_option("--alltags", action="store_true", help=_("Remove from all tags"))
@@ -5788,7 +5788,7 @@ def handle_image_build(options, session, args):
                'vagrant-vmware-fusion', 'vagrant-hyperv', 'docker', 'raw-xz',
                'liveimg-squashfs', 'tar-gz')
     usage = _("usage: %prog image-build [options] <name> <version> " +
-              "<target> <install-tree-url> <arch> [<arch>...]")
+              "<target> <install-tree-url> <arch> [<arch> ...]")
     usage += _("\n       %prog image-build --config FILE")
     usage += _("\n\n(Specify the --help global option for a list of other " +
                "help options)")
@@ -6054,7 +6054,7 @@ def _build_image_oz(options, task_opts, session, args):
 def handle_win_build(options, session, args):
     """[build] Build a Windows package from source"""
     # Usage & option parsing
-    usage = _("usage: %prog win-build [options] target URL VM")
+    usage = _("usage: %prog win-build [options] <target> <URL> <VM>")
     usage += _("\n(Specify the --help global option for a list of other " +
                "help options)")
     parser = OptionParser(usage=usage)
@@ -6188,7 +6188,7 @@ def handle_cancel(goptions, session, args):
 
 def handle_set_task_priority(goptions, session, args):
     "[admin] Set task priority"
-    usage = _("usage: %prog set-task-priority [options] --priority=<priority> <task-id> [task-id]...")
+    usage = _("usage: %prog set-task-priority [options] --priority=<priority> <task-id> [<task-id> ...]")
     usage += _("\n(Specify the --help global option for a list of other help options)")
     parser = OptionParser(usage=usage)
     parser.add_option("--priority", type="int", help=_("New priority"))
@@ -6243,7 +6243,7 @@ def handle_list_tasks(goptions, session, args):
 
 def handle_set_pkg_arches(goptions, session, args):
     "[admin] Set the list of extra arches for a package"
-    usage = _("usage: %prog set-pkg-arches [options] arches tag package [package2 ...]")
+    usage = _("usage: %prog set-pkg-arches [options] <arches> <tag> <package> [<package> ...]")
     usage += _("\n(Specify the --help global option for a list of other help options)")
     parser = OptionParser(usage=usage)
     parser.add_option("--force", action='store_true', help=_("Force operation"))
@@ -6260,7 +6260,7 @@ def handle_set_pkg_arches(goptions, session, args):
 
 def handle_set_pkg_owner(goptions, session, args):
     "[admin] Set the owner for a package"
-    usage = _("usage: %prog set-pkg-owner [options] owner tag package [package2 ...]")
+    usage = _("usage: %prog set-pkg-owner [options] <owner> <tag> <package> [<package> ...]")
     usage += _("\n(Specify the --help global option for a list of other help options)")
     parser = OptionParser(usage=usage)
     parser.add_option("--force", action='store_true', help=_("Force operation"))
@@ -6277,7 +6277,7 @@ def handle_set_pkg_owner(goptions, session, args):
 
 def handle_set_pkg_owner_global(goptions, session, args):
     "[admin] Set the owner for a package globally"
-    usage = _("usage: %prog set-pkg-owner-global [options] owner package [package2 ...]")
+    usage = _("usage: %prog set-pkg-owner-global [options] <owner> <package> [<package> ...]")
     usage += _("\n(Specify the --help global option for a list of other help options)")
     parser = OptionParser(usage=usage)
     parser.add_option("--verbose", action='store_true', help=_("List changes"))
@@ -6335,7 +6335,7 @@ def handle_set_pkg_owner_global(goptions, session, args):
 
 def anon_handle_watch_task(goptions, session, args):
     "[monitor] Track progress of particular tasks"
-    usage = _("usage: %prog watch-task [options] <task id> [<task id>...]")
+    usage = _("usage: %prog watch-task [options] <task id> [<task id> ...]")
     usage += _("\n(Specify the --help global option for a list of other help options)")
     parser = OptionParser(usage=usage)
     parser.add_option("--quiet", action="store_true", default=goptions.quiet,
@@ -6378,7 +6378,7 @@ def anon_handle_watch_task(goptions, session, args):
 
 def anon_handle_watch_logs(goptions, session, args):
     "[monitor] Watch logs in realtime"
-    usage = _("usage: %prog watch-logs [options] <task id> [<task id>...]")
+    usage = _("usage: %prog watch-logs [options] <task id> [<task id> ...]")
     usage += _("\n(Specify the --help global option for a list of other help options)")
     parser = OptionParser(usage=usage)
     parser.add_option("--log", help=_("Watch only a specific log"))
@@ -6411,7 +6411,7 @@ def anon_handle_watch_logs(goptions, session, args):
 
 def handle_make_task(goptions, session, args):
     "[admin] Create an arbitrary task"
-    usage = _("usage: %prog make-task [options] <method> [<arg>...]")
+    usage = _("usage: %prog make-task [options] <method> [<arg> ...]")
     usage += _("\n(Specify the --help global option for a list of other help options)")
     parser = OptionParser(usage=usage)
     parser.add_option("--channel", help=_("set channel"))
@@ -6442,7 +6442,7 @@ def handle_make_task(goptions, session, args):
 
 def handle_tag_build(opts, session, args):
     "[bind] Apply a tag to one or more builds"
-    usage = _("usage: %prog tag-build [options] <tag> <pkg> [<pkg>...]")
+    usage = _("usage: %prog tag-build [options] <tag> <pkg> [<pkg> ...]")
     usage += _("\n(Specify the --help global option for a list of other help options)")
     parser = OptionParser(usage=usage)
     parser.add_option("--force", action="store_true", help=_("force operation"))
@@ -6467,7 +6467,7 @@ def handle_tag_build(opts, session, args):
 
 def handle_move_build(opts, session, args):
     "[bind] 'Move' one or more builds between tags"
-    usage = _("usage: %prog move-build [options] <tag1> <tag2> <pkg> [<pkg>...]")
+    usage = _("usage: %prog move-build [options] <tag1> <tag2> <pkg> [<pkg> ...]")
     usage += _("\n(Specify the --help global option for a list of other help options)")
     parser = OptionParser(usage=usage)
     parser.add_option("--force", action="store_true", help=_("force operation"))
@@ -6514,7 +6514,7 @@ def handle_move_build(opts, session, args):
 
 def handle_untag_build(goptions, session, args):
     "[bind] Remove a tag from one or more builds"
-    usage = _("usage: %prog untag-build [options] <tag> <pkg> [<pkg>...]")
+    usage = _("usage: %prog untag-build [options] <tag> <pkg> [<pkg> ...]")
     usage += _("\n(Specify the --help global option for a list of other help options)")
     parser = OptionParser(usage=usage)
     parser.add_option("--all", action="store_true", help=_("untag all versions of the package in this tag"))
@@ -6583,7 +6583,7 @@ def handle_untag_build(goptions, session, args):
 
 def handle_unblock_pkg(goptions, session, args):
     "[admin] Unblock a package in the listing for tag"
-    usage = _("usage: %prog unblock-pkg [options] tag package [package2 ...]")
+    usage = _("usage: %prog unblock-pkg [options] <tag> <package> [<package> ...]")
     usage += _("\n(Specify the --help global option for a list of other help options)")
     parser = OptionParser(usage=usage)
     (options, args) = parser.parse_args(args)
@@ -7073,7 +7073,7 @@ def handle_regen_repo(options, session, args):
 
 def handle_dist_repo(options, session, args):
     """Create a yum repo with distribution options"""
-    usage = _("usage: %prog dist-repo [options] tag keyID [keyID...]")
+    usage = _("usage: %prog dist-repo [options] <tag> <keyID> [<keyID> ...]")
     usage += _("\n(Specify the --help option for a list of other options)")
     parser = OptionParser(usage=usage)
     parser.add_option('--allow-missing-signatures', action='store_true',
@@ -7203,7 +7203,7 @@ _search_types = ('package', 'build', 'tag', 'target', 'user', 'host', 'rpm',
 
 def anon_handle_search(options, session, args):
     "[search] Search the system"
-    usage = _("usage: %prog search [options] search_type pattern")
+    usage = _("usage: %prog search [options] <search_type> <pattern>")
     usage += _('\nAvailable search types: %s') % ', '.join(_search_types)
     usage += _("\n(Specify the --help global option for a list of other help options)")
     parser = OptionParser(usage=usage)
@@ -7371,7 +7371,7 @@ def handle_add_notification(goptions, session, args):
 
 def handle_remove_notification(goptions, session, args):
     "[monitor] Remove user's notifications"
-    usage = _("usage: %prog remove-notification [options] ID [ID2, ...]")
+    usage = _("usage: %prog remove-notification [options] <ID> [<ID> ...]")
     usage += _("\n(Specify the --help global option for a list of other help options)")
     parser = OptionParser(usage=usage)
     (options, args) = parser.parse_args(args)
@@ -7394,7 +7394,7 @@ def handle_remove_notification(goptions, session, args):
 
 def handle_edit_notification(goptions, session, args):
     "[monitor] Edit user's notification"
-    usage = _("usage: %prog edit-notification [options] ID")
+    usage = _("usage: %prog edit-notification [options] <ID>")
     usage += _("\n(Specify the --help global option for a list of other help options)")
     parser = OptionParser(usage=usage)
     parser.add_option("--package",
@@ -7504,7 +7504,7 @@ def handle_block_notification(goptions, session, args):
 
 def handle_unblock_notification(goptions, session, args):
     "[monitor] Unblock user's notification"
-    usage = _("usage: %prog unblock-notification [options] ID [ID2, ...]")
+    usage = _("usage: %prog unblock-notification [options] <ID> [<ID> ...]")
     usage += _("\n(Specify the --help global option for a list of other help options)")
     parser = OptionParser(usage=usage)
     (options, args) = parser.parse_args(args)

From 8f2d504cd52dd17e1e66f5be2854321a6418fc17 Mon Sep 17 00:00:00 2001
From: Tomas Kopecek <tkopecek@redhat.com>
Date: Dec 10 2019 09:19:04 +0000
Subject: [PATCH 5/7] get_usage_str


---

diff --git a/cli/koji_cli/commands.py b/cli/koji_cli/commands.py
index 34ec496..a0f4f79 100644
--- a/cli/koji_cli/commands.py
+++ b/cli/koji_cli/commands.py
@@ -41,7 +41,7 @@ from koji_cli.lib import _, activate_session, parse_arches, \
         arg_filter, linked_upload, list_task_output_all_volumes, \
         print_task_headers, print_task_recurse, download_file, watch_logs, \
         error, warn, greetings, _list_tasks, unique_path, \
-        format_inheritance_flags
+        format_inheritance_flags, get_usage_str
 
 
 def _printable_unicode(s):
@@ -54,8 +54,7 @@ def _printable_unicode(s):
 def handle_add_group(goptions, session, args):
     "[admin] Add a group to a tag"
     usage = _("usage: %prog add-group <tag> <group>")
-    usage += _("\n(Specify the --help global option for a list of other help options)")
-    parser = OptionParser(usage=usage)
+    parser = OptionParser(usage=get_usage_str(usage))
     (options, args) = parser.parse_args(args)
     if len(args) != 2:
         parser.error(_("Please specify a tag name and a group name"))
@@ -83,8 +82,7 @@ def handle_add_group(goptions, session, args):
 def handle_block_group(goptions, session, args):
     "[admin] Block group in tag"
     usage = _("usage: %prog block-group <tag> <group>")
-    usage += _("\n(Specify the --help global option for a list of other help options)")
-    parser = OptionParser(usage=usage)
+    parser = OptionParser(usage=get_usage_str(usage))
     (options, args) = parser.parse_args(args)
     if len(args) != 2:
         parser.error(_("Please specify a tag name and a group name"))
@@ -112,8 +110,7 @@ def handle_block_group(goptions, session, args):
 def handle_remove_group(goptions, session, args):
     "[admin] Remove group from tag"
     usage = _("usage: %prog remove-group <tag> <group>")
-    usage += _("\n(Specify the --help global option for a list of other help options)")
-    parser = OptionParser(usage=usage)
+    parser = OptionParser(usage=get_usage_str(usage))
     (options, args) = parser.parse_args(args)
     if len(args) != 2:
         parser.error(_("Please specify a tag name and a group name"))
@@ -139,8 +136,7 @@ def handle_remove_group(goptions, session, args):
 def handle_assign_task(goptions, session, args):
     "[admin] Assign a task to a host"
     usage = _('usage: %prog assign-task <task_id> <hostname>')
-    usage += _('\n(Specify the --help global option for a list of other help options)')
-    parser = OptionParser(usage=usage)
+    parser = OptionParser(usage=get_usage_str(usage))
     parser.add_option('-f', '--force', action='store_true', default=False,
                           help=_('force to assign a non-free task'))
     (options, args) = parser.parse_args(args)
@@ -177,8 +173,7 @@ def handle_assign_task(goptions, session, args):
 def handle_add_host(goptions, session, args):
     "[admin] Add a host"
     usage = _("usage: %prog add-host [options] <hostname> <arch> [<arch> ...]")
-    usage += _("\n(Specify the --help global option for a list of other help options)")
-    parser = OptionParser(usage=usage)
+    parser = OptionParser(usage=get_usage_str(usage))
     parser.add_option("--krb-principal", help=_("set a non-default kerberos principal for the host"))
     (options, args) = parser.parse_args(args)
     if len(args) < 2:
@@ -201,8 +196,7 @@ def handle_add_host(goptions, session, args):
 def handle_edit_host(options, session, args):
     "[admin] Edit a host"
     usage = _("usage: %prog edit-host <hostname> ... [options]")
-    usage += _("\n(Specify the --help global option for a list of other help options)")
-    parser = OptionParser(usage=usage)
+    parser = OptionParser(usage=get_usage_str(usage))
     parser.add_option("--arches", help=_("Space or comma-separated list of supported architectures"))
     parser.add_option("--capacity", type="float", help=_("Capacity of this host"))
     parser.add_option("--description", metavar="DESC", help=_("Description of this host"))
@@ -246,8 +240,7 @@ def handle_edit_host(options, session, args):
 def handle_add_host_to_channel(goptions, session, args):
     "[admin] Add a host to a channel"
     usage = _("usage: %prog add-host-to-channel [options] <hostname> <channel>")
-    usage += _("\n(Specify the --help global option for a list of other help options)")
-    parser = OptionParser(usage=usage)
+    parser = OptionParser(usage=get_usage_str(usage))
     parser.add_option("--list", action="store_true", help=SUPPRESS_HELP)
     parser.add_option("--new", action="store_true", help=_("Create channel if needed"))
     (options, args) = parser.parse_args(args)
@@ -278,8 +271,7 @@ def handle_add_host_to_channel(goptions, session, args):
 def handle_remove_host_from_channel(goptions, session, args):
     "[admin] Remove a host from a channel"
     usage = _("usage: %prog remove-host-from-channel [options] <hostname> <channel>")
-    usage += _("\n(Specify the --help global option for a list of other help options)")
-    parser = OptionParser(usage=usage)
+    parser = OptionParser(usage=get_usage_str(usage))
     (options, args) = parser.parse_args(args)
     if len(args) != 2:
         parser.error(_("Please specify a hostname and a channel"))
@@ -302,8 +294,7 @@ def handle_remove_host_from_channel(goptions, session, args):
 def handle_remove_channel(goptions, session, args):
     "[admin] Remove a channel entirely"
     usage = _("usage: %prog remove-channel [options] <channel>")
-    usage += _("\n(Specify the --help global option for a list of other help options)")
-    parser = OptionParser(usage=usage)
+    parser = OptionParser(usage=get_usage_str(usage))
     parser.add_option("--force", action="store_true", help=_("force removal, if possible"))
     (options, args) = parser.parse_args(args)
     if len(args) != 1:
@@ -319,8 +310,7 @@ def handle_remove_channel(goptions, session, args):
 def handle_rename_channel(goptions, session, args):
     "[admin] Rename a channel"
     usage = _("usage: %prog rename-channel [options] <old-name> <new-name>")
-    usage += _("\n(Specify the --help global option for a list of other help options)")
-    parser = OptionParser(usage=usage)
+    parser = OptionParser(usage=get_usage_str(usage))
     (options, args) = parser.parse_args(args)
     if len(args) != 2:
         parser.error(_("Incorrect number of arguments"))
@@ -335,8 +325,7 @@ def handle_rename_channel(goptions, session, args):
 def handle_add_pkg(goptions, session, args):
     "[admin] Add a package to the listing for tag"
     usage = _("usage: %prog add-pkg [options] <tag> <package> [<package> ...]")
-    usage += _("\n(Specify the --help global option for a list of other help options)")
-    parser = OptionParser(usage=usage)
+    parser = OptionParser(usage=get_usage_str(usage))
     parser.add_option("--force", action='store_true', help=_("Override blocks if necessary"))
     parser.add_option("--owner", help=_("Specify owner"))
     parser.add_option("--extra-arches", help=_("Specify extra arches"))
@@ -380,8 +369,7 @@ def handle_add_pkg(goptions, session, args):
 def handle_block_pkg(goptions, session, args):
     "[admin] Block a package in the listing for tag"
     usage = _("usage: %prog block-pkg [options] <tag> <package> [<package> ...]")
-    usage += _("\n(Specify the --help global option for a list of other help options)")
-    parser = OptionParser(usage=usage)
+    parser = OptionParser(usage=get_usage_str(usage))
     parser.add_option("--force", action='store_true', default=False, help=_("Override blocks and owner if necessary"))
     (options, args) = parser.parse_args(args)
     if len(args) < 2:
@@ -416,8 +404,7 @@ def handle_block_pkg(goptions, session, args):
 def handle_remove_pkg(goptions, session, args):
     "[admin] Remove a package from the listing for tag"
     usage = _("usage: %prog remove-pkg [options] <tag> <package> [<package> ...]")
-    usage += _("\n(Specify the --help global option for a list of other help options)")
-    parser = OptionParser(usage=usage)
+    parser = OptionParser(usage=get_usage_str(usage))
     parser.add_option("--force", action='store_true', help=_("Override blocks if necessary"))
     (options, args) = parser.parse_args(args)
     if len(args) < 2:
@@ -449,8 +436,7 @@ def handle_remove_pkg(goptions, session, args):
 def handle_build(options, session, args):
     "[build] Build a package from source"
     usage = _("usage: %prog build [options] <target> <srpm path or scm url>")
-    usage += _("\n(Specify the --help global option for a list of other help options)")
-    parser = OptionParser(usage=usage)
+    parser = OptionParser(usage=get_usage_str(usage))
     parser.add_option("--skip-tag", action="store_true",
                       help=_("Do not attempt to tag package"))
     parser.add_option("--scratch", action="store_true",
@@ -529,8 +515,7 @@ def handle_chain_build(options, session, args):
     # XXX - replace handle_build with this, once chain-building has gotten testing
     "[build] Build one or more packages from source"
     usage = _("usage: %prog chain-build [options] target URL [URL2 [:] URL3 [:] URL4 ...]")
-    usage += _("\n(Specify the --help global option for a list of other help options)")
-    parser = OptionParser(usage=usage)
+    parser = OptionParser(usage=get_usage_str(usage))
     parser.add_option("--nowait", action="store_true",
                       help=_("Don't wait on build"))
     parser.add_option("--quiet", action="store_true",
@@ -605,8 +590,7 @@ def handle_maven_build(options, session, args):
     "[build] Build a Maven package from source"
     usage = _("usage: %prog maven-build [options] <target> <URL>")
     usage += _("\n       %prog maven-build --ini=CONFIG... [options] target")
-    usage += _("\n(Specify the --help global option for a list of other help options)")
-    parser = OptionParser(usage=usage)
+    parser = OptionParser(usage=get_usage_str(usage))
     parser.add_option("--patches", action="store", metavar="URL",
                       help=_("SCM URL of a directory containing patches to apply to the sources before building"))
     parser.add_option("-G", "--goal", action="append",
@@ -704,8 +688,7 @@ def handle_maven_build(options, session, args):
 def handle_wrapper_rpm(options, session, args):
     """[build] Build wrapper rpms for any archives associated with a build."""
     usage = _("usage: %prog wrapper-rpm [options] <target> <build-id|n-v-r> <URL>")
-    usage += _("\n(Specify the --help global option for a list of other help options)")
-    parser = OptionParser(usage=usage)
+    parser = OptionParser(usage=get_usage_str(usage))
     parser.add_option("--create-build", action="store_true", help=_("Create a new build to contain wrapper rpms"))
     parser.add_option("--ini", action="append",
                       dest="inis", metavar="CONFIG", default=[],
@@ -772,8 +755,7 @@ def handle_wrapper_rpm(options, session, args):
 def handle_maven_chain(options, session, args):
     "[build] Run a set of Maven builds in dependency order"
     usage = _("usage: %prog maven-chain [options] <target> <config> [<config> ...]")
-    usage += _("\n(Specify the --help global option for a list of other help options)")
-    parser = OptionParser(usage=usage)
+    parser = OptionParser(usage=get_usage_str(usage))
     parser.add_option("--skip-tag", action="store_true",
                       help=_("Do not attempt to tag builds"))
     parser.add_option("--scratch", action="store_true",
@@ -825,8 +807,7 @@ def handle_maven_chain(options, session, args):
 def handle_resubmit(goptions, session, args):
     """[build] Retry a canceled or failed task, using the same parameter as the original task."""
     usage = _("usage: %prog resubmit [options] <task_id>")
-    usage += _("\n(Specify the --help global option for a list of other help options)")
-    parser = OptionParser(usage=usage)
+    parser = OptionParser(usage=get_usage_str(usage))
     parser.add_option("--nowait", action="store_true", help=_("Don't wait on task"))
     parser.add_option("--nowatch", action="store_true", dest="nowait",
             help=_("An alias for --nowait"))
@@ -854,8 +835,7 @@ def handle_resubmit(goptions, session, args):
 def handle_call(goptions, session, args):
     "Execute an arbitrary XML-RPC call"
     usage = _("usage: %prog call [options] <name> [<arg> ...]")
-    usage += _("\n(Specify the --help global option for a list of other help options)")
-    parser = OptionParser(usage=usage)
+    parser = OptionParser(usage=get_usage_str(usage))
     parser.add_option("--python", action="store_true", help=_("Use python syntax for values"))
     parser.add_option("--kwargs", help=_("Specify keyword arguments as a dictionary (implies --python)"))
     parser.add_option("--json-output", action="store_true", help=_("Use JSON syntax for output"))
@@ -893,8 +873,7 @@ def handle_call(goptions, session, args):
 def anon_handle_mock_config(goptions, session, args):
     "[info] Create a mock config"
     usage = _("usage: %prog mock-config [options]")
-    usage += _("\n(Specify the --help global option for a list of other help options)")
-    parser = OptionParser(usage=usage)
+    parser = OptionParser(usage=get_usage_str(usage))
     parser.add_option("-a", "--arch", help=_("Specify the arch"))
     parser.add_option("-n", "--name", help=_("Specify the name for the buildroot"))
     parser.add_option("--tag", help=_("Create a mock config for a tag"))
@@ -1022,8 +1001,7 @@ def anon_handle_mock_config(goptions, session, args):
 def handle_disable_host(goptions, session, args):
     "[admin] Mark one or more hosts as disabled"
     usage = _("usage: %prog disable-host [options] <hostname> [<hostname> ...]")
-    usage += _("\n(Specify the --help global option for a list of other help options)")
-    parser = OptionParser(usage=usage)
+    parser = OptionParser(usage=get_usage_str(usage))
     parser.add_option("--comment", help=_("Comment indicating why the host(s) are being disabled"))
     (options, args) = parser.parse_args(args)
 
@@ -1053,8 +1031,7 @@ def handle_disable_host(goptions, session, args):
 def handle_enable_host(goptions, session, args):
     "[admin] Mark one or more hosts as enabled"
     usage = _("usage: %prog enable-host [options] <hostname> [<hostname> ...]")
-    usage += _("\n(Specify the --help global option for a list of other help options)")
-    parser = OptionParser(usage=usage)
+    parser = OptionParser(usage=get_usage_str(usage))
     parser.add_option("--comment", help=_("Comment indicating why the host(s) are being enabled"))
     (options, args) = parser.parse_args(args)
 
@@ -1084,8 +1061,7 @@ def handle_enable_host(goptions, session, args):
 def handle_restart_hosts(options, session, args):
     "[admin] Restart enabled hosts"
     usage = _("usage: %prog restart-hosts [options]")
-    usage += _("\n(Specify the --help global option for a list of other help options)")
-    parser = OptionParser(usage=usage)
+    parser = OptionParser(usage=get_usage_str(usage))
     parser.add_option("--wait", action="store_true",
                       help=_("Wait on the task, even if running in the background"))
     parser.add_option("--nowait", action="store_false", dest="wait",
@@ -1144,8 +1120,7 @@ def handle_restart_hosts(options, session, args):
 def handle_import(goptions, session, args):
     "[admin] Import externally built RPMs into the database"
     usage = _("usage: %prog import [options] <package> [<package> ...]")
-    usage += _("\n(Specify the --help global option for a list of other help options)")
-    parser = OptionParser(usage=usage)
+    parser = OptionParser(usage=get_usage_str(usage))
     parser.add_option("--link", action="store_true", help=_("Attempt to hardlink instead of uploading"))
     parser.add_option("--test", action="store_true", help=_("Don't actually import"))
     parser.add_option("--create-build", action="store_true", help=_("Auto-create builds as needed"))
@@ -1292,8 +1267,7 @@ def handle_import(goptions, session, args):
 def handle_import_cg(goptions, session, args):
     "[admin] Import external builds with rich metadata"
     usage = _("usage: %prog import-cg [options] <metadata_file> <files_dir>")
-    usage += _("\n(Specify the --help global option for a list of other help options)")
-    parser = OptionParser(usage=usage)
+    parser = OptionParser(usage=get_usage_str(usage))
     parser.add_option("--noprogress", action="store_true",
                       help=_("Do not display progress of the upload"))
     parser.add_option("--link", action="store_true", help=_("Attempt to hardlink instead of uploading"))
@@ -1347,8 +1321,7 @@ def handle_import_cg(goptions, session, args):
 def handle_import_comps(goptions, session, args):
     "Import group/package information from a comps file"
     usage = _("usage: %prog import-comps [options] <file> <tag>")
-    usage += _("\n(Specify the --help global option for a list of other help options)")
-    parser = OptionParser(usage=usage)
+    parser = OptionParser(usage=get_usage_str(usage))
     parser.add_option("--force", action="store_true", help=_("force import"))
     (local_options, args) = parser.parse_args(args)
     if len(args) != 2:
@@ -1441,8 +1414,7 @@ def _import_comps_alt(session, filename, tag, options): # no cover 3.x
 def handle_import_sig(goptions, session, args):
     "[admin] Import signatures into the database"
     usage = _("usage: %prog import-sig [options] <package> [<package> ...]")
-    usage += _("\n(Specify the --help global option for a list of other help options)")
-    parser = OptionParser(usage=usage)
+    parser = OptionParser(usage=get_usage_str(usage))
     parser.add_option("--with-unsigned", action="store_true",
                       help=_("Also import unsigned sig headers"))
     parser.add_option("--write", action="store_true",
@@ -1503,8 +1475,7 @@ def handle_import_sig(goptions, session, args):
 def handle_write_signed_rpm(goptions, session, args):
     "[admin] Write signed RPMs to disk"
     usage = _("usage: %prog write-signed-rpm [options] <signature-key> <n-v-r> [<n-v-r> ...]")
-    usage += _("\n(Specify the --help global option for a list of other help options)")
-    parser = OptionParser(usage=usage)
+    parser = OptionParser(usage=get_usage_str(usage))
     parser.add_option("--all", action="store_true", help=_("Write out all RPMs signed with this key"))
     parser.add_option("--buildid", help=_("Specify a build id rather than an n-v-r"))
     (options, args) = parser.parse_args(args)
@@ -1545,8 +1516,7 @@ def handle_write_signed_rpm(goptions, session, args):
 def handle_prune_signed_copies(options, session, args):
     "[admin] Prune signed copies"
     usage = _("usage: %prog prune-sigs [options]")
-    usage += _("\n(Specify the --help global option for a list of other help options)")
-    parser = OptionParser(usage=usage)
+    parser = OptionParser(usage=get_usage_str(usage))
     parser.add_option("-n", "--test", action="store_true", help=_("Test mode"))
     parser.add_option("-v", "--verbose", action="store_true", help=_("Be more verbose"))
     parser.add_option("--days", type="int", default=5, help=_("Timeout before clearing"))
@@ -1893,8 +1863,7 @@ def handle_prune_signed_copies(options, session, args):
 def handle_set_build_volume(goptions, session, args):
     "[admin] Move a build to a different volume"
     usage = _("usage: %prog set-build-volume <volume> <n-v-r> [<n-v-r> ...]")
-    usage += _("\n(Specify the --help global option for a list of other help options)")
-    parser = OptionParser(usage=usage)
+    parser = OptionParser(usage=get_usage_str(usage))
     parser.add_option("-v", "--verbose", action="store_true", help=_("Be verbose"))
     (options, args) = parser.parse_args(args)
     if len(args) < 2:
@@ -1925,8 +1894,7 @@ def handle_set_build_volume(goptions, session, args):
 def handle_add_volume(goptions, session, args):
     "[admin] Add a new storage volume"
     usage = _("usage: %prog add-volume <volume-name>")
-    usage += _("\n(Specify the --help global option for a list of other help options)")
-    parser = OptionParser(usage=usage)
+    parser = OptionParser(usage=get_usage_str(usage))
     (options, args) = parser.parse_args(args)
     if len(args) != 1:
         parser.error(_("Command requires exactly one volume-name."))
@@ -1943,8 +1911,7 @@ def handle_add_volume(goptions, session, args):
 def handle_list_volumes(options, session, args):
     "[info] List storage volumes"
     usage = _("usage: %prog list-volumes")
-    usage += _("\n(Specify the --help global option for a list of other help options)")
-    parser = OptionParser(usage=usage)
+    parser = OptionParser(usage=get_usage_str(usage))
     (options, args) = parser.parse_args(args)
     for volinfo in session.listVolumes():
         print(volinfo['name'])
@@ -1953,8 +1920,7 @@ def handle_list_volumes(options, session, args):
 def handle_list_permissions(goptions, session, args):
     "[info] List user permissions"
     usage = _("usage: %prog list-permissions [options]")
-    usage += _("\n(Specify the --help global option for a list of other help options)")
-    parser = OptionParser(usage=usage)
+    parser = OptionParser(usage=get_usage_str(usage))
     parser.add_option("--user", help=_("List permissions for the given user"))
     parser.add_option("--mine", action="store_true", help=_("List your permissions"))
     (options, args) = parser.parse_args(args)
@@ -1978,8 +1944,7 @@ def handle_list_permissions(goptions, session, args):
 def handle_add_user(goptions, session, args):
     "[admin] Add a user"
     usage = _("usage: %prog add-user <username> [options]")
-    usage += _("\n(Specify the --help global option for a list of other help options)")
-    parser = OptionParser(usage=usage)
+    parser = OptionParser(usage=get_usage_str(usage))
     parser.add_option("--principal", help=_("The Kerberos principal for this user"))
     parser.add_option("--disable", help=_("Prohibit logins by this user"), action="store_true")
     (options, args) = parser.parse_args(args)
@@ -2000,8 +1965,7 @@ def handle_add_user(goptions, session, args):
 def handle_enable_user(goptions, session, args):
     "[admin] Enable logins by a user"
     usage = _("usage: %prog enable-user <username>")
-    usage += _("\n(Specify the --help global option for a list of other help options)")
-    parser = OptionParser(usage=usage)
+    parser = OptionParser(usage=get_usage_str(usage))
     (options, args) = parser.parse_args(args)
     if len(args) < 1:
         parser.error(_("You must specify the username of the user to enable"))
@@ -2015,8 +1979,7 @@ def handle_enable_user(goptions, session, args):
 def handle_disable_user(goptions, session, args):
     "[admin] Disable logins by a user"
     usage = _("usage: %prog disable-user <username>")
-    usage += _("\n(Specify the --help global option for a list of other help options)")
-    parser = OptionParser(usage=usage)
+    parser = OptionParser(usage=get_usage_str(usage))
     (options, args) = parser.parse_args(args)
     if len(args) < 1:
         parser.error(_("You must specify the username of the user to disable"))
@@ -2030,8 +1993,7 @@ def handle_disable_user(goptions, session, args):
 def handle_edit_user(goptions, session, args):
     "[admin] Alter user information"
     usage = _("usage: %prog edit-user <username> [options]")
-    usage += _("\n(Specify the --help global option for a list of other help options)")
-    parser = OptionParser(usage=usage)
+    parser = OptionParser(usage=get_usage_str(usage))
     parser.add_option("--rename", help=_("Rename the user"))
     parser.add_option("--edit-krb", action="append", default=[],
                       metavar="OLD=NEW",
@@ -2062,8 +2024,7 @@ def handle_edit_user(goptions, session, args):
 def handle_list_signed(goptions, session, args):
     "[admin] List signed copies of rpms"
     usage = _("usage: %prog list-signed [options]")
-    usage += _("\n(Specify the --help global option for a list of other help options)")
-    parser = OptionParser(usage=usage)
+    parser = OptionParser(usage=get_usage_str(usage))
     parser.add_option("--debug", action="store_true")
     parser.add_option("--key", help=_("Only list RPMs signed with this key"))
     parser.add_option("--build", help=_("Only list RPMs from this build"))
@@ -2134,8 +2095,7 @@ def handle_list_signed(goptions, session, args):
 def handle_import_archive(options, session, args):
     "[admin] Import an archive file and associate it with a build"
     usage = _("usage: %prog import-archive <build-id|n-v-r> <archive_path> [<archive_path2 ...]")
-    usage += _("\n(Specify the --help global option for a list of other help options)")
-    parser = OptionParser(usage=usage)
+    parser = OptionParser(usage=get_usage_str(usage))
     parser.add_option("--noprogress", action="store_true",
                       help=_("Do not display progress of the upload"))
     parser.add_option("--create-build", action="store_true", help=_("Auto-create builds as needed"))
@@ -2230,8 +2190,7 @@ def handle_import_archive(options, session, args):
 def handle_grant_permission(goptions, session, args):
     "[admin] Grant a permission to a user"
     usage = _("usage: %prog grant-permission <permission> <user> [<user> ...]")
-    usage += _("\n(Specify the --help global option for a list of other help options)")
-    parser = OptionParser(usage=usage)
+    parser = OptionParser(usage=get_usage_str(usage))
     parser.add_option("--new", action="store_true", help=_("Create a new permission"))
     (options, args) = parser.parse_args(args)
     if len(args) < 2:
@@ -2255,8 +2214,7 @@ def handle_grant_permission(goptions, session, args):
 def handle_revoke_permission(goptions, session, args):
     "[admin] Revoke a permission from a user"
     usage = _("usage: %prog revoke-permission <permission> <user> [<user> ...]")
-    usage += _("\n(Specify the --help global option for a list of other help options)")
-    parser = OptionParser(usage=usage)
+    parser = OptionParser(usage=get_usage_str(usage))
     (options, args) = parser.parse_args(args)
     if len(args) < 2:
         parser.error(_("Please specify a permission and at least one user"))
@@ -2276,8 +2234,7 @@ def handle_revoke_permission(goptions, session, args):
 def handle_grant_cg_access(goptions, session, args):
     "[admin] Add a user to a content generator"
     usage = _("usage: %prog grant-cg-access <user> <content generator>")
-    usage += _("\n(Specify the --help global option for a list of other help options)")
-    parser = OptionParser(usage=usage)
+    parser = OptionParser(usage=get_usage_str(usage))
     parser.add_option("--new", action="store_true", help=_("Create a new content generator"))
     (options, args) = parser.parse_args(args)
     if len(args) != 2:
@@ -2297,8 +2254,7 @@ def handle_grant_cg_access(goptions, session, args):
 def handle_revoke_cg_access(goptions, session, args):
     "[admin] Remove a user from a content generator"
     usage = _("usage: %prog revoke-cg-access <user> <content generator>")
-    usage += _("\n(Specify the --help global option for a list of other help options)")
-    parser = OptionParser(usage=usage)
+    parser = OptionParser(usage=get_usage_str(usage))
     (options, args) = parser.parse_args(args)
     if len(args) != 2:
         parser.error(_("Please specify a user and content generator"))
@@ -2314,8 +2270,7 @@ def handle_revoke_cg_access(goptions, session, args):
 def anon_handle_latest_build(goptions, session, args):
     "[info] Print the latest builds for a tag"
     usage = _("usage: %prog latest-build [options] <tag> <package> [<package> ...]")
-    usage += _("\n(Specify the --help global option for a list of other help options)")
-    parser = OptionParser(usage=usage)
+    parser = OptionParser(usage=get_usage_str(usage))
     parser.add_option("--arch", help=_("List all of the latest packages for this arch"))
     parser.add_option("--all", action="store_true", help=_("List all of the latest packages for this tag"))
     parser.add_option("--quiet", action="store_true", default=goptions.quiet,
@@ -2386,8 +2341,7 @@ def anon_handle_latest_build(goptions, session, args):
 def anon_handle_list_api(goptions, session, args):
     "[info] Print the list of XML-RPC APIs"
     usage = _("usage: %prog list-api [options]")
-    usage += _("\n(Specify the --help global option for a list of other help options)")
-    parser = OptionParser(usage=usage)
+    parser = OptionParser(usage=get_usage_str(usage))
     (options, args) = parser.parse_args(args)
     if len(args) != 0:
         parser.error(_("This command takes no arguments"))
@@ -2417,8 +2371,7 @@ def anon_handle_list_api(goptions, session, args):
 def anon_handle_list_tagged(goptions, session, args):
     "[info] List the builds or rpms in a tag"
     usage = _("usage: %prog list-tagged [options] <tag> [<package>]")
-    usage += _("\n(Specify the --help global option for a list of other help options)")
-    parser = OptionParser(usage=usage)
+    parser = OptionParser(usage=get_usage_str(usage))
     parser.add_option("--arch", action="append", default=[], help=_("List rpms for this arch"))
     parser.add_option("--rpms", action="store_true", help=_("Show rpms instead of builds"))
     parser.add_option("--inherit", action="store_true", help=_("Follow inheritance"))
@@ -2526,8 +2479,7 @@ def anon_handle_list_tagged(goptions, session, args):
 def anon_handle_list_buildroot(goptions, session, args):
     "[info] List the rpms used in or built in a buildroot"
     usage = _("usage: %prog list-buildroot [options] <buildroot-id>")
-    usage += _("\n(Specify the --help global option for a list of other help options)")
-    parser = OptionParser(usage=usage)
+    parser = OptionParser(usage=get_usage_str(usage))
     parser.add_option("--paths", action="store_true", help=_("Show the file paths"))
     parser.add_option("--built", action="store_true", help=_("Show the built rpms"))
     parser.add_option("--verbose", "-v", action="store_true", help=_("Show more information"))
@@ -2556,8 +2508,7 @@ def anon_handle_list_buildroot(goptions, session, args):
 def anon_handle_list_untagged(goptions, session, args):
     "[info] List untagged builds"
     usage = _("usage: %prog list-untagged [options] [<package>]")
-    usage += _("\n(Specify the --help global option for a list of other help options)")
-    parser = OptionParser(usage=usage)
+    parser = OptionParser(usage=get_usage_str(usage))
     parser.add_option("--paths", action="store_true", help=_("Show the file paths"))
     parser.add_option("--show-references", action="store_true", help=_("Show build references"))
     (options, args) = parser.parse_args(args)
@@ -2619,8 +2570,7 @@ def print_group_list_req_package(pkg):
 def anon_handle_list_groups(goptions, session, args):
     "[info] Print the group listings"
     usage = _("usage: %prog list-groups [options] <tag> [<group>]")
-    usage += _("\n(Specify the --help global option for a list of other help options)")
-    parser = OptionParser(usage=usage)
+    parser = OptionParser(usage=get_usage_str(usage))
     parser.add_option("--event", type='int', metavar="EVENT#", help=_("query at event"))
     parser.add_option("--ts", type='int', metavar="TIMESTAMP", help=_("query at last event before timestamp"))
     parser.add_option("--repo", type='int', metavar="REPO#", help=_("query at event for a repo"))
@@ -2660,8 +2610,7 @@ def anon_handle_list_groups(goptions, session, args):
 def handle_add_group_pkg(goptions, session, args):
     "[admin] Add a package to a group's package listing"
     usage = _("usage: %prog add-group-pkg [options] <tag> <group> <pkg> [<pkg> ...]")
-    usage += _("\n(Specify the --help global option for a list of other help options)")
-    parser = OptionParser(usage=usage)
+    parser = OptionParser(usage=get_usage_str(usage))
     (options, args) = parser.parse_args(args)
     if len(args) < 3:
         parser.error(_("You must specify a tag name, group name, and one or more package names"))
@@ -2677,8 +2626,7 @@ def handle_block_group_pkg(goptions, session, args):
     usage = _("usage: %prog block-group-pkg [options] <tag> <group> <pkg> [<pkg> ...]")
     usage += '\n' + _("Note that blocking is propagated through the inheritance chain, so "
                       "it is not exactly the same as package removal.")
-    usage += _("\n(Specify the --help global option for a list of other help options)")
-    parser = OptionParser(usage=usage)
+    parser = OptionParser(usage=get_usage_str(usage))
     (options, args) = parser.parse_args(args)
     if len(args) < 3:
         parser.error(_("You must specify a tag name, group name, and one or more package names"))
@@ -2692,8 +2640,7 @@ def handle_block_group_pkg(goptions, session, args):
 def handle_unblock_group_pkg(goptions, session, args):
     "[admin] Unblock a package from a group's package listing"
     usage = _("usage: %prog unblock-group-pkg [options] <tag> <group> <pkg> [<pkg> ...]")
-    usage += _("\n(Specify the --help global option for a list of other help options)")
-    parser = OptionParser(usage=usage)
+    parser = OptionParser(usage=get_usage_str(usage))
     (options, args) = parser.parse_args(args)
     if len(args) < 3:
         parser.error(_("You must specify a tag name, group name, and one or more package names"))
@@ -2707,8 +2654,7 @@ def handle_unblock_group_pkg(goptions, session, args):
 def handle_add_group_req(goptions, session, args):
     "[admin] Add a group to a group's required list"
     usage = _("usage: %prog add-group-req [options] <tag> <target group> <required group>")
-    usage += _("\n(Specify the --help global option for a list of other help options)")
-    parser = OptionParser(usage=usage)
+    parser = OptionParser(usage=get_usage_str(usage))
     (options, args) = parser.parse_args(args)
     if len(args) != 3:
         parser.error(_("You must specify a tag name and two group names"))
@@ -2722,8 +2668,7 @@ def handle_add_group_req(goptions, session, args):
 def handle_block_group_req(goptions, session, args):
     "[admin] Block a group's requirement listing"
     usage = _("usage: %prog block-group-req [options] <tag> <group> <blocked req>")
-    usage += _("\n(Specify the --help global option for a list of other help options)")
-    parser = OptionParser(usage=usage)
+    parser = OptionParser(usage=get_usage_str(usage))
     (options, args) = parser.parse_args(args)
     if len(args) != 3:
         parser.error(_("You must specify a tag name and two group names"))
@@ -2737,8 +2682,7 @@ def handle_block_group_req(goptions, session, args):
 def handle_unblock_group_req(goptions, session, args):
     "[admin] Unblock a group's requirement listing"
     usage = _("usage: %prog unblock-group-req [options] <tag> <group> <requirement>")
-    usage += _("\n(Specify the --help global option for a list of other help options)")
-    parser = OptionParser(usage=usage)
+    parser = OptionParser(usage=get_usage_str(usage))
     (options, args) = parser.parse_args(args)
     if len(args) != 3:
         parser.error(_("You must specify a tag name and two group names"))
@@ -2752,8 +2696,7 @@ def handle_unblock_group_req(goptions, session, args):
 def anon_handle_list_channels(goptions, session, args):
     "[info] Print channels listing"
     usage = _("usage: %prog list-channels")
-    usage += _("\n(Specify the --help global option for a list of other help options)")
-    parser = OptionParser(usage=usage)
+    parser = OptionParser(usage=get_usage_str(usage))
     parser.add_option("--simple", action="store_true", default=False,
                 help=_("Print just list of channels without additional info"))
     parser.add_option("--quiet", action="store_true", default=goptions.quiet,
@@ -2790,8 +2733,7 @@ def anon_handle_list_channels(goptions, session, args):
 def anon_handle_list_hosts(goptions, session, args):
     "[info] Print the host listing"
     usage = _("usage: %prog list-hosts [options]")
-    usage += _("\n(Specify the --help global option for a list of other help options)")
-    parser = OptionParser(usage=usage)
+    parser = OptionParser(usage=get_usage_str(usage))
     parser.add_option("--arch", action="append", default=[], help=_("Specify an architecture"))
     parser.add_option("--channel", help=_("Specify a channel"))
     parser.add_option("--ready", action="store_true", help=_("Limit to ready hosts"))
@@ -2866,8 +2808,7 @@ def anon_handle_list_hosts(goptions, session, args):
 def anon_handle_list_pkgs(goptions, session, args):
     "[info] Print the package listing for tag or for owner"
     usage = _("usage: %prog list-pkgs [options]")
-    usage += _("\n(Specify the --help global option for a list of other help options)")
-    parser = OptionParser(usage=usage)
+    parser = OptionParser(usage=get_usage_str(usage))
     parser.add_option("--owner", help=_("Specify owner"))
     parser.add_option("--tag", help=_("Specify tag"))
     parser.add_option("--package", help=_("Specify package"))
@@ -2952,8 +2893,7 @@ def anon_handle_list_pkgs(goptions, session, args):
 def anon_handle_list_builds(goptions, session, args):
     "[info] Print the build listing"
     usage = _("usage: %prog list-builds [options]")
-    usage += _("\n(Specify the --help global option for a list of other help options)")
-    parser = OptionParser(usage=usage)
+    parser = OptionParser(usage=get_usage_str(usage))
     parser.add_option("--package", help=_("List builds for this package"))
     parser.add_option("--buildid", help=_("List specific build from ID or nvr"))
     parser.add_option("--before",
@@ -3072,8 +3012,7 @@ def anon_handle_list_builds(goptions, session, args):
 def anon_handle_rpminfo(goptions, session, args):
     "[info] Print basic information about an RPM"
     usage = _("usage: %prog rpminfo [options] <n-v-r.a> [<n-v-r.a> ...]")
-    usage += _("\n(Specify the --help global option for a list of other help options)")
-    parser = OptionParser(usage=usage)
+    parser = OptionParser(usage=get_usage_str(usage))
     parser.add_option("--buildroots", action="store_true", help=_("show buildroots the rpm was used in"))
     (options, args) = parser.parse_args(args)
     if len(args) < 1:
@@ -3140,8 +3079,7 @@ def anon_handle_rpminfo(goptions, session, args):
 def anon_handle_buildinfo(goptions, session, args):
     "[info] Print basic information about a build"
     usage = _("usage: %prog buildinfo [options] <n-v-r> [<n-v-r> ...]")
-    usage += _("\n(Specify the --help global option for a list of other help options)")
-    parser = OptionParser(usage=usage)
+    parser = OptionParser(usage=get_usage_str(usage))
     parser.add_option("--changelog", action="store_true", help=_("Show the changelog for the build"))
     (options, args) = parser.parse_args(args)
     if len(args) < 1:
@@ -3232,8 +3170,7 @@ def anon_handle_buildinfo(goptions, session, args):
 def anon_handle_hostinfo(goptions, session, args):
     "[info] Print basic information about a host"
     usage = _("usage: %prog hostinfo [options] <hostname> [<hostname> ...]")
-    usage += _("\n(Specify the --help global option for a list of other help options)")
-    parser = OptionParser(usage=usage)
+    parser = OptionParser(usage=get_usage_str(usage))
     (options, args) = parser.parse_args(args)
     if len(args) < 1:
         parser.error(_("Please specify a host"))
@@ -3291,8 +3228,7 @@ def handle_clone_tag(goptions, session, args):
     "[admin] Duplicate the contents of one tag onto another tag"
     usage = _("usage: %prog clone-tag [options] <src-tag> <dst-tag>")
     usage += _("\nclone-tag will create the destination tag if it does not already exist")
-    usage += _("\n(Specify the --help global option for a list of other help options)")
-    parser = OptionParser(usage=usage)
+    parser = OptionParser(usage=get_usage_str(usage))
     parser.add_option('--config', action='store_true',
             help=_("Copy config from the source to the dest tag"))
     parser.add_option('--groups', action='store_true',
@@ -3763,8 +3699,7 @@ def handle_clone_tag(goptions, session, args):
 def handle_add_target(goptions, session, args):
     "[admin] Create a new build target"
     usage = _("usage: %prog add-target <name> <build tag> <dest tag>")
-    usage += _("\n(Specify the --help global option for a list of other help options)")
-    parser = OptionParser(usage=usage)
+    parser = OptionParser(usage=get_usage_str(usage))
     (options, args) = parser.parse_args(args)
     if len(args) < 2:
         parser.error(_("Please specify a target name, a build tag, and destination tag"))
@@ -3799,8 +3734,7 @@ def handle_add_target(goptions, session, args):
 def handle_edit_target(goptions, session, args):
     "[admin] Set the name, build_tag, and/or dest_tag of an existing build target to new values"
     usage = _("usage: %prog edit-target [options] <name>")
-    usage += _("\n(Specify the --help global option for a list of other help options)")
-    parser = OptionParser(usage=usage)
+    parser = OptionParser(usage=get_usage_str(usage))
     parser.add_option("--rename", help=_("Specify new name for target"))
     parser.add_option("--build-tag", help=_("Specify a different build tag"))
     parser.add_option("--dest-tag", help=_("Specify a different destination tag"))
@@ -3844,8 +3778,7 @@ def handle_edit_target(goptions, session, args):
 def handle_remove_target(goptions, session, args):
     "[admin] Remove a build target"
     usage = _("usage: %prog remove-target [options] <name>")
-    usage += _("\n(Specify the --help global option for a list of other help options)")
-    parser = OptionParser(usage=usage)
+    parser = OptionParser(usage=get_usage_str(usage))
     (options, args) = parser.parse_args(args)
 
     if len(args) != 1:
@@ -3867,8 +3800,7 @@ def handle_remove_target(goptions, session, args):
 def handle_remove_tag(goptions, session, args):
     "[admin] Remove a tag"
     usage = _("usage: %prog remove-tag [options] <name>")
-    usage += _("\n(Specify the --help global option for a list of other help options)")
-    parser = OptionParser(usage=usage)
+    parser = OptionParser(usage=get_usage_str(usage))
     (options, args) = parser.parse_args(args)
 
     if len(args) != 1:
@@ -3890,8 +3822,7 @@ def handle_remove_tag(goptions, session, args):
 def anon_handle_list_targets(goptions, session, args):
     "[info] List the build targets"
     usage = _("usage: %prog list-targets [options]")
-    usage += _("\n(Specify the --help global option for a list of other help options)")
-    parser = OptionParser(usage=usage)
+    parser = OptionParser(usage=get_usage_str(usage))
     parser.add_option("--name", help=_("Specify the build target name"))
     parser.add_option("--quiet", action="store_true", default=goptions.quiet,
                 help=_("Do not print the header information"))
@@ -3957,8 +3888,7 @@ def _printInheritance(tags, sibdepths=None, reverse=False):
 def anon_handle_list_tag_inheritance(goptions, session, args):
     "[info] Print the inheritance information for a tag"
     usage = _("usage: %prog list-tag-inheritance [options] <tag>")
-    usage += _("\n(Specify the --help global option for a list of other help options)")
-    parser = OptionParser(usage=usage)
+    parser = OptionParser(usage=get_usage_str(usage))
     parser.add_option("--reverse", action="store_true", help=_("Process tag's children instead of its parents"))
     parser.add_option("--stop", help=_("Stop processing inheritance at this tag"))
     parser.add_option("--jump", help=_("Jump from one tag to another when processing inheritance"))
@@ -4012,8 +3942,7 @@ def anon_handle_list_tag_inheritance(goptions, session, args):
 def anon_handle_list_tags(goptions, session, args):
     "[info] Print the list of tags"
     usage = _("usage: %prog list-tags [options] [pattern]")
-    usage += _("\n(Specify the --help global option for a list of other help options)")
-    parser = OptionParser(usage=usage)
+    parser = OptionParser(usage=get_usage_str(usage))
     parser.add_option("--show-id", action="store_true", help=_("Show tag ids"))
     parser.add_option("--verbose", action="store_true", help=_("Show more information"))
     parser.add_option("--unlocked", action="store_true", help=_("Only show unlocked tags"))
@@ -4067,8 +3996,7 @@ def anon_handle_list_tags(goptions, session, args):
 def anon_handle_list_tag_history(goptions, session, args):
     "[info] Print a history of tag operations"
     usage = _("usage: %prog list-tag-history [options]")
-    usage += _("\n(Specify the --help global option for a list of other help options)")
-    parser = OptionParser(usage=usage)
+    parser = OptionParser(usage=get_usage_str(usage))
     parser.add_option("--debug", action="store_true")
     parser.add_option("--build", help=_("Only show data for a specific build"))
     parser.add_option("--package", help=_("Only show data for a specific package"))
@@ -4363,8 +4291,7 @@ _table_keys = {
 def anon_handle_list_history(goptions, session, args):
     "[info] Display historical data"
     usage = _("usage: %prog list-history [options]")
-    usage += _("\n(Specify the --help global option for a list of other help options)")
-    parser = OptionParser(usage=usage)
+    parser = OptionParser(usage=get_usage_str(usage))
     parser.add_option("--debug", action="store_true")
     parser.add_option("--build", help=_("Only show data for a specific build"))
     parser.add_option("--package", help=_("Only show data for a specific package"))
@@ -4742,8 +4669,7 @@ def _printTaskInfo(session, task_id, topdir, level=0, recurse=True, verbose=True
 def anon_handle_taskinfo(goptions, session, args):
     """[info] Show information about a task"""
     usage = _("usage: %prog taskinfo [options] <task_id> [<task_id> ...]")
-    usage += _("\n(Specify the --help global option for a list of other help options)")
-    parser = OptionParser(usage=usage)
+    parser = OptionParser(usage=get_usage_str(usage))
     parser.add_option("-r", "--recurse", action="store_true", help=_("Show children of this task as well"))
     parser.add_option("-v", "--verbose", action="store_true", help=_("Be verbose"))
     (options, args) = parser.parse_args(args)
@@ -4760,8 +4686,7 @@ def anon_handle_taskinfo(goptions, session, args):
 def anon_handle_taginfo(goptions, session, args):
     "[info] Print basic information about a tag"
     usage = _("usage: %prog taginfo [options] <tag> [<tag> ...]")
-    usage += _("\n(Specify the --help global option for a list of other help options)")
-    parser = OptionParser(usage=usage)
+    parser = OptionParser(usage=get_usage_str(usage))
     parser.add_option("--event", type='int', metavar="EVENT#", help=_("query at event"))
     parser.add_option("--ts", type='int', metavar="TIMESTAMP", help=_("query at last event before timestamp"))
     parser.add_option("--repo", type='int', metavar="REPO#", help=_("query at event for a repo"))
@@ -4853,8 +4778,7 @@ def anon_handle_taginfo(goptions, session, args):
 def handle_add_tag(goptions, session, args):
     "[admin] Add a new tag to the database"
     usage = _("usage: %prog add-tag [options] <name>")
-    usage += _("\n(Specify the --help global option for a list of other help options)")
-    parser = OptionParser(usage=usage)
+    parser = OptionParser(usage=get_usage_str(usage))
     parser.add_option("--parent", help=_("Specify parent"))
     parser.add_option("--arches", help=_("Specify arches"))
     parser.add_option("--maven-support", action="store_true", help=_("Enable creation of Maven repos for this tag"))
@@ -4889,8 +4813,7 @@ def handle_add_tag(goptions, session, args):
 def handle_edit_tag(goptions, session, args):
     "[admin] Alter tag information"
     usage = _("usage: %prog edit-tag [options] <name>")
-    usage += _("\n(Specify the --help global option for a list of other help options)")
-    parser = OptionParser(usage=usage)
+    parser = OptionParser(usage=get_usage_str(usage))
     parser.add_option("--arches", help=_("Specify arches"))
     parser.add_option("--perm", help=_("Specify permission requirement"))
     parser.add_option("--no-perm", action="store_true", help=_("Remove permission requirement"))
@@ -4947,8 +4870,7 @@ def handle_edit_tag(goptions, session, args):
 def handle_lock_tag(goptions, session, args):
     "[admin] Lock a tag"
     usage = _("usage: %prog lock-tag [options] <tag> [<tag> ...] ")
-    usage += _("\n(Specify the --help global option for a list of other help options)")
-    parser = OptionParser(usage=usage)
+    parser = OptionParser(usage=get_usage_str(usage))
     parser.add_option("--perm", help=_("Specify permission requirement"))
     parser.add_option("--glob", action="store_true", help=_("Treat args as glob patterns"))
     parser.add_option("--master", action="store_true", help=_("Lock the master lock"))
@@ -4997,8 +4919,7 @@ def handle_lock_tag(goptions, session, args):
 def handle_unlock_tag(goptions, session, args):
     "[admin] Unlock a tag"
     usage = _("usage: %prog unlock-tag [options] <tag> [<tag> ...]")
-    usage += _("\n(Specify the --help global option for a list of other help options)")
-    parser = OptionParser(usage=usage)
+    parser = OptionParser(usage=get_usage_str(usage))
     parser.add_option("--glob", action="store_true", help=_("Treat args as glob patterns"))
     parser.add_option("-n", "--test", action="store_true", help=_("Test mode"))
     (options, args) = parser.parse_args(args)
@@ -5040,8 +4961,7 @@ def handle_unlock_tag(goptions, session, args):
 def handle_add_tag_inheritance(goptions, session, args):
     """[admin] Add to a tag's inheritance"""
     usage = _("usage: %prog add-tag-inheritance [options] <tag> <parent-tag>")
-    usage += _("\n(Specify the --help global option for a list of other help options)")
-    parser = OptionParser(usage=usage)
+    parser = OptionParser(usage=get_usage_str(usage))
     parser.add_option("--priority", help=_("Specify priority"))
     parser.add_option("--maxdepth", help=_("Specify max depth"))
     parser.add_option("--intransitive", action="store_true", help=_("Set intransitive"))
@@ -5096,8 +5016,7 @@ def handle_add_tag_inheritance(goptions, session, args):
 def handle_edit_tag_inheritance(goptions, session, args):
     """[admin] Edit tag inheritance"""
     usage = _("usage: %prog edit-tag-inheritance [options] <tag> <parent> <priority>")
-    usage += _("\n(Specify the --help global option for a list of other help options)")
-    parser = OptionParser(usage=usage)
+    parser = OptionParser(usage=get_usage_str(usage))
     parser.add_option("--priority", help=_("Specify a new priority"))
     parser.add_option("--maxdepth", help=_("Specify max depth"))
     parser.add_option("--intransitive", action="store_true", help=_("Set intransitive"))
@@ -5182,8 +5101,7 @@ def handle_edit_tag_inheritance(goptions, session, args):
 def handle_remove_tag_inheritance(goptions, session, args):
     """[admin] Remove a tag inheritance link"""
     usage = _("usage: %prog remove-tag-inheritance <tag> <parent> <priority>")
-    usage += _("\n(Specify the --help global option for a list of other help options)")
-    parser = OptionParser(usage=usage)
+    parser = OptionParser(usage=get_usage_str(usage))
     (options, args) = parser.parse_args(args)
 
     if len(args) < 1:
@@ -5244,8 +5162,7 @@ def handle_remove_tag_inheritance(goptions, session, args):
 def anon_handle_show_groups(goptions, session, args):
     "[info] Show groups data for a tag"
     usage = _("usage: %prog show-groups [options] <tag>")
-    usage += _("\n(Specify the --help global option for a list of other help options)")
-    parser = OptionParser(usage=usage)
+    parser = OptionParser(usage=get_usage_str(usage))
     parser.add_option("--comps", action="store_true", help=_("Print in comps format"))
     parser.add_option("-x", "--expand", action="store_true", default=False,
                       help=_("Expand groups in comps format"))
@@ -5273,8 +5190,7 @@ def anon_handle_show_groups(goptions, session, args):
 def anon_handle_list_external_repos(goptions, session, args):
     "[info] List external repos"
     usage = _("usage: %prog list-external-repos [options]")
-    usage += _("\n(Specify the --help global option for a list of other help options)")
-    parser = OptionParser(usage=usage)
+    parser = OptionParser(usage=get_usage_str(usage))
     parser.add_option("--url",  help=_("Select by url"))
     parser.add_option("--name",  help=_("Select by name"))
     parser.add_option("--id", type="int", help=_("Select by id"))
@@ -5375,8 +5291,7 @@ def _parse_tagpri(tagpri):
 def handle_add_external_repo(goptions, session, args):
     "[admin] Create an external repo and/or add one to a tag"
     usage = _("usage: %prog add-external-repo [options] <name> [<url>]")
-    usage += _("\n(Specify the --help global option for a list of other help options)")
-    parser = OptionParser(usage=usage)
+    parser = OptionParser(usage=get_usage_str(usage))
     parser.add_option("-t", "--tag", action="append", metavar="TAG",
                       help=_("Also add repo to tag. Use tag::N to set priority"))
     parser.add_option("-p", "--priority", type='int',
@@ -5419,8 +5334,7 @@ def handle_add_external_repo(goptions, session, args):
 def handle_edit_external_repo(goptions, session, args):
     "[admin] Edit data for an external repo"
     usage = _("usage: %prog edit-external-repo <name>")
-    usage += _("\n(Specify the --help global option for a list of other help options)")
-    parser = OptionParser(usage=usage)
+    parser = OptionParser(usage=get_usage_str(usage))
     parser.add_option("--url",  help=_("Change the url"))
     parser.add_option("--name",  help=_("Change the name"))
     (options, args) = parser.parse_args(args)
@@ -5440,8 +5354,7 @@ def handle_edit_external_repo(goptions, session, args):
 def handle_remove_external_repo(goptions, session, args):
     "[admin] Remove an external repo from a tag or tags, or remove entirely"
     usage = _("usage: %prog remove-external-repo <repo> [<tag> ...]")
-    usage += _("\n(Specify the --help global option for a list of other help options)")
-    parser = OptionParser(usage=usage)
+    parser = OptionParser(usage=get_usage_str(usage))
     parser.add_option("--alltags", action="store_true", help=_("Remove from all tags"))
     parser.add_option("--force", action='store_true', help=_("Force action"))
     (options, args) = parser.parse_args(args)
@@ -5485,8 +5398,7 @@ def handle_spin_livecd(options, session, args):
     usage = _("usage: %prog spin-livecd [options] <name> <version> <target>" +
               " <arch> <kickstart-file>")
     usage += _("\n(Specify the --help global option for a list of other " +
-               "help options)")
-    parser = OptionParser(usage=usage)
+    parser = OptionParser(usage=get_usage_str(usage))
     parser.add_option("--wait", action="store_true",
         help=_("Wait on the livecd creation, even if running in the background"))
     parser.add_option("--nowait", action="store_false", dest="wait",
@@ -5532,8 +5444,7 @@ def handle_spin_livemedia(options, session, args):
     usage = _("usage: %prog spin-livemedia [options] <name> <version> <target>" +
               " <arch> <kickstart-file>")
     usage += _("\n(Specify the --help global option for a list of other " +
-               "help options)")
-    parser = OptionParser(usage=usage)
+    parser = OptionParser(usage=get_usage_str(usage))
     parser.add_option("--wait", action="store_true",
         help=_("Wait on the livemedia creation, even if running in the background"))
     parser.add_option("--nowait", action="store_false", dest="wait",
@@ -5594,8 +5505,7 @@ def handle_spin_appliance(options, session, args):
     usage = _("usage: %prog spin-appliance [options] <name> <version> " +
               "<target> <arch> <kickstart-file>")
     usage += _("\n(Specify the --help global option for a list of other " +
-               "help options)")
-    parser = OptionParser(usage=usage)
+    parser = OptionParser(usage=get_usage_str(usage))
     parser.add_option("--wait", action="store_true",
         help=_("Wait on the appliance creation, even if running in the background"))
     parser.add_option("--nowait", action="store_false", dest="wait",
@@ -5646,8 +5556,7 @@ def handle_image_build_indirection(options, session, args):
               "[utility_image] [indirection_build_template]")
     usage += _("\n       %prog image-build --config FILE")
     usage += _("\n\n(Specify the --help global option for a list of other " +
-               "help options)")
-    parser = OptionParser(usage=usage)
+    parser = OptionParser(usage=get_usage_str(usage))
     parser.add_option("--config",
         help=_("Use a configuration file to define image-build options " +
                "instead of command line options (they will be ignored)."))
@@ -5791,8 +5700,7 @@ def handle_image_build(options, session, args):
               "<target> <install-tree-url> <arch> [<arch> ...]")
     usage += _("\n       %prog image-build --config FILE")
     usage += _("\n\n(Specify the --help global option for a list of other " +
-               "help options)")
-    parser = OptionParser(usage=usage)
+    parser = OptionParser(usage=get_usage_str(usage))
     parser.add_option("--background", action="store_true",
         help=_("Run the image creation task at a lower priority"))
     parser.add_option("--config",
@@ -6056,8 +5964,7 @@ def handle_win_build(options, session, args):
     # Usage & option parsing
     usage = _("usage: %prog win-build [options] <target> <URL> <VM>")
     usage += _("\n(Specify the --help global option for a list of other " +
-               "help options)")
-    parser = OptionParser(usage=usage)
+    parser = OptionParser(usage=get_usage_str(usage))
     parser.add_option("--winspec", metavar="URL",
                       help=_("SCM URL to retrieve the build descriptor from. " + \
                              "If not specified, the winspec must be in the root directory " + \
@@ -6132,8 +6039,7 @@ def handle_win_build(options, session, args):
 def handle_free_task(goptions, session, args):
     "[admin] Free a task"
     usage = _("usage: %prog free-task [options] <task-id> [<task-id> ...]")
-    usage += _("\n(Specify the --help global option for a list of other help options)")
-    parser = OptionParser(usage=usage)
+    parser = OptionParser(usage=get_usage_str(usage))
     (options, args) = parser.parse_args(args)
     activate_session(session, goptions)
     tlist = []
@@ -6151,8 +6057,7 @@ def handle_free_task(goptions, session, args):
 def handle_cancel(goptions, session, args):
     "[build] Cancel tasks and/or builds"
     usage = _("usage: %prog cancel [options] <task-id|build> [<task-id|build> ...]")
-    usage += _("\n(Specify the --help global option for a list of other help options)")
-    parser = OptionParser(usage=usage)
+    parser = OptionParser(usage=get_usage_str(usage))
     parser.add_option("--justone", action="store_true", help=_("Do not cancel subtasks"))
     parser.add_option("--full", action="store_true", help=_("Full cancellation (admin only)"))
     parser.add_option("--force", action="store_true", help=_("Allow subtasks with --full"))
@@ -6189,8 +6094,7 @@ def handle_cancel(goptions, session, args):
 def handle_set_task_priority(goptions, session, args):
     "[admin] Set task priority"
     usage = _("usage: %prog set-task-priority [options] --priority=<priority> <task-id> [<task-id> ...]")
-    usage += _("\n(Specify the --help global option for a list of other help options)")
-    parser = OptionParser(usage=usage)
+    parser = OptionParser(usage=get_usage_str(usage))
     parser.add_option("--priority", type="int", help=_("New priority"))
     parser.add_option("--recurse", action="store_true", default=False, help=_("Change priority of child tasks as well"))
     (options, args) = parser.parse_args(args)
@@ -6213,8 +6117,7 @@ def handle_set_task_priority(goptions, session, args):
 def handle_list_tasks(goptions, session, args):
     "[info] Print the list of tasks"
     usage = _("usage: %prog list-tasks [options]")
-    usage += _("\n(Specify the --help global option for a list of other help options)")
-    parser = OptionParser(usage=usage)
+    parser = OptionParser(usage=get_usage_str(usage))
     parser.add_option("--mine", action="store_true", help=_("Just print your tasks"))
     parser.add_option("--user", help=_("Only tasks for this user"))
     parser.add_option("--arch", help=_("Only tasks for this architecture"))
@@ -6244,8 +6147,7 @@ def handle_list_tasks(goptions, session, args):
 def handle_set_pkg_arches(goptions, session, args):
     "[admin] Set the list of extra arches for a package"
     usage = _("usage: %prog set-pkg-arches [options] <arches> <tag> <package> [<package> ...]")
-    usage += _("\n(Specify the --help global option for a list of other help options)")
-    parser = OptionParser(usage=usage)
+    parser = OptionParser(usage=get_usage_str(usage))
     parser.add_option("--force", action='store_true', help=_("Force operation"))
     (options, args) = parser.parse_args(args)
     if len(args) < 3:
@@ -6261,8 +6163,7 @@ def handle_set_pkg_arches(goptions, session, args):
 def handle_set_pkg_owner(goptions, session, args):
     "[admin] Set the owner for a package"
     usage = _("usage: %prog set-pkg-owner [options] <owner> <tag> <package> [<package> ...]")
-    usage += _("\n(Specify the --help global option for a list of other help options)")
-    parser = OptionParser(usage=usage)
+    parser = OptionParser(usage=get_usage_str(usage))
     parser.add_option("--force", action='store_true', help=_("Force operation"))
     (options, args) = parser.parse_args(args)
     if len(args) < 3:
@@ -6278,8 +6179,7 @@ def handle_set_pkg_owner(goptions, session, args):
 def handle_set_pkg_owner_global(goptions, session, args):
     "[admin] Set the owner for a package globally"
     usage = _("usage: %prog set-pkg-owner-global [options] <owner> <package> [<package> ...]")
-    usage += _("\n(Specify the --help global option for a list of other help options)")
-    parser = OptionParser(usage=usage)
+    parser = OptionParser(usage=get_usage_str(usage))
     parser.add_option("--verbose", action='store_true', help=_("List changes"))
     parser.add_option("--test", action='store_true', help=_("Test mode"))
     parser.add_option("--old-user", "--from", action="store", help=_("Only change ownership for packages belonging to this user"))
@@ -6336,8 +6236,7 @@ def handle_set_pkg_owner_global(goptions, session, args):
 def anon_handle_watch_task(goptions, session, args):
     "[monitor] Track progress of particular tasks"
     usage = _("usage: %prog watch-task [options] <task id> [<task id> ...]")
-    usage += _("\n(Specify the --help global option for a list of other help options)")
-    parser = OptionParser(usage=usage)
+    parser = OptionParser(usage=get_usage_str(usage))
     parser.add_option("--quiet", action="store_true", default=goptions.quiet,
                       help=_("Do not print the task information"))
     parser.add_option("--mine", action="store_true", help=_("Just watch your tasks"))
@@ -6379,8 +6278,7 @@ def anon_handle_watch_task(goptions, session, args):
 def anon_handle_watch_logs(goptions, session, args):
     "[monitor] Watch logs in realtime"
     usage = _("usage: %prog watch-logs [options] <task id> [<task id> ...]")
-    usage += _("\n(Specify the --help global option for a list of other help options)")
-    parser = OptionParser(usage=usage)
+    parser = OptionParser(usage=get_usage_str(usage))
     parser.add_option("--log", help=_("Watch only a specific log"))
     parser.add_option("--mine", action="store_true", help=_("Watch logs for "
         "all your tasks, task_id arguments are forbidden in this case."))
@@ -6412,8 +6310,7 @@ def anon_handle_watch_logs(goptions, session, args):
 def handle_make_task(goptions, session, args):
     "[admin] Create an arbitrary task"
     usage = _("usage: %prog make-task [options] <method> [<arg> ...]")
-    usage += _("\n(Specify the --help global option for a list of other help options)")
-    parser = OptionParser(usage=usage)
+    parser = OptionParser(usage=get_usage_str(usage))
     parser.add_option("--channel", help=_("set channel"))
     parser.add_option("--priority", help=_("set priority"))
     parser.add_option("--watch", action="store_true", help=_("watch the task"))
@@ -6443,8 +6340,7 @@ def handle_make_task(goptions, session, args):
 def handle_tag_build(opts, session, args):
     "[bind] Apply a tag to one or more builds"
     usage = _("usage: %prog tag-build [options] <tag> <pkg> [<pkg> ...]")
-    usage += _("\n(Specify the --help global option for a list of other help options)")
-    parser = OptionParser(usage=usage)
+    parser = OptionParser(usage=get_usage_str(usage))
     parser.add_option("--force", action="store_true", help=_("force operation"))
     parser.add_option("--nowait", action="store_true", help=_("Do not wait on task"))
     (options, args) = parser.parse_args(args)
@@ -6467,9 +6363,7 @@ def handle_tag_build(opts, session, args):
 
 def handle_move_build(opts, session, args):
     "[bind] 'Move' one or more builds between tags"
-    usage = _("usage: %prog move-build [options] <tag1> <tag2> <pkg> [<pkg> ...]")
-    usage += _("\n(Specify the --help global option for a list of other help options)")
-    parser = OptionParser(usage=usage)
+    parser = OptionParser(usage=get_usage_str(uget_usage_str(usage))
     parser.add_option("--force", action="store_true", help=_("force operation"))
     parser.add_option("--nowait", action="store_true", help=_("do not wait on tasks"))
     parser.add_option("--all", action="store_true", help=_("move all instances of a package, <pkg>'s are package names"))
@@ -6515,8 +6409,7 @@ def handle_move_build(opts, session, args):
 def handle_untag_build(goptions, session, args):
     "[bind] Remove a tag from one or more builds"
     usage = _("usage: %prog untag-build [options] <tag> <pkg> [<pkg> ...]")
-    usage += _("\n(Specify the --help global option for a list of other help options)")
-    parser = OptionParser(usage=usage)
+    parser = OptionParser(usage=get_usage_str(usage))
     parser.add_option("--all", action="store_true", help=_("untag all versions of the package in this tag"))
     parser.add_option("--non-latest", action="store_true", help=_("untag all versions of the package in this tag except the latest"))
     parser.add_option("-n", "--test", action="store_true", help=_("test mode"))
@@ -6584,8 +6477,7 @@ def handle_untag_build(goptions, session, args):
 def handle_unblock_pkg(goptions, session, args):
     "[admin] Unblock a package in the listing for tag"
     usage = _("usage: %prog unblock-pkg [options] <tag> <package> [<package> ...]")
-    usage += _("\n(Specify the --help global option for a list of other help options)")
-    parser = OptionParser(usage=usage)
+    parser = OptionParser(usage=get_usage_str(usage))
     (options, args) = parser.parse_args(args)
     if len(args) < 2:
         parser.error(_("Please specify a tag and at least one package"))
@@ -6599,8 +6491,7 @@ def handle_unblock_pkg(goptions, session, args):
 def anon_handle_download_build(options, session, args):
     "[download] Download a built package"
     usage = _("usage: %prog download-build [options] <n-v-r | build_id | package>")
-    usage += _("\n(Specify the --help global option for a list of other help options)")
-    parser = OptionParser(usage=usage)
+    parser = OptionParser(usage=get_usage_str(usage))
     parser.add_option("--arch", "-a", dest="arches", metavar="ARCH", action="append", default=[],
                       help=_("Only download packages for this arch (may be used multiple times)"))
     parser.add_option("--type", help=_("Download archives of the given type, rather than rpms (maven, win, or image)"))
@@ -6732,8 +6623,7 @@ def anon_handle_download_logs(options, session, args):
     usage = _("usage: %prog download-logs [options] <task-id> [<task-id> ...]")
     usage += _("\n       %prog download-logs [options] --nvr <n-v-r> [<n-v-r> ...]")
     usage += _("\n(Specify the --help global option for a list of other help options)")
-    usage += _("\nCreates special log with name %s if task failed." % FAIL_LOG)
-    parser = OptionParser(usage=usage)
+    parser = OptionParser(usage=get_usage_str(usage))
     parser.add_option("-r", "--recurse", action="store_true",
                       help=_("Process children of this task as well"))
     parser.add_option("--nvr", action="store_true",
@@ -6849,8 +6739,7 @@ def anon_handle_download_logs(options, session, args):
 def anon_handle_download_task(options, session, args):
     "[download] Download the output of a build task"
     usage = _("usage: %prog download-task <task_id>")
-    usage += _("\n(Specify the --help global option for a list of other help options)")
-    parser = OptionParser(usage=usage)
+    parser = OptionParser(usage=get_usage_str(usage))
     parser.add_option("--arch", dest="arches", metavar="ARCH", action="append", default=[],
                       help=_("Only download packages for this arch (may be used multiple times)"))
     parser.add_option("--logs", dest="logs", action="store_true", default=False, help=_("Also download build logs"))
@@ -6937,8 +6826,7 @@ def anon_handle_download_task(options, session, args):
 def anon_handle_wait_repo(options, session, args):
     "[monitor] Wait for a repo to be regenerated"
     usage = _("usage: %prog wait-repo [options] <tag>")
-    usage += _("\n(Specify the --help global option for a list of other help options)")
-    parser = OptionParser(usage=usage)
+    parser = OptionParser(usage=get_usage_str(usage))
     parser.add_option("--build", metavar="NVR", dest="builds", action="append", default=[],
                       help=_("Check that the given build is in the newly-generated repo (may be used multiple times)"))
     parser.add_option("--target", action="store_true", help=_("Interpret the argument as a build target name"))
@@ -7019,8 +6907,7 @@ def anon_handle_wait_repo(options, session, args):
 def handle_regen_repo(options, session, args):
     "[admin] Force a repo to be regenerated"
     usage = _("usage: %prog regen-repo [options] <tag>")
-    usage += _("\n(Specify the --help global option for a list of other help options)")
-    parser = OptionParser(usage=usage)
+    parser = OptionParser(usage=get_usage_str(usage))
     parser.add_option("--target", action="store_true", help=_("Interpret the argument as a build target name"))
     parser.add_option("--nowait", action="store_true", help=_("Don't wait on for regen to finish"))
     parser.add_option("--debuginfo", action="store_true", help=_("Include debuginfo rpms in repo"))
@@ -7074,8 +6961,7 @@ def handle_regen_repo(options, session, args):
 def handle_dist_repo(options, session, args):
     """Create a yum repo with distribution options"""
     usage = _("usage: %prog dist-repo [options] <tag> <keyID> [<keyID> ...]")
-    usage += _("\n(Specify the --help option for a list of other options)")
-    parser = OptionParser(usage=usage)
+    parser = OptionParser(usage=get_usage_str(usage))
     parser.add_option('--allow-missing-signatures', action='store_true',
         default=False,
         help=_('For RPMs not signed with a desired key, fall back to the '
@@ -7205,8 +7091,7 @@ def anon_handle_search(options, session, args):
     "[search] Search the system"
     usage = _("usage: %prog search [options] <search_type> <pattern>")
     usage += _('\nAvailable search types: %s') % ', '.join(_search_types)
-    usage += _("\n(Specify the --help global option for a list of other help options)")
-    parser = OptionParser(usage=usage)
+    parser = OptionParser(usage=get_usage_str(usage))
     parser.add_option("-r", "--regex", action="store_true", help=_("treat pattern as regex"))
     parser.add_option("--exact", action="store_true", help=_("exact matches only"))
     (options, args) = parser.parse_args(args)
@@ -7230,8 +7115,7 @@ def anon_handle_search(options, session, args):
 
 def handle_moshimoshi(options, session, args):
     "[misc] Introduce yourself"
-    usage = _("usage: %prog moshimoshi [options]")
-    parser = OptionParser(usage=usage)
+    parser = OptionParser(usage=get_usage_str(usage))
     (opts, args) = parser.parse_args(args)
     if len(args) != 0:
         parser.error(_("This command takes no arguments"))
@@ -7257,8 +7141,7 @@ def handle_moshimoshi(options, session, args):
 def anon_handle_list_notifications(goptions, session, args):
     "[monitor] List user's notifications and blocks"
     usage = _("usage: %prog list-notifications [options]")
-    usage += _("\n(Specify the --help global option for a list of other help options)")
-    parser = OptionParser(usage=usage)
+    parser = OptionParser(usage=get_usage_str(usage))
     parser.add_option("--mine", action="store_true", help=_("Just print your notifications"))
     parser.add_option("--user", help=_("Only notifications for this user"))
     (options, args) = parser.parse_args(args)
@@ -7327,8 +7210,7 @@ def anon_handle_list_notifications(goptions, session, args):
 def handle_add_notification(goptions, session, args):
     "[monitor] Add user's notification"
     usage = _("usage: %prog add-notification [options]")
-    usage += _("\n(Specify the --help global option for a list of other help options)")
-    parser = OptionParser(usage=usage)
+    parser = OptionParser(usage=get_usage_str(usage))
     parser.add_option("--user", help=_("Add notifications for this user (admin-only)"))
     parser.add_option("--package", help=_("Add notifications for this package"))
     parser.add_option("--tag", help=_("Add notifications for this tag"))
@@ -7372,8 +7254,7 @@ def handle_add_notification(goptions, session, args):
 def handle_remove_notification(goptions, session, args):
     "[monitor] Remove user's notifications"
     usage = _("usage: %prog remove-notification [options] <ID> [<ID> ...]")
-    usage += _("\n(Specify the --help global option for a list of other help options)")
-    parser = OptionParser(usage=usage)
+    parser = OptionParser(usage=get_usage_str(usage))
     (options, args) = parser.parse_args(args)
 
     activate_session(session, goptions)
@@ -7395,8 +7276,7 @@ def handle_remove_notification(goptions, session, args):
 def handle_edit_notification(goptions, session, args):
     "[monitor] Edit user's notification"
     usage = _("usage: %prog edit-notification [options] <ID>")
-    usage += _("\n(Specify the --help global option for a list of other help options)")
-    parser = OptionParser(usage=usage)
+    parser = OptionParser(usage=get_usage_str(usage))
     parser.add_option("--package",
             help=_("Notifications for this package, '*' for all"))
     parser.add_option("--tag",
@@ -7452,8 +7332,7 @@ def handle_edit_notification(goptions, session, args):
 def handle_block_notification(goptions, session, args):
     "[monitor] Block user's notifications"
     usage = _("usage: %prog block-notification [options]")
-    usage += _("\n(Specify the --help global option for a list of other help options)")
-    parser = OptionParser(usage=usage)
+    parser = OptionParser(usage=get_usage_str(usage))
     parser.add_option("--user", help=_("Block notifications for this user (admin-only)"))
     parser.add_option("--package", help=_("Block notifications for this package"))
     parser.add_option("--tag", help=_("Block notifications for this tag"))
@@ -7505,8 +7384,7 @@ def handle_block_notification(goptions, session, args):
 def handle_unblock_notification(goptions, session, args):
     "[monitor] Unblock user's notification"
     usage = _("usage: %prog unblock-notification [options] <ID> [<ID> ...]")
-    usage += _("\n(Specify the --help global option for a list of other help options)")
-    parser = OptionParser(usage=usage)
+    parser = OptionParser(usage=get_usage_str(usage))
     (options, args) = parser.parse_args(args)
 
     activate_session(session, goptions)
diff --git a/cli/koji_cli/lib.py b/cli/koji_cli/lib.py
index 065d855..a49a5c6 100644
--- a/cli/koji_cli/lib.py
+++ b/cli/koji_cli/lib.py
@@ -100,6 +100,9 @@ Available categories are: %(categories)s
     return _(epilog_str)
 
 
+def get_usage_str(usage):
+    return usage + _("\n(Specify the --help global option for a list of other help options)")
+
 def ensure_connection(session):
     try:
         ret = session.getAPIVersion()

From a88829ef6ca804136449989157abfbb60236a8a9 Mon Sep 17 00:00:00 2001
From: Tomas Kopecek <tkopecek@redhat.com>
Date: Dec 10 2019 09:19:04 +0000
Subject: [PATCH 6/7] fix tests


---

diff --git a/cli/koji_cli/commands.py b/cli/koji_cli/commands.py
index a0f4f79..d94209d 100644
--- a/cli/koji_cli/commands.py
+++ b/cli/koji_cli/commands.py
@@ -195,7 +195,7 @@ def handle_add_host(goptions, session, args):
 
 def handle_edit_host(options, session, args):
     "[admin] Edit a host"
-    usage = _("usage: %prog edit-host <hostname> ... [options]")
+    usage = _("usage: %prog edit-host <hostname> [<hostname> ...] [options]")
     parser = OptionParser(usage=get_usage_str(usage))
     parser.add_option("--arches", help=_("Space or comma-separated list of supported architectures"))
     parser.add_option("--capacity", type="float", help=_("Capacity of this host"))
@@ -514,7 +514,7 @@ def handle_build(options, session, args):
 def handle_chain_build(options, session, args):
     # XXX - replace handle_build with this, once chain-building has gotten testing
     "[build] Build one or more packages from source"
-    usage = _("usage: %prog chain-build [options] target URL [URL2 [:] URL3 [:] URL4 ...]")
+    usage = _("usage: %prog chain-build [options] <target> <URL> [<URL> [:] <URL> [:] <URL> ...]")
     parser = OptionParser(usage=get_usage_str(usage))
     parser.add_option("--nowait", action="store_true",
                       help=_("Don't wait on build"))
@@ -589,7 +589,7 @@ def handle_chain_build(options, session, args):
 def handle_maven_build(options, session, args):
     "[build] Build a Maven package from source"
     usage = _("usage: %prog maven-build [options] <target> <URL>")
-    usage += _("\n       %prog maven-build --ini=CONFIG... [options] target")
+    usage += _("\n       %prog maven-build --ini=CONFIG... [options] <target>")
     parser = OptionParser(usage=get_usage_str(usage))
     parser.add_option("--patches", action="store", metavar="URL",
                       help=_("SCM URL of a directory containing patches to apply to the sources before building"))
@@ -5397,7 +5397,6 @@ def handle_spin_livecd(options, session, args):
     # Usage & option parsing.
     usage = _("usage: %prog spin-livecd [options] <name> <version> <target>" +
               " <arch> <kickstart-file>")
-    usage += _("\n(Specify the --help global option for a list of other " +
     parser = OptionParser(usage=get_usage_str(usage))
     parser.add_option("--wait", action="store_true",
         help=_("Wait on the livecd creation, even if running in the background"))
@@ -5443,7 +5442,6 @@ def handle_spin_livemedia(options, session, args):
     # Usage & option parsing.
     usage = _("usage: %prog spin-livemedia [options] <name> <version> <target>" +
               " <arch> <kickstart-file>")
-    usage += _("\n(Specify the --help global option for a list of other " +
     parser = OptionParser(usage=get_usage_str(usage))
     parser.add_option("--wait", action="store_true",
         help=_("Wait on the livemedia creation, even if running in the background"))
@@ -5504,7 +5502,6 @@ def handle_spin_appliance(options, session, args):
     # Usage & option parsing
     usage = _("usage: %prog spin-appliance [options] <name> <version> " +
               "<target> <arch> <kickstart-file>")
-    usage += _("\n(Specify the --help global option for a list of other " +
     parser = OptionParser(usage=get_usage_str(usage))
     parser.add_option("--wait", action="store_true",
         help=_("Wait on the appliance creation, even if running in the background"))
@@ -5554,8 +5551,7 @@ def handle_image_build_indirection(options, session, args):
     """[build] Create a disk image using other disk images via the Indirection plugin"""
     usage = _("usage: %prog image-build-indirection [base_image] " +
               "[utility_image] [indirection_build_template]")
-    usage += _("\n       %prog image-build --config FILE")
-    usage += _("\n\n(Specify the --help global option for a list of other " +
+    usage += _("\n       %prog image-build --config <FILE>\n")
     parser = OptionParser(usage=get_usage_str(usage))
     parser.add_option("--config",
         help=_("Use a configuration file to define image-build options " +
@@ -5698,8 +5694,7 @@ def handle_image_build(options, session, args):
                'liveimg-squashfs', 'tar-gz')
     usage = _("usage: %prog image-build [options] <name> <version> " +
               "<target> <install-tree-url> <arch> [<arch> ...]")
-    usage += _("\n       %prog image-build --config FILE")
-    usage += _("\n\n(Specify the --help global option for a list of other " +
+    usage += _("\n       %prog image-build --config <FILE>\n")
     parser = OptionParser(usage=get_usage_str(usage))
     parser.add_option("--background", action="store_true",
         help=_("Run the image creation task at a lower priority"))
@@ -5963,7 +5958,6 @@ def handle_win_build(options, session, args):
     """[build] Build a Windows package from source"""
     # Usage & option parsing
     usage = _("usage: %prog win-build [options] <target> <URL> <VM>")
-    usage += _("\n(Specify the --help global option for a list of other " +
     parser = OptionParser(usage=get_usage_str(usage))
     parser.add_option("--winspec", metavar="URL",
                       help=_("SCM URL to retrieve the build descriptor from. " + \
@@ -6038,7 +6032,7 @@ def handle_win_build(options, session, args):
 
 def handle_free_task(goptions, session, args):
     "[admin] Free a task"
-    usage = _("usage: %prog free-task [options] <task-id> [<task-id> ...]")
+    usage = _("usage: %prog free-task [options] <task_id> [<task_id> ...]")
     parser = OptionParser(usage=get_usage_str(usage))
     (options, args) = parser.parse_args(args)
     activate_session(session, goptions)
@@ -6047,16 +6041,16 @@ def handle_free_task(goptions, session, args):
         try:
             tlist.append(int(task_id))
         except ValueError:
-            parser.error(_("task-id must be an integer"))
+            parser.error(_("task_id must be an integer"))
     if not tlist:
-        parser.error(_("please specify at least one task-id"))
+        parser.error(_("please specify at least one task_id"))
     for task_id in tlist:
         session.freeTask(task_id)
 
 
 def handle_cancel(goptions, session, args):
     "[build] Cancel tasks and/or builds"
-    usage = _("usage: %prog cancel [options] <task-id|build> [<task-id|build> ...]")
+    usage = _("usage: %prog cancel [options] <task_id|build> [<task_id|build> ...]")
     parser = OptionParser(usage=get_usage_str(usage))
     parser.add_option("--justone", action="store_true", help=_("Do not cancel subtasks"))
     parser.add_option("--full", action="store_true", help=_("Full cancellation (admin only)"))
@@ -6093,7 +6087,7 @@ def handle_cancel(goptions, session, args):
 
 def handle_set_task_priority(goptions, session, args):
     "[admin] Set task priority"
-    usage = _("usage: %prog set-task-priority [options] --priority=<priority> <task-id> [<task-id> ...]")
+    usage = _("usage: %prog set-task-priority [options] --priority=<priority> <task_id> [<task_id> ...]")
     parser = OptionParser(usage=get_usage_str(usage))
     parser.add_option("--priority", type="int", help=_("New priority"))
     parser.add_option("--recurse", action="store_true", default=False, help=_("Change priority of child tasks as well"))
@@ -6363,7 +6357,8 @@ def handle_tag_build(opts, session, args):
 
 def handle_move_build(opts, session, args):
     "[bind] 'Move' one or more builds between tags"
-    parser = OptionParser(usage=get_usage_str(uget_usage_str(usage))
+    usage = _("usage: %prog move-build [options] <tag1> <tag2> <pkg> [<pkg> ...]")
+    parser = OptionParser(usage=get_usage_str(usage))
     parser.add_option("--force", action="store_true", help=_("force operation"))
     parser.add_option("--nowait", action="store_true", help=_("do not wait on tasks"))
     parser.add_option("--all", action="store_true", help=_("move all instances of a package, <pkg>'s are package names"))
@@ -6620,7 +6615,7 @@ def anon_handle_download_logs(options, session, args):
     "[download] Download a logs for package"
 
     FAIL_LOG = "task_failed.log"
-    usage = _("usage: %prog download-logs [options] <task-id> [<task-id> ...]")
+    usage = _("usage: %prog download-logs [options] <task_id> [<task_id> ...]")
     usage += _("\n       %prog download-logs [options] --nvr <n-v-r> [<n-v-r> ...]")
     usage += _("\n(Specify the --help global option for a list of other help options)")
     parser = OptionParser(usage=get_usage_str(usage))
@@ -6960,7 +6955,7 @@ def handle_regen_repo(options, session, args):
 
 def handle_dist_repo(options, session, args):
     """Create a yum repo with distribution options"""
-    usage = _("usage: %prog dist-repo [options] <tag> <keyID> [<keyID> ...]")
+    usage = _("usage: %prog dist-repo [options] <tag> <key_id> [<key_id> ...]")
     parser = OptionParser(usage=get_usage_str(usage))
     parser.add_option('--allow-missing-signatures', action='store_true',
         default=False,
@@ -7115,6 +7110,7 @@ def anon_handle_search(options, session, args):
 
 def handle_moshimoshi(options, session, args):
     "[misc] Introduce yourself"
+    usage = _("usage: %prog moshimoshi [options]")
     parser = OptionParser(usage=get_usage_str(usage))
     (opts, args) = parser.parse_args(args)
     if len(args) != 0:
@@ -7253,7 +7249,7 @@ def handle_add_notification(goptions, session, args):
 
 def handle_remove_notification(goptions, session, args):
     "[monitor] Remove user's notifications"
-    usage = _("usage: %prog remove-notification [options] <ID> [<ID> ...]")
+    usage = _("usage: %prog remove-notification [options] <notification_id> [<notification_id> ...]")
     parser = OptionParser(usage=get_usage_str(usage))
     (options, args) = parser.parse_args(args)
 
@@ -7275,7 +7271,7 @@ def handle_remove_notification(goptions, session, args):
 
 def handle_edit_notification(goptions, session, args):
     "[monitor] Edit user's notification"
-    usage = _("usage: %prog edit-notification [options] <ID>")
+    usage = _("usage: %prog edit-notification [options] <notification_id>")
     parser = OptionParser(usage=get_usage_str(usage))
     parser.add_option("--package",
             help=_("Notifications for this package, '*' for all"))
@@ -7383,7 +7379,7 @@ def handle_block_notification(goptions, session, args):
 
 def handle_unblock_notification(goptions, session, args):
     "[monitor] Unblock user's notification"
-    usage = _("usage: %prog unblock-notification [options] <ID> [<ID> ...]")
+    usage = _("usage: %prog unblock-notification [options] <notification_id> [<notification_id> ...]")
     parser = OptionParser(usage=get_usage_str(usage))
     (options, args) = parser.parse_args(args)
 
diff --git a/tests/test_cli/test_add_group_pkg.py b/tests/test_cli/test_add_group_pkg.py
index 4eddb13..1531c19 100644
--- a/tests/test_cli/test_add_group_pkg.py
+++ b/tests/test_cli/test_add_group_pkg.py
@@ -19,7 +19,7 @@ class TestAddGroupPkg(utils.CliTestCase):
         self.options = mock.MagicMock()
         self.activate_session = mock.patch('koji_cli.commands.activate_session').start()
 
-        self.error_format = """Usage: %s add-group-pkg [options] <tag> <group> <pkg> [<pkg>...]
+        self.error_format = """Usage: %s add-group-pkg [options] <tag> <group> <pkg> [<pkg> ...]
 (Specify the --help global option for a list of other help options)
 
 %s: error: {message}
@@ -54,7 +54,7 @@ class TestAddGroupPkg(utils.CliTestCase):
     def test_handle_add_group_pkg_help(self):
         self.assert_help(
             handle_add_group_pkg,
-            """Usage: %s add-group-pkg [options] <tag> <group> <pkg> [<pkg>...]
+            """Usage: %s add-group-pkg [options] <tag> <group> <pkg> [<pkg> ...]
 (Specify the --help global option for a list of other help options)
 
 Options:
diff --git a/tests/test_cli/test_add_host.py b/tests/test_cli/test_add_host.py
index 11b83f0..94260ad 100644
--- a/tests/test_cli/test_add_host.py
+++ b/tests/test_cli/test_add_host.py
@@ -116,7 +116,7 @@ class TestAddHost(unittest.TestCase):
         actual_stdout = stdout.getvalue()
         actual_stderr = stderr.getvalue()
         expected_stdout = ''
-        expected_stderr = """Usage: %s add-host [options] hostname arch [arch2 ...]
+        expected_stderr = """Usage: %s add-host [options] <hostname> <arch> [<arch> ...]
 (Specify the --help global option for a list of other help options)
 
 %s: error: Please specify a hostname and at least one arch
diff --git a/tests/test_cli/test_add_host_to_channel.py b/tests/test_cli/test_add_host_to_channel.py
index 80ebf18..9220bfe 100644
--- a/tests/test_cli/test_add_host_to_channel.py
+++ b/tests/test_cli/test_add_host_to_channel.py
@@ -182,7 +182,7 @@ class TestAddHostToChannel(unittest.TestCase):
         actual_stdout = stdout.getvalue()
         actual_stderr = stderr.getvalue()
         expected_stdout = ''
-        expected_stderr = """Usage: %s add-host-to-channel [options] hostname channel
+        expected_stderr = """Usage: %s add-host-to-channel [options] <hostname> <channel>
 (Specify the --help global option for a list of other help options)
 
 %s: error: Please specify a hostname and a channel
diff --git a/tests/test_cli/test_add_pkg.py b/tests/test_cli/test_add_pkg.py
index 8072a18..2a3a823 100644
--- a/tests/test_cli/test_add_pkg.py
+++ b/tests/test_cli/test_add_pkg.py
@@ -202,7 +202,7 @@ class TestAddPkg(unittest.TestCase):
         actual_stdout = stdout.getvalue()
         actual_stderr = stderr.getvalue()
         expected_stdout = ''
-        expected_stderr = """Usage: %s add-pkg [options] tag package [package2 ...]
+        expected_stderr = """Usage: %s add-pkg [options] <tag> <package> [<package> ...]
 (Specify the --help global option for a list of other help options)
 
 %s: error: Please specify an owner for the package(s)
@@ -239,7 +239,7 @@ class TestAddPkg(unittest.TestCase):
         actual_stdout = stdout.getvalue()
         actual_stderr = stderr.getvalue()
         expected_stdout = ''
-        expected_stderr = """Usage: %s add-pkg [options] tag package [package2 ...]
+        expected_stderr = """Usage: %s add-pkg [options] <tag> <package> [<package> ...]
 (Specify the --help global option for a list of other help options)
 
 %s: error: Please specify a tag and at least one package
diff --git a/tests/test_cli/test_add_tag.py b/tests/test_cli/test_add_tag.py
index 72f4a96..c24c3e3 100644
--- a/tests/test_cli/test_add_tag.py
+++ b/tests/test_cli/test_add_tag.py
@@ -16,7 +16,7 @@ class TestAddTag(utils.CliTestCase):
     maxDiff = None
 
     def setUp(self):
-        self.error_format = """Usage: %s add-tag [options] name
+        self.error_format = """Usage: %s add-tag [options] <name>
 (Specify the --help global option for a list of other help options)
 
 %s: error: {message}
@@ -80,7 +80,7 @@ class TestAddTag(utils.CliTestCase):
     def test_handle_add_tag_help(self):
         self.assert_help(
             handle_add_tag,
-            """Usage: %s add-tag [options] name
+            """Usage: %s add-tag [options] <name>
 (Specify the --help global option for a list of other help options)
 
 Options:
diff --git a/tests/test_cli/test_add_user.py b/tests/test_cli/test_add_user.py
index 2b2f591..388f60e 100644
--- a/tests/test_cli/test_add_user.py
+++ b/tests/test_cli/test_add_user.py
@@ -16,7 +16,7 @@ class TestAddUser(utils.CliTestCase):
     maxDiff = None
 
     def setUp(self):
-        self.error_format = """Usage: %s add-user username [options]
+        self.error_format = """Usage: %s add-user <username> [options]
 (Specify the --help global option for a list of other help options)
 
 %s: error: {message}
@@ -82,7 +82,7 @@ class TestAddUser(utils.CliTestCase):
     def test_handle_add_user_help(self):
         self.assert_help(
             handle_add_user,
-            """Usage: %s add-user username [options]
+            """Usage: %s add-user <username> [options]
 (Specify the --help global option for a list of other help options)
 
 Options:
diff --git a/tests/test_cli/test_add_volume.py b/tests/test_cli/test_add_volume.py
index 08c81ce..4a0b889 100644
--- a/tests/test_cli/test_add_volume.py
+++ b/tests/test_cli/test_add_volume.py
@@ -16,7 +16,7 @@ class TestAddVolume(utils.CliTestCase):
     maxDiff = None
 
     def setUp(self):
-        self.error_format = """Usage: %s add-volume volume-name
+        self.error_format = """Usage: %s add-volume <volume-name>
 (Specify the --help global option for a list of other help options)
 
 %s: error: {message}
@@ -66,7 +66,7 @@ class TestAddVolume(utils.CliTestCase):
     def test_handle_add_volume_help(self):
         self.assert_help(
             handle_add_volume,
-            """Usage: %s add-volume volume-name
+            """Usage: %s add-volume <volume-name>
 (Specify the --help global option for a list of other help options)
 
 Options:
diff --git a/tests/test_cli/test_block_group_pkg.py b/tests/test_cli/test_block_group_pkg.py
index a57233c..da56e13 100644
--- a/tests/test_cli/test_block_group_pkg.py
+++ b/tests/test_cli/test_block_group_pkg.py
@@ -19,7 +19,7 @@ class TestBlockGroupPkg(utils.CliTestCase):
         self.options = mock.MagicMock()
         self.activate_session = mock.patch('koji_cli.commands.activate_session').start()
 
-        self.error_format = """Usage: %s block-group-pkg [options] <tag> <group> <pkg> [<pkg>...]
+        self.error_format = """Usage: %s block-group-pkg [options] <tag> <group> <pkg> [<pkg> ...]
 Note that blocking is propagated through the inheritance chain, so it is not exactly the same as package removal.
 (Specify the --help global option for a list of other help options)
 
@@ -55,7 +55,7 @@ Note that blocking is propagated through the inheritance chain, so it is not exa
     def test_handle_block_group_pkg_help(self):
         self.assert_help(
             handle_block_group_pkg,
-            """Usage: %s block-group-pkg [options] <tag> <group> <pkg> [<pkg>...]
+            """Usage: %s block-group-pkg [options] <tag> <group> <pkg> [<pkg> ...]
 Note that blocking is propagated through the inheritance chain, so it is not exactly the same as package removal.
 (Specify the --help global option for a list of other help options)
 
diff --git a/tests/test_cli/test_block_pkg.py b/tests/test_cli/test_block_pkg.py
index 1af6ff9..a7bf3e0 100644
--- a/tests/test_cli/test_block_pkg.py
+++ b/tests/test_cli/test_block_pkg.py
@@ -168,7 +168,7 @@ class TestBlockPkg(unittest.TestCase):
         actual_stdout = stdout.getvalue()
         actual_stderr = stderr.getvalue()
         expected_stdout = ''
-        expected_stderr = """Usage: %s block-pkg [options] tag package [package2 ...]
+        expected_stderr = """Usage: %s block-pkg [options] <tag> <package> [<package> ...]
 (Specify the --help global option for a list of other help options)
 
 %s: error: Please specify a tag and at least one package
diff --git a/tests/test_cli/test_build.py b/tests/test_cli/test_build.py
index 86392f7..6384eed 100644
--- a/tests/test_cli/test_build.py
+++ b/tests/test_cli/test_build.py
@@ -147,7 +147,7 @@ Task info: weburl/taskinfo?taskID=1
         actual_stdout = stdout.getvalue()
         actual_stderr = stderr.getvalue()
         expected_stdout = ''
-        expected_stderr = """Usage: %s build [options] target <srpm path or scm url>
+        expected_stderr = """Usage: %s build [options] <target> <srpm path or scm url>
 (Specify the --help global option for a list of other help options)
 
 %s: error: Exactly two arguments (a build target and a SCM URL or srpm file) are required
@@ -192,7 +192,7 @@ Task info: weburl/taskinfo?taskID=1
             handle_build(self.options, self.session, args)
         actual_stdout = stdout.getvalue()
         actual_stderr = stderr.getvalue()
-        expected_stdout = """Usage: %s build [options] target <srpm path or scm url>
+        expected_stdout = """Usage: %s build [options] <target> <srpm path or scm url>
 (Specify the --help global option for a list of other help options)
 
 Options:
@@ -255,7 +255,7 @@ Options:
         actual_stdout = stdout.getvalue()
         actual_stderr = stderr.getvalue()
         expected_stdout = ''
-        expected_stderr = """Usage: %s build [options] target <srpm path or scm url>
+        expected_stderr = """Usage: %s build [options] <target> <srpm path or scm url>
 (Specify the --help global option for a list of other help options)
 
 %s: error: --arch_override is only allowed for --scratch builds
@@ -350,7 +350,7 @@ Task info: weburl/taskinfo?taskID=1
         with self.assertRaises(SystemExit) as cm:
             handle_build(self.options, self.session, args)
         actual = stderr.getvalue()
-        expected = """Usage: %s build [options] target <srpm path or scm url>
+        expected = """Usage: %s build [options] <target> <srpm path or scm url>
 (Specify the --help global option for a list of other help options)
 
 %s: error: Unknown build target: target
@@ -401,7 +401,7 @@ Task info: weburl/taskinfo?taskID=1
         with self.assertRaises(SystemExit) as cm:
             handle_build(self.options, self.session, args)
         actual = stderr.getvalue()
-        expected = """Usage: %s build [options] target <srpm path or scm url>
+        expected = """Usage: %s build [options] <target> <srpm path or scm url>
 (Specify the --help global option for a list of other help options)
 
 %s: error: Unknown destination tag: dest_tag_name
@@ -452,7 +452,7 @@ Task info: weburl/taskinfo?taskID=1
         with self.assertRaises(SystemExit) as cm:
             handle_build(self.options, self.session, args)
         actual = stderr.getvalue()
-        expected = """Usage: %s build [options] target <srpm path or scm url>
+        expected = """Usage: %s build [options] <target> <srpm path or scm url>
 (Specify the --help global option for a list of other help options)
 
 %s: error: Destination tag dest_tag_name is locked
diff --git a/tests/test_cli/test_call.py b/tests/test_cli/test_call.py
index c45901d..8ffcf89 100644
--- a/tests/test_cli/test_call.py
+++ b/tests/test_cli/test_call.py
@@ -17,7 +17,7 @@ class TestCall(utils.CliTestCase):
     maxDiff = None
 
     def setUp(self):
-        self.error_format = """Usage: %s call [options] name [arg...]
+        self.error_format = """Usage: %s call [options] <name> [<arg> ...]
 (Specify the --help global option for a list of other help options)
 
 %s: error: {message}
@@ -136,7 +136,7 @@ class TestCall(utils.CliTestCase):
         """Test handle_call help message"""
         self.assert_help(
             handle_call,
-            """Usage: %s call [options] name [arg...]
+            """Usage: %s call [options] <name> [<arg> ...]
 (Specify the --help global option for a list of other help options)
 
 Options:
diff --git a/tests/test_cli/test_chain_build.py b/tests/test_cli/test_chain_build.py
index da7a62a..b8ab16d 100644
--- a/tests/test_cli/test_chain_build.py
+++ b/tests/test_cli/test_chain_build.py
@@ -105,7 +105,7 @@ Task info: weburl/taskinfo?taskID=1
         actual_stdout = stdout.getvalue()
         actual_stderr = stderr.getvalue()
         expected_stdout = ''
-        expected_stderr = """Usage: %s chain-build [options] target URL [URL2 [:] URL3 [:] URL4 ...]
+        expected_stderr = """Usage: %s chain-build [options] <target> <URL> [<URL> [:] <URL> [:] <URL> ...]
 (Specify the --help global option for a list of other help options)
 
 %s: error: At least two arguments (a build target and a SCM URL) are required
@@ -147,7 +147,7 @@ Task info: weburl/taskinfo?taskID=1
             handle_chain_build(self.options, self.session, args)
         actual_stdout = stdout.getvalue()
         actual_stderr = stderr.getvalue()
-        expected_stdout = """Usage: %s chain-build [options] target URL [URL2 [:] URL3 [:] URL4 ...]
+        expected_stdout = """Usage: %s chain-build [options] <target> <URL> [<URL> [:] <URL> [:] <URL> ...]
 (Specify the --help global option for a list of other help options)
 
 Options:
@@ -206,7 +206,7 @@ Options:
         with self.assertRaises(SystemExit) as cm:
             handle_chain_build(self.options, self.session, args)
         actual = stderr.getvalue()
-        expected = """Usage: %s chain-build [options] target URL [URL2 [:] URL3 [:] URL4 ...]
+        expected = """Usage: %s chain-build [options] <target> <URL> [<URL> [:] <URL> [:] <URL> ...]
 (Specify the --help global option for a list of other help options)
 
 %s: error: Unknown build target: target
@@ -268,7 +268,7 @@ Options:
         with self.assertRaises(SystemExit) as cm:
             handle_chain_build(self.options, self.session, args)
         actual = stderr.getvalue()
-        expected = """Usage: %s chain-build [options] target URL [URL2 [:] URL3 [:] URL4 ...]
+        expected = """Usage: %s chain-build [options] <target> <URL> [<URL> [:] <URL> [:] <URL> ...]
 (Specify the --help global option for a list of other help options)
 
 %s: error: Destination tag dest_tag is locked
@@ -461,7 +461,7 @@ Target target is not usable for a chain-build
             with self.assertRaises(SystemExit) as cm:
                 handle_chain_build(self.options, self.session, args)
             actual = stderr.getvalue()
-            expected = """Usage: %s chain-build [options] target URL [URL2 [:] URL3 [:] URL4 ...]
+            expected = """Usage: %s chain-build [options] <target> <URL> [<URL> [:] <URL> [:] <URL> ...]
 (Specify the --help global option for a list of other help options)
 
 %s: error: You must specify at least one dependency between builds with : (colon)
diff --git a/tests/test_cli/test_disable_host.py b/tests/test_cli/test_disable_host.py
index dbb23ff..5f44aba 100644
--- a/tests/test_cli/test_disable_host.py
+++ b/tests/test_cli/test_disable_host.py
@@ -17,7 +17,7 @@ class TestDisableHost(utils.CliTestCase):
     maxDiff = None
 
     def setUp(self):
-        self.error_format = """Usage: %s disable-host [options] hostname ...
+        self.error_format = """Usage: %s disable-host [options] <hostname> [<hostname> ...]
 (Specify the --help global option for a list of other help options)
 
 %s: error: {message}
@@ -123,7 +123,7 @@ class TestDisableHost(utils.CliTestCase):
         """Test %s help message""" % handle_disable_host.__name__
         self.assert_help(
             handle_disable_host,
-            """Usage: %s disable-host [options] hostname ...
+            """Usage: %s disable-host [options] <hostname> [<hostname> ...]
 (Specify the --help global option for a list of other help options)
 
 Options:
diff --git a/tests/test_cli/test_disable_user.py b/tests/test_cli/test_disable_user.py
index e8598a4..ef1f83c 100644
--- a/tests/test_cli/test_disable_user.py
+++ b/tests/test_cli/test_disable_user.py
@@ -16,7 +16,7 @@ class TestDisableUser(utils.CliTestCase):
     maxDiff = None
 
     def setUp(self):
-        self.error_format = """Usage: %s disable-user username
+        self.error_format = """Usage: %s disable-user <username>
 (Specify the --help global option for a list of other help options)
 
 %s: error: {message}
@@ -63,7 +63,7 @@ class TestDisableUser(utils.CliTestCase):
     def test_handle_disable_user_help(self):
         self.assert_help(
             handle_disable_user,
-            """Usage: %s disable-user username
+            """Usage: %s disable-user <username>
 (Specify the --help global option for a list of other help options)
 
 Options:
diff --git a/tests/test_cli/test_dist_repo.py b/tests/test_cli/test_dist_repo.py
index 6d38fbd..f625529 100644
--- a/tests/test_cli/test_dist_repo.py
+++ b/tests/test_cli/test_dist_repo.py
@@ -44,8 +44,8 @@ class TestDistRepo(utils.CliTestCase):
         self.session.getTag.return_value = copy.deepcopy(self.TAG)
         self.session.distRepo.return_value = self.task_id
 
-        self.error_format = """Usage: %s dist-repo [options] tag keyID [keyID...]
-(Specify the --help option for a list of other options)
+        self.error_format = """Usage: %s dist-repo [options] <tag> <key_id> [<key_id> ...]
+(Specify the --help global option for a list of other help options)
 
 %s: error: {message}
 """ % (self.progname, self.progname)
@@ -248,8 +248,8 @@ class TestDistRepo(utils.CliTestCase):
         """Test handle_dist_repo help message"""
         self.assert_help(
             handle_dist_repo,
-            """Usage: %s dist-repo [options] tag keyID [keyID...]
-(Specify the --help option for a list of other options)
+            """Usage: %s dist-repo [options] <tag> <key_id> [<key_id> ...]
+(Specify the --help global option for a list of other help options)
 
 Options:
   -h, --help            show this help message and exit
diff --git a/tests/test_cli/test_edit_host.py b/tests/test_cli/test_edit_host.py
index 4b255d4..6b5641f 100644
--- a/tests/test_cli/test_edit_host.py
+++ b/tests/test_cli/test_edit_host.py
@@ -162,7 +162,7 @@ class TestEditHost(unittest.TestCase):
         actual_stdout = stdout.getvalue()
         actual_stderr = stderr.getvalue()
         expected_stdout = ''
-        expected_stderr = """Usage: %s edit-host hostname ... [options]
+        expected_stderr = """Usage: %s edit-host <hostname> [<hostname> ...] [options]
 (Specify the --help global option for a list of other help options)
 
 %s: error: Please specify a hostname
diff --git a/tests/test_cli/test_edit_tag.py b/tests/test_cli/test_edit_tag.py
index 5244a63..b08404b 100644
--- a/tests/test_cli/test_edit_tag.py
+++ b/tests/test_cli/test_edit_tag.py
@@ -111,7 +111,7 @@ class TestEditTag(unittest.TestCase):
             handle_edit_tag(options, session, args)
         actual_stdout = stdout.getvalue()
         actual_stderr = stderr.getvalue()
-        expected_stdout = """Usage: %s edit-tag [options] name
+        expected_stdout = """Usage: %s edit-tag [options] <name>
 (Specify the --help global option for a list of other help options)
 
 Options:
@@ -162,7 +162,7 @@ Options:
         actual_stdout = stdout.getvalue()
         actual_stderr = stderr.getvalue()
         expected_stdout = ''
-        expected_stderr = """Usage: %(progname)s edit-tag [options] name
+        expected_stderr = """Usage: %(progname)s edit-tag [options] <name>
 (Specify the --help global option for a list of other help options)
 
 %(progname)s: error: Please specify a name for the tag
diff --git a/tests/test_cli/test_edit_user.py b/tests/test_cli/test_edit_user.py
index 7f56116..12e43af 100644
--- a/tests/test_cli/test_edit_user.py
+++ b/tests/test_cli/test_edit_user.py
@@ -70,7 +70,7 @@ class TestEditUser(unittest.TestCase):
             handle_edit_user(options, session, args)
         actual_stdout = stdout.getvalue()
         actual_stderr = stderr.getvalue()
-        expected_stdout = """Usage: %s edit-user name [options]
+        expected_stdout = """Usage: %s edit-user <username> [options]
 (Specify the --help global option for a list of other help options)
 
 Options:
@@ -106,7 +106,7 @@ Options:
         actual_stdout = stdout.getvalue()
         actual_stderr = stderr.getvalue()
         expected_stdout = ''
-        expected_stderr = """Usage: %(progname)s edit-user name [options]
+        expected_stderr = """Usage: %(progname)s edit-user <username> [options]
 (Specify the --help global option for a list of other help options)
 
 %(progname)s: error: You must specify the username of the user to edit
diff --git a/tests/test_cli/test_enable_host.py b/tests/test_cli/test_enable_host.py
index c274bee..20fc5ee 100644
--- a/tests/test_cli/test_enable_host.py
+++ b/tests/test_cli/test_enable_host.py
@@ -17,7 +17,7 @@ class TestEnableHost(utils.CliTestCase):
     maxDiff = None
 
     def setUp(self):
-        self.error_format = """Usage: %s enable-host [options] hostname ...
+        self.error_format = """Usage: %s enable-host [options] <hostname> [<hostname> ...]
 (Specify the --help global option for a list of other help options)
 
 %s: error: {message}
@@ -122,7 +122,7 @@ class TestEnableHost(utils.CliTestCase):
         """Test %s help message""" % handle_enable_host.__name__
         self.assert_help(
             handle_enable_host,
-            """Usage: %s enable-host [options] hostname ...
+            """Usage: %s enable-host [options] <hostname> [<hostname> ...]
 (Specify the --help global option for a list of other help options)
 
 Options:
diff --git a/tests/test_cli/test_enable_user.py b/tests/test_cli/test_enable_user.py
index 2861ce1..8145c97 100644
--- a/tests/test_cli/test_enable_user.py
+++ b/tests/test_cli/test_enable_user.py
@@ -16,7 +16,7 @@ class TestEnableUser(utils.CliTestCase):
     maxDiff = None
 
     def setUp(self):
-        self.error_format = """Usage: %s enable-user username
+        self.error_format = """Usage: %s enable-user <username>
 (Specify the --help global option for a list of other help options)
 
 %s: error: {message}
@@ -63,7 +63,7 @@ class TestEnableUser(utils.CliTestCase):
     def test_handle_enable_user_help(self):
         self.assert_help(
             handle_enable_user,
-            """Usage: %s enable-user username
+            """Usage: %s enable-user <username>
 (Specify the --help global option for a list of other help options)
 
 Options:
diff --git a/tests/test_cli/test_hello.py b/tests/test_cli/test_hello.py
index a5638a1..e345c2a 100644
--- a/tests/test_cli/test_hello.py
+++ b/tests/test_cli/test_hello.py
@@ -59,6 +59,7 @@ class TestHello(utils.CliTestCase):
         print_unicode_mock.return_value = "Hello"
 
         expect = """Usage: %s moshimoshi [options]
+(Specify the --help global option for a list of other help options)
 
 %s: error: This command takes no arguments
 """ % (self.progname, self.progname)
@@ -102,6 +103,7 @@ class TestHello(utils.CliTestCase):
         self.assert_help(
             handle_moshimoshi,
             """Usage: %s moshimoshi [options]
+(Specify the --help global option for a list of other help options)
 
 Options:
   -h, --help  show this help message and exit
diff --git a/tests/test_cli/test_image_build.py b/tests/test_cli/test_image_build.py
index f9211ca..e1c3adb 100644
--- a/tests/test_cli/test_image_build.py
+++ b/tests/test_cli/test_image_build.py
@@ -227,8 +227,8 @@ class TestImageBuild(utils.CliTestCase):
         self.session = mock.MagicMock()
         self.configparser = mock.patch('six.moves.configparser.ConfigParser').start()
 
-        self.error_format = """Usage: %s image-build [options] <name> <version> <target> <install-tree-url> <arch> [<arch>...]
-       %s image-build --config FILE
+        self.error_format = """Usage: %s image-build [options] <name> <version> <target> <install-tree-url> <arch> [<arch> ...]
+       %s image-build --config <FILE>
 
 (Specify the --help global option for a list of other help options)
 
@@ -328,8 +328,8 @@ class TestImageBuild(utils.CliTestCase):
         """Test handle_image_build help message"""
         self.assert_help(
             handle_image_build,
-            """Usage: %s image-build [options] <name> <version> <target> <install-tree-url> <arch> [<arch>...]
-       %s image-build --config FILE
+            """Usage: %s image-build [options] <name> <version> <target> <install-tree-url> <arch> [<arch> ...]
+       %s image-build --config <FILE>
 
 (Specify the --help global option for a list of other help options)
 
diff --git a/tests/test_cli/test_image_build_indirection.py b/tests/test_cli/test_image_build_indirection.py
index 429b3b0..88dda02 100644
--- a/tests/test_cli/test_image_build_indirection.py
+++ b/tests/test_cli/test_image_build_indirection.py
@@ -200,7 +200,7 @@ class TestImageBuildIndirection(utils.CliTestCase):
         self.session = mock.MagicMock()
 
         self.error_format = """Usage: %s image-build-indirection [base_image] [utility_image] [indirection_build_template]
-       %s image-build --config FILE
+       %s image-build --config <FILE>
 
 (Specify the --help global option for a list of other help options)
 
@@ -220,7 +220,7 @@ class TestImageBuildIndirection(utils.CliTestCase):
         self.assert_help(
             handle_image_build_indirection,
             """Usage: %s image-build-indirection [base_image] [utility_image] [indirection_build_template]
-       %s image-build --config FILE
+       %s image-build --config <FILE>
 
 (Specify the --help global option for a list of other help options)
 
diff --git a/tests/test_cli/test_import.py b/tests/test_cli/test_import.py
index d198417..623567f 100644
--- a/tests/test_cli/test_import.py
+++ b/tests/test_cli/test_import.py
@@ -82,7 +82,7 @@ class TestImport(utils.CliTestCase):
             'CANCELED': 4,
         }
 
-        self.error_format = """Usage: %s import [options] package [package...]
+        self.error_format = """Usage: %s import [options] <package> [<package> ...]
 (Specify the --help global option for a list of other help options)
 
 %s: error: {message}
@@ -681,7 +681,7 @@ class TestImport(utils.CliTestCase):
         """Test handle_import function help message"""
         self.assert_help(
             handle_import,
-            """Usage: %s import [options] package [package...]
+            """Usage: %s import [options] <package> [<package> ...]
 (Specify the --help global option for a list of other help options)
 
 Options:
diff --git a/tests/test_cli/test_import_cg.py b/tests/test_cli/test_import_cg.py
index 72eae49..1875a51 100644
--- a/tests/test_cli/test_import_cg.py
+++ b/tests/test_cli/test_import_cg.py
@@ -27,7 +27,7 @@ class TestImportCG(utils.CliTestCase):
     def setUp(self):
         self.custom_os_path_exists = {}
         self.os_path_exists = os.path.exists
-        self.error_format = """Usage: %s import-cg [options] metadata_file files_dir
+        self.error_format = """Usage: %s import-cg [options] <metadata_file> <files_dir>
 (Specify the --help global option for a list of other help options)
 
 %s: error: {message}
@@ -209,7 +209,7 @@ class TestImportCG(utils.CliTestCase):
         """Test handle_import_cg help message"""
         self.assert_help(
             handle_import_cg,
-            """Usage: %s import-cg [options] metadata_file files_dir
+            """Usage: %s import-cg [options] <metadata_file> <files_dir>
 (Specify the --help global option for a list of other help options)
 
 Options:
diff --git a/tests/test_cli/test_import_sig.py b/tests/test_cli/test_import_sig.py
index 2321a41..828ef9b 100644
--- a/tests/test_cli/test_import_sig.py
+++ b/tests/test_cli/test_import_sig.py
@@ -1,5 +1,4 @@
 from __future__ import absolute_import
-import base64
 import copy
 import hashlib
 import mock
@@ -68,7 +67,7 @@ class TestImportSIG(utils.CliTestCase):
             }
         ]
 
-        self.error_format = """Usage: %s import-sig [options] package [package...]
+        self.error_format = """Usage: %s import-sig [options] <package> [<package> ...]
 (Specify the --help global option for a list of other help options)
 
 %s: error: {message}
@@ -274,7 +273,7 @@ class TestImportSIG(utils.CliTestCase):
         """Test handle_import_sig help message"""
         self.assert_help(
             handle_import_sig,
-            """Usage: %s import-sig [options] package [package...]
+            """Usage: %s import-sig [options] <package> [<package> ...]
 (Specify the --help global option for a list of other help options)
 
 Options:
diff --git a/tests/test_cli/test_list_groups.py b/tests/test_cli/test_list_groups.py
index 1a5c85b..57cc9f0 100644
--- a/tests/test_cli/test_list_groups.py
+++ b/tests/test_cli/test_list_groups.py
@@ -23,7 +23,7 @@ class TestListGroups(utils.CliTestCase):
         self.activate_session = mock.patch('koji_cli.commands.activate_session').start()
         self.event_from_opts = mock.patch('koji.util.eventFromOpts').start()
 
-        self.error_format = """Usage: %s list-groups [options] <tag> [group]
+        self.error_format = """Usage: %s list-groups [options] <tag> [<group>]
 (Specify the --help global option for a list of other help options)
 
 %s: error: {message}
@@ -184,7 +184,7 @@ class TestListGroups(utils.CliTestCase):
     def test_anon_handle_list_groups_help(self):
         self.assert_help(
             anon_handle_list_groups,
-            """Usage: %s list-groups [options] <tag> [group]
+            """Usage: %s list-groups [options] <tag> [<group>]
 (Specify the --help global option for a list of other help options)
 
 Options:
diff --git a/tests/test_cli/test_list_tagged.py b/tests/test_cli/test_list_tagged.py
index 2d37a2d..a8f775d 100644
--- a/tests/test_cli/test_list_tagged.py
+++ b/tests/test_cli/test_list_tagged.py
@@ -16,7 +16,7 @@ class TestCliListTagged(utils.CliTestCase):
         self.original_timezone = os.environ.get('TZ')
         os.environ['TZ'] = 'US/Eastern'
         time.tzset()
-        self.error_format = """Usage: %s list-tagged [options] tag [package]
+        self.error_format = """Usage: %s list-tagged [options] <tag> [<package>]
 (Specify the --help global option for a list of other help options)
 
 %s: error: {message}
@@ -232,7 +232,7 @@ class TestCliListTagged(utils.CliTestCase):
     def test_handle_list_tagged_help(self):
         self.assert_help(
             anon_handle_list_tagged,
-            """Usage: %s list-tagged [options] tag [package]
+            """Usage: %s list-tagged [options] <tag> [<package>]
 (Specify the --help global option for a list of other help options)
 
 Options:
diff --git a/tests/test_cli/test_maven_build.py b/tests/test_cli/test_maven_build.py
index a3d5bf9..fac3cb5 100644
--- a/tests/test_cli/test_maven_build.py
+++ b/tests/test_cli/test_maven_build.py
@@ -108,8 +108,8 @@ Task info: weburl/taskinfo?taskID=1
         actual_stdout = stdout.getvalue()
         actual_stderr = stderr.getvalue()
         expected_stdout = ''
-        expected_stderr = """Usage: %s maven-build [options] target URL
-       %s maven-build --ini=CONFIG... [options] target
+        expected_stderr = """Usage: %s maven-build [options] <target> <URL>
+       %s maven-build --ini=CONFIG... [options] <target>
 (Specify the --help global option for a list of other help options)
 
 %s: error: Exactly two arguments (a build target and a SCM URL) are required
@@ -151,8 +151,8 @@ Task info: weburl/taskinfo?taskID=1
         actual_stdout = stdout.getvalue()
         actual_stderr = stderr.getvalue()
         expected_stdout = ''
-        expected_stderr = """Usage: %s maven-build [options] target URL
-       %s maven-build --ini=CONFIG... [options] target
+        expected_stderr = """Usage: %s maven-build [options] <target> <URL>
+       %s maven-build --ini=CONFIG... [options] <target>
 (Specify the --help global option for a list of other help options)
 
 %s: error: Exactly one argument (a build target) is required
@@ -193,8 +193,8 @@ Task info: weburl/taskinfo?taskID=1
             handle_maven_build(self.options, self.session, args)
         actual_stdout = stdout.getvalue()
         actual_stderr = stderr.getvalue()
-        expected_stdout = """Usage: %s maven-build [options] target URL
-       %s maven-build --ini=CONFIG... [options] target
+        expected_stdout = """Usage: %s maven-build [options] <target> <URL>
+       %s maven-build --ini=CONFIG... [options] <target>
 (Specify the --help global option for a list of other help options)
 
 Options:
@@ -268,8 +268,8 @@ Options:
         with self.assertRaises(SystemExit) as cm:
             handle_maven_build(self.options, self.session, args)
         actual = stderr.getvalue()
-        expected = """Usage: %s maven-build [options] target URL
-       %s maven-build --ini=CONFIG... [options] target
+        expected = """Usage: %s maven-build [options] <target> <URL>
+       %s maven-build --ini=CONFIG... [options] <target>
 (Specify the --help global option for a list of other help options)
 
 %s: error: Unknown build target: target
@@ -316,8 +316,8 @@ Options:
         with self.assertRaises(SystemExit) as cm:
             handle_maven_build(self.options, self.session, args)
         actual = stderr.getvalue()
-        expected = """Usage: %s maven-build [options] target URL
-       %s maven-build --ini=CONFIG... [options] target
+        expected = """Usage: %s maven-build [options] <target> <URL>
+       %s maven-build --ini=CONFIG... [options] <target>
 (Specify the --help global option for a list of other help options)
 
 %s: error: Unknown destination tag: dest_tag
@@ -364,8 +364,8 @@ Options:
         with self.assertRaises(SystemExit) as cm:
             handle_maven_build(self.options, self.session, args)
         actual = stderr.getvalue()
-        expected = """Usage: %s maven-build [options] target URL
-       %s maven-build --ini=CONFIG... [options] target
+        expected = """Usage: %s maven-build [options] <target> <URL>
+       %s maven-build --ini=CONFIG... [options] <target>
 (Specify the --help global option for a list of other help options)
 
 %s: error: Destination tag dest_tag is locked
@@ -476,8 +476,8 @@ Task info: weburl/taskinfo?taskID=1
         with self.assertRaises(SystemExit) as cm:
             handle_maven_build(self.options, self.session, args)
         actual = stderr.getvalue()
-        expected = """Usage: %s maven-build [options] target URL
-       %s maven-build --ini=CONFIG... [options] target
+        expected = """Usage: %s maven-build [options] <target> <URL>
+       %s maven-build --ini=CONFIG... [options] <target>
 (Specify the --help global option for a list of other help options)
 
 %s: error: Section section does not contain a maven-build config
@@ -507,8 +507,8 @@ Task info: weburl/taskinfo?taskID=1
         with self.assertRaises(SystemExit) as cm:
             handle_maven_build(self.options, self.session, args)
         actual = stderr.getvalue()
-        expected = """Usage: %s maven-build [options] target URL
-       %s maven-build --ini=CONFIG... [options] target
+        expected = """Usage: %s maven-build [options] <target> <URL>
+       %s maven-build --ini=CONFIG... [options] <target>
 (Specify the --help global option for a list of other help options)
 
 %s: error: errormsg
@@ -557,8 +557,8 @@ Task info: weburl/taskinfo?taskID=1
         with self.assertRaises(SystemExit) as cm:
             handle_maven_build(self.options, self.session, args)
         actual = stderr.getvalue()
-        expected = """Usage: %s maven-build [options] target URL
-       %s maven-build --ini=CONFIG... [options] target
+        expected = """Usage: %s maven-build [options] <target> <URL>
+       %s maven-build --ini=CONFIG... [options] <target>
 (Specify the --help global option for a list of other help options)
 
 %s: error: Invalid SCM URL: badscm
diff --git a/tests/test_cli/test_maven_chain.py b/tests/test_cli/test_maven_chain.py
index bb4380c..91429e2 100644
--- a/tests/test_cli/test_maven_chain.py
+++ b/tests/test_cli/test_maven_chain.py
@@ -20,7 +20,7 @@ class TestMavenChain(utils.CliTestCase):
         self.config = 'config'
         self.task_id = 101
 
-        self.error_format = """Usage: %s maven-chain [options] target config...
+        self.error_format = """Usage: %s maven-chain [options] <target> <config> [<config> ...]
 (Specify the --help global option for a list of other help options)
 
 %s: error: {message}
@@ -175,7 +175,7 @@ class TestMavenChain(utils.CliTestCase):
         """Test handle_maven_chain help message full output"""
         self.assert_help(
             handle_maven_chain,
-            """Usage: %s maven-chain [options] target config...
+            """Usage: %s maven-chain [options] <target> <config> [<config> ...]
 (Specify the --help global option for a list of other help options)
 
 Options:
diff --git a/tests/test_cli/test_move_build.py b/tests/test_cli/test_move_build.py
index da184be..19b5fed 100644
--- a/tests/test_cli/test_move_build.py
+++ b/tests/test_cli/test_move_build.py
@@ -19,7 +19,7 @@ class TestMoveBuild(utils.CliTestCase):
         self.session = mock.MagicMock()
         self.options = mock.MagicMock()
 
-        self.error_format = """Usage: %s move-build [options] <tag1> <tag2> <pkg> [<pkg>...]
+        self.error_format = """Usage: %s move-build [options] <tag1> <tag2> <pkg> [<pkg> ...]
 (Specify the --help global option for a list of other help options)
 
 %s: error: {message}
@@ -147,7 +147,7 @@ class TestMoveBuild(utils.CliTestCase):
         """Test handle_move_build help message"""
         self.assert_help(
             handle_move_build,
-            """Usage: %s move-build [options] <tag1> <tag2> <pkg> [<pkg>...]
+            """Usage: %s move-build [options] <tag1> <tag2> <pkg> [<pkg> ...]
 (Specify the --help global option for a list of other help options)
 
 Options:
diff --git a/tests/test_cli/test_remove_channel.py b/tests/test_cli/test_remove_channel.py
index c1381ac..61fe9d5 100644
--- a/tests/test_cli/test_remove_channel.py
+++ b/tests/test_cli/test_remove_channel.py
@@ -111,7 +111,7 @@ class TestRemoveChannel(unittest.TestCase):
         actual_stdout = stdout.getvalue()
         actual_stderr = stderr.getvalue()
         expected_stdout = ''
-        expected_stderr = """Usage: %s remove-channel [options] channel
+        expected_stderr = """Usage: %s remove-channel [options] <channel>
 (Specify the --help global option for a list of other help options)
 
 %s: error: Incorrect number of arguments
diff --git a/tests/test_cli/test_remove_host_from_channel.py b/tests/test_cli/test_remove_host_from_channel.py
index dc5ae0d..35c9cba 100644
--- a/tests/test_cli/test_remove_host_from_channel.py
+++ b/tests/test_cli/test_remove_host_from_channel.py
@@ -124,7 +124,7 @@ class TestRemoveHostFromChannel(unittest.TestCase):
         actual_stdout = stdout.getvalue()
         actual_stderr = stderr.getvalue()
         expected_stdout = ''
-        expected_stderr = """Usage: %s remove-host-from-channel [options] hostname channel
+        expected_stderr = """Usage: %s remove-host-from-channel [options] <hostname> <channel>
 (Specify the --help global option for a list of other help options)
 
 %s: error: Please specify a hostname and a channel
diff --git a/tests/test_cli/test_remove_pkg.py b/tests/test_cli/test_remove_pkg.py
index 455f3c0..bf8e366 100644
--- a/tests/test_cli/test_remove_pkg.py
+++ b/tests/test_cli/test_remove_pkg.py
@@ -209,7 +209,7 @@ class TestRemovePkg(unittest.TestCase):
         actual_stdout = stdout.getvalue()
         actual_stderr = stderr.getvalue()
         expected_stdout = ''
-        expected_stderr = """Usage: %s remove-pkg [options] tag package [package2 ...]
+        expected_stderr = """Usage: %s remove-pkg [options] <tag> <package> [<package> ...]
 (Specify the --help global option for a list of other help options)
 
 %s: error: Please specify a tag and at least one package
diff --git a/tests/test_cli/test_rename_channel.py b/tests/test_cli/test_rename_channel.py
index 404a4ef..9d0835b 100644
--- a/tests/test_cli/test_rename_channel.py
+++ b/tests/test_cli/test_rename_channel.py
@@ -87,7 +87,7 @@ class TestRenameChannel(unittest.TestCase):
         actual_stdout = stdout.getvalue()
         actual_stderr = stderr.getvalue()
         expected_stdout = ''
-        expected_stderr = """Usage: %s rename-channel [options] old-name new-name
+        expected_stderr = """Usage: %s rename-channel [options] <old-name> <new-name>
 (Specify the --help global option for a list of other help options)
 
 %s: error: Incorrect number of arguments
diff --git a/tests/test_cli/test_resubmit.py b/tests/test_cli/test_resubmit.py
index f062dd6..4dfae37 100644
--- a/tests/test_cli/test_resubmit.py
+++ b/tests/test_cli/test_resubmit.py
@@ -31,7 +31,7 @@ Log Files:
   /mnt/koji/work/tasks/2/2/mergerepos.log
 """
 
-        self.error_format = """Usage: %s resubmit [options] taskID
+        self.error_format = """Usage: %s resubmit [options] <task_id>
 (Specify the --help global option for a list of other help options)
 
 %s: error: {message}
@@ -123,7 +123,7 @@ Log Files:
         """Test handle_resubmit help message output"""
         self.assert_help(
             handle_resubmit,
-            """Usage: %s resubmit [options] taskID
+            """Usage: %s resubmit [options] <task_id>
 (Specify the --help global option for a list of other help options)
 
 Options:
diff --git a/tests/test_cli/test_search.py b/tests/test_cli/test_search.py
index 344c923..1d4c6c3 100644
--- a/tests/test_cli/test_search.py
+++ b/tests/test_cli/test_search.py
@@ -16,7 +16,7 @@ class TestSearch(utils.CliTestCase):
     maxDiff = None
 
     def setUp(self):
-        self.error_format = """Usage: %s search [options] search_type pattern
+        self.error_format = """Usage: %s search [options] <search_type> <pattern>
 Available search types: package, build, tag, target, user, host, rpm, maven, win
 (Specify the --help global option for a list of other help options)
 
@@ -80,7 +80,7 @@ Available search types: package, build, tag, target, user, host, rpm, maven, win
     def test_anon_handle_search_help(self):
         self.assert_help(
             anon_handle_search,
-            """Usage: %s search [options] search_type pattern
+            """Usage: %s search [options] <search_type> <pattern>
 Available search types: package, build, tag, target, user, host, rpm, maven, win
 (Specify the --help global option for a list of other help options)
 
diff --git a/tests/test_cli/test_set_build_volume.py b/tests/test_cli/test_set_build_volume.py
index 23596f0..85c1850 100644
--- a/tests/test_cli/test_set_build_volume.py
+++ b/tests/test_cli/test_set_build_volume.py
@@ -16,7 +16,7 @@ class TestSetBuildVolume(utils.CliTestCase):
     maxDiff = None
 
     def setUp(self):
-        self.error_format = """Usage: %s set-build-volume volume n-v-r [n-v-r ...]
+        self.error_format = """Usage: %s set-build-volume <volume> <n-v-r> [<n-v-r> ...]
 (Specify the --help global option for a list of other help options)
 
 %s: error: {message}
@@ -104,7 +104,7 @@ class TestSetBuildVolume(utils.CliTestCase):
     def test_handle_set_build_volume_help(self):
         self.assert_help(
             handle_set_build_volume,
-            """Usage: %s set-build-volume volume n-v-r [n-v-r ...]
+            """Usage: %s set-build-volume <volume> <n-v-r> [<n-v-r> ...]
 (Specify the --help global option for a list of other help options)
 
 Options:
diff --git a/tests/test_cli/test_set_pkg_arches.py b/tests/test_cli/test_set_pkg_arches.py
index 0211e44..6501e79 100644
--- a/tests/test_cli/test_set_pkg_arches.py
+++ b/tests/test_cli/test_set_pkg_arches.py
@@ -16,7 +16,7 @@ class TestSetPkgArches(utils.CliTestCase):
     maxDiff = None
 
     def setUp(self):
-        self.error_format = """Usage: %s set-pkg-arches [options] arches tag package [package2 ...]
+        self.error_format = """Usage: %s set-pkg-arches [options] <arches> <tag> <package> [<package> ...]
 (Specify the --help global option for a list of other help options)
 
 %s: error: {message}
@@ -59,7 +59,7 @@ class TestSetPkgArches(utils.CliTestCase):
     def test_handle_set_pkg_arches_help(self):
         self.assert_help(
             handle_set_pkg_arches,
-            """Usage: %s set-pkg-arches [options] arches tag package [package2 ...]
+            """Usage: %s set-pkg-arches [options] <arches> <tag> <package> [<package> ...]
 (Specify the --help global option for a list of other help options)
 
 Options:
diff --git a/tests/test_cli/test_set_pkg_owner.py b/tests/test_cli/test_set_pkg_owner.py
index 968f603..18e57af 100644
--- a/tests/test_cli/test_set_pkg_owner.py
+++ b/tests/test_cli/test_set_pkg_owner.py
@@ -16,7 +16,7 @@ class TestSetPkgOwner(utils.CliTestCase):
     maxDiff = None
 
     def setUp(self):
-        self.error_format = """Usage: %s set-pkg-owner [options] owner tag package [package2 ...]
+        self.error_format = """Usage: %s set-pkg-owner [options] <owner> <tag> <package> [<package> ...]
 (Specify the --help global option for a list of other help options)
 
 %s: error: {message}
@@ -59,7 +59,7 @@ class TestSetPkgOwner(utils.CliTestCase):
     def test_handle_set_pkg_owner_help(self):
         self.assert_help(
             handle_set_pkg_owner,
-            """Usage: %s set-pkg-owner [options] owner tag package [package2 ...]
+            """Usage: %s set-pkg-owner [options] <owner> <tag> <package> [<package> ...]
 (Specify the --help global option for a list of other help options)
 
 Options:
diff --git a/tests/test_cli/test_set_task_priority.py b/tests/test_cli/test_set_task_priority.py
index 61a3144..1455fc0 100644
--- a/tests/test_cli/test_set_task_priority.py
+++ b/tests/test_cli/test_set_task_priority.py
@@ -16,7 +16,7 @@ class TestSetTaskPriority(utils.CliTestCase):
     maxDiff = None
 
     def setUp(self):
-        self.error_format = """Usage: %s set-task-priority [options] --priority=<priority> <task-id> [task-id]...
+        self.error_format = """Usage: %s set-task-priority [options] --priority=<priority> <task_id> [<task_id> ...]
 (Specify the --help global option for a list of other help options)
 
 %s: error: {message}
@@ -82,7 +82,7 @@ class TestSetTaskPriority(utils.CliTestCase):
     def test_handle_set_task_priority_help(self):
         self.assert_help(
             handle_set_task_priority,
-            """Usage: %s set-task-priority [options] --priority=<priority> <task-id> [task-id]...
+            """Usage: %s set-task-priority [options] --priority=<priority> <task_id> [<task_id> ...]
 (Specify the --help global option for a list of other help options)
 
 Options:
diff --git a/tests/test_cli/test_tag_build.py b/tests/test_cli/test_tag_build.py
index ed87776..e82e007 100644
--- a/tests/test_cli/test_tag_build.py
+++ b/tests/test_cli/test_tag_build.py
@@ -19,7 +19,7 @@ class TestTagBuild(utils.CliTestCase):
         self.session = mock.MagicMock()
         self.options = mock.MagicMock()
 
-        self.error_format = """Usage: %s tag-build [options] <tag> <pkg> [<pkg>...]
+        self.error_format = """Usage: %s tag-build [options] <tag> <pkg> [<pkg> ...]
 (Specify the --help global option for a list of other help options)
 
 %s: error: {message}
@@ -89,7 +89,7 @@ class TestTagBuild(utils.CliTestCase):
     def test_handle_tag_build_help(self):
         self.assert_help(
             handle_tag_build,
-            """Usage: %s tag-build [options] <tag> <pkg> [<pkg>...]
+            """Usage: %s tag-build [options] <tag> <pkg> [<pkg> ...]
 (Specify the --help global option for a list of other help options)
 
 Options:
diff --git a/tests/test_cli/test_taskinfo.py b/tests/test_cli/test_taskinfo.py
index 5c342be..d16a220 100644
--- a/tests/test_cli/test_taskinfo.py
+++ b/tests/test_cli/test_taskinfo.py
@@ -588,7 +588,7 @@ class TestTaskInfo(utils.CliTestCase):
     maxDiff = None
 
     def setUp(self):
-        self.error_format = """Usage: %s taskinfo [options] taskID [taskID...]
+        self.error_format = """Usage: %s taskinfo [options] <task_id> [<task_id> ...]
 (Specify the --help global option for a list of other help options)
 
 %s: error: {message}
@@ -638,7 +638,7 @@ Host: kojibuilder
     def test_anon_handle_taskinfo_help(self):
         self.assert_help(
             anon_handle_taskinfo,
-            """Usage: %s taskinfo [options] taskID [taskID...]
+            """Usage: %s taskinfo [options] <task_id> [<task_id> ...]
 (Specify the --help global option for a list of other help options)
 
 Options:
diff --git a/tests/test_cli/test_unblock_group_pkg.py b/tests/test_cli/test_unblock_group_pkg.py
index 8cdfe31..d82deb1 100644
--- a/tests/test_cli/test_unblock_group_pkg.py
+++ b/tests/test_cli/test_unblock_group_pkg.py
@@ -19,7 +19,7 @@ class TestBlockGroupPkg(utils.CliTestCase):
         self.options = mock.MagicMock()
         self.activate_session = mock.patch('koji_cli.commands.activate_session').start()
 
-        self.error_format = """Usage: %s unblock-group-pkg [options] <tag> <group> <pkg> [<pkg>...]
+        self.error_format = """Usage: %s unblock-group-pkg [options] <tag> <group> <pkg> [<pkg> ...]
 (Specify the --help global option for a list of other help options)
 
 %s: error: {message}
@@ -54,7 +54,7 @@ class TestBlockGroupPkg(utils.CliTestCase):
     def test_handle_unblock_group_pkg_help(self):
         self.assert_help(
             handle_unblock_group_pkg,
-            """Usage: %s unblock-group-pkg [options] <tag> <group> <pkg> [<pkg>...]
+            """Usage: %s unblock-group-pkg [options] <tag> <group> <pkg> [<pkg> ...]
 (Specify the --help global option for a list of other help options)
 
 Options:
diff --git a/tests/test_cli/test_unblock_pkg.py b/tests/test_cli/test_unblock_pkg.py
index 2b6555c..1d1923b 100644
--- a/tests/test_cli/test_unblock_pkg.py
+++ b/tests/test_cli/test_unblock_pkg.py
@@ -17,7 +17,7 @@ class TestUnblockPkg(utils.CliTestCase):
     maxDiff = None
 
     def setUp(self):
-        self.error_format = """Usage: %s unblock-pkg [options] tag package [package2 ...]
+        self.error_format = """Usage: %s unblock-pkg [options] <tag> <package> [<package> ...]
 (Specify the --help global option for a list of other help options)
 
 %s: error: {message}
@@ -60,7 +60,7 @@ class TestUnblockPkg(utils.CliTestCase):
     def test_handle_unblock_pkg_help(self):
         self.assert_help(
             handle_unblock_pkg,
-            """Usage: %s unblock-pkg [options] tag package [package2 ...]
+            """Usage: %s unblock-pkg [options] <tag> <package> [<package> ...]
 (Specify the --help global option for a list of other help options)
 
 Options:
diff --git a/tests/test_cli/test_wrapper_rpm.py b/tests/test_cli/test_wrapper_rpm.py
index f4f83ce..ee69f04 100644
--- a/tests/test_cli/test_wrapper_rpm.py
+++ b/tests/test_cli/test_wrapper_rpm.py
@@ -21,7 +21,7 @@ class TestWrapperRpm(utils.CliTestCase):
         self.scm_url = 'git+https://github.com/project/test#12345'
         self.task_id = 1
 
-        self.error_format = """Usage: %s wrapper-rpm [options] target build-id|n-v-r URL
+        self.error_format = """Usage: %s wrapper-rpm [options] <target> <build-id|n-v-r> <URL>
 (Specify the --help global option for a list of other help options)
 
 %s: error: {message}
@@ -223,7 +223,7 @@ class TestWrapperRpm(utils.CliTestCase):
         """Test  handle_wrapper_rpm help message output"""
         self.assert_help(
             handle_wrapper_rpm,
-            """Usage: %s wrapper-rpm [options] target build-id|n-v-r URL
+            """Usage: %s wrapper-rpm [options] <target> <build-id|n-v-r> <URL>
 (Specify the --help global option for a list of other help options)
 
 Options:
diff --git a/tests/test_cli/test_write_signed_rpm.py b/tests/test_cli/test_write_signed_rpm.py
index ad258da..1c6a07f 100644
--- a/tests/test_cli/test_write_signed_rpm.py
+++ b/tests/test_cli/test_write_signed_rpm.py
@@ -107,7 +107,7 @@ class TestWriteSignedRPM(utils.CliTestCase):
     def setUp(self):
         self.custom_os_path_exists = {}
         self.os_path_exists = os.path.exists
-        self.error_format = """Usage: %s write-signed-rpm [options] <signature-key> n-v-r [n-v-r...]
+        self.error_format = """Usage: %s write-signed-rpm [options] <signature-key> <n-v-r> [<n-v-r> ...]
 (Specify the --help global option for a list of other help options)
 
 %s: error: {message}
@@ -238,7 +238,7 @@ class TestWriteSignedRPM(utils.CliTestCase):
         """Test handle_write_signed_rpm help message"""
         self.assert_help(
             handle_write_signed_rpm,
-            """Usage: %s write-signed-rpm [options] <signature-key> n-v-r [n-v-r...]
+            """Usage: %s write-signed-rpm [options] <signature-key> <n-v-r> [<n-v-r> ...]
 (Specify the --help global option for a list of other help options)
 
 Options:

From 7b598f3f84079b005815b0313ecf38cb2c6fcee5 Mon Sep 17 00:00:00 2001
From: Tomas Kopecek <tkopecek@redhat.com>
Date: Dec 10 2019 13:26:18 +0000
Subject: [PATCH 7/7] fix permission check in CLI


---

diff --git a/cli/koji_cli/commands.py b/cli/koji_cli/commands.py
index d94209d..c1f4647 100644
--- a/cli/koji_cli/commands.py
+++ b/cli/koji_cli/commands.py
@@ -118,8 +118,8 @@ def handle_remove_group(goptions, session, args):
     group = args[1]
 
     activate_session(session, goptions)
-    if not session.hasPerm('admin'):
-        error(_("This action requires admin privileges"))
+    if not (session.hasPerm('admin') or session.hasPerm('tag')):
+        parser.error(_("This action requires tag or admin privileges"))
 
     dsttag = session.getTag(tag)
     if not dsttag:
diff --git a/tests/test_cli/test_remove_group.py b/tests/test_cli/test_remove_group.py
index d478479..4314737 100644
--- a/tests/test_cli/test_remove_group.py
+++ b/tests/test_cli/test_remove_group.py
@@ -33,7 +33,7 @@ class TestRemoveGroup(utils.CliTestCase):
         session.getTag.return_value = None
 
         with self.assertRaises(SystemExit):
-            rv = handle_remove_group(options, session, arguments)
+            handle_remove_group(options, session, arguments)
 
         # assert that things were called as we expected.
         activate_session_mock.assert_called_once_with(session, options)
@@ -58,7 +58,7 @@ class TestRemoveGroup(utils.CliTestCase):
         session.getTagGroups.return_value = []
 
         with self.assertRaises(SystemExit):
-            rv = handle_remove_group(options, session, arguments)
+            handle_remove_group(options, session, arguments)
 
         # assert that things were called as we expected.
         activate_session_mock.assert_called_once_with(session, options)
@@ -111,8 +111,8 @@ class TestRemoveGroup(utils.CliTestCase):
                 stderr=expected,
                 activate_session=None)
 
-        # if we don't have 'admin' permission
+        # if we don't have 'tag' permission
         session.hasPerm.return_value = False
         with self.assertRaises(SystemExit):
-            rv = handle_remove_group(options, session, ['tag', 'grp'])
+            handle_remove_group(options, session, ['tag', 'grp'])
         activate_session_mock.assert_called_with(session, options)

