From 56345c345bdfdd71399d17ccd0ffe8f39bf720eb Mon Sep 17 00:00:00 2001 From: Mike Frysinger Date: Mon, 26 Jul 2021 23:46:32 -0400 Subject: [PATCH] repo: refactor help output handling Currently we have the behavior: * `repo`: Equivalent to `repo help` -- only shows common subcommands (with short description), and then exits 0. * `repo --help`: Shows repo's core options, lists all commands (no specific info), and then exits 0. The first case is not behaving well: * If you run `repo` without a specific subcommand, that's an error, so we should be exiting 1 instead. * Showing only subcommands and no actual option summary makes it seem like repo itself doesn't take any options. This confuses users. Let's rework things a bit. Now we have the behavior: * `repo`: Shows repo's core options, lists all commands (no specific info), and then exits 1. * `repo --help`: Shows repo's core options, shows common subcommands (with short description), and then exits 0. * `repo --help-all`: Shows repo's core options, shows all subcommands (with short description), and then exits 0. Basically we swap the behavior of `repo` and `repo --help`, and fix the exit status when the subcommand is missing. The addition of --help-all is mostly for the man pages. We were relying on `repo help --all` to generate the repo(1) man page, but that too omitted the core repo options. Now the man page includes all the core repo options and provides a summary of all commands. Change-Id: I1f99b99d5b8af2591f96a078d0647a3d76d6b0fc Reviewed-on: https://gerrit-review.googlesource.com/c/git-repo/+/312908 Reviewed-by: Xin Li Tested-by: Mike Frysinger --- main.py | 30 ++++++++++++++++++++++------- man/repo-manifest.1 | 19 +++++++++++-------- man/repo.1 | 42 ++++++++++++++++++++++++++++++++++++++--- release/update-manpages | 2 +- subcmds/help.py | 7 +++++++ 5 files changed, 81 insertions(+), 19 deletions(-) diff --git a/main.py b/main.py index 253f3112..229cb729 100755 --- a/main.py +++ b/main.py @@ -95,6 +95,8 @@ global_options = optparse.OptionParser( add_help_option=False) global_options.add_option('-h', '--help', action='store_true', help='show this help message and exit') +global_options.add_option('--help-all', action='store_true', + help='show this help message with all subcommands and exit') global_options.add_option('-p', '--paginate', dest='pager', action='store_true', help='display command output in the pager') @@ -128,6 +130,23 @@ class _Repo(object): self.repodir = repodir self.commands = all_commands + def _PrintHelp(self, short: bool = False, all_commands: bool = False): + """Show --help screen.""" + global_options.print_help() + print() + if short: + commands = ' '.join(sorted(self.commands)) + wrapped_commands = textwrap.wrap(commands, width=77) + print('Available commands:\n %s' % ('\n '.join(wrapped_commands),)) + print('\nRun `repo help ` for command-specific details.') + print('Bug reports:', Wrapper().BUG_URL) + else: + cmd = self.commands['help']() + if all_commands: + cmd.PrintAllCommandsBody() + else: + cmd.PrintCommonCommandsBody() + def _ParseArgs(self, argv): """Parse the main `repo` command line options.""" for i, arg in enumerate(argv): @@ -177,19 +196,16 @@ class _Repo(object): SetTrace() # Handle options that terminate quickly first. - if gopts.help: - global_options.print_help() - commands = ' '.join(sorted(self.commands)) - wrapped_commands = textwrap.wrap(commands, width=77) - print('\nAvailable commands:\n %s' % ('\n '.join(wrapped_commands),)) - print('\nRun `repo help ` for command-specific details.') + if gopts.help or gopts.help_all: + self._PrintHelp(short=False, all_commands=gopts.help_all) return 0 elif gopts.show_version: # Always allow global --version regardless of subcommand validity. name = 'version' elif not name: # No subcommand specified, so show the help/subcommand. - name = 'help' + self._PrintHelp(short=True) + return 1 SetDefaultColoring(gopts.color) diff --git a/man/repo-manifest.1 b/man/repo-manifest.1 index e42cc42e..be467607 100644 --- a/man/repo-manifest.1 +++ b/man/repo-manifest.1 @@ -36,6 +36,9 @@ output manifest in JSON format (experimental) \fB\-\-pretty\fR format output for humans to read .TP +\fB\-\-no\-local\-manifests\fR +ignore local manifests +.TP \fB\-o\fR \-|NAME.xml, \fB\-\-output\-file\fR=\fI\,\-\/\fR|NAME.xml file to save the manifest to .SS Logging options: @@ -95,7 +98,7 @@ include*)> .IP .IP - + @@ -393,13 +396,13 @@ Same syntax as the corresponding element of `project`. .PP Element annotation .PP -Zero or more annotation elements may be specified as children of a project -element. Each element describes a name\-value pair that will be exported into -each project's environment during a 'forall' command, prefixed with REPO__. In -addition, there is an optional attribute "keep" which accepts the case -insensitive values "true" (default) or "false". This attribute determines -whether or not the annotation will be kept when exported with the manifest -subcommand. +Zero or more annotation elements may be specified as children of a project or +remote element. Each element describes a name\-value pair. For projects, this +name\-value pair will be exported into each project's environment during a +\&'forall' command, prefixed with `REPO__`. In addition, there is an optional +attribute "keep" which accepts the case insensitive values "true" (default) or +"false". This attribute determines whether or not the annotation will be kept +when exported with the manifest subcommand. .PP Element copyfile .PP diff --git a/man/repo.1 b/man/repo.1 index 0bc3acdb..0e85b0b7 100644 --- a/man/repo.1 +++ b/man/repo.1 @@ -2,9 +2,44 @@ .TH REPO "1" "July 2021" "repo" "Repo Manual" .SH NAME repo \- repository management tool built on top of git -.SH DESCRIPTION -usage: repo COMMAND [ARGS] -The complete list of recognized repo commands are: +.SH SYNOPSIS +.B repo +[\fI\,-p|--paginate|--no-pager\/\fR] \fI\,COMMAND \/\fR[\fI\,ARGS\/\fR] +.SH OPTIONS +.TP +\fB\-h\fR, \fB\-\-help\fR +show this help message and exit +.TP +\fB\-\-help\-all\fR +show this help message with all subcommands and exit +.TP +\fB\-p\fR, \fB\-\-paginate\fR +display command output in the pager +.TP +\fB\-\-no\-pager\fR +disable the pager +.TP +\fB\-\-color\fR=\fI\,COLOR\/\fR +control color usage: auto, always, never +.TP +\fB\-\-trace\fR +trace git command execution (REPO_TRACE=1) +.TP +\fB\-\-trace\-python\fR +trace python command execution +.TP +\fB\-\-time\fR +time repo command execution +.TP +\fB\-\-version\fR +display this version of repo +.TP +\fB\-\-event\-log\fR=\fI\,EVENT_LOG\/\fR +filename of event log to append timeline to +.TP +\fB\-\-git\-trace2\-event\-log\fR=\fI\,GIT_TRACE2_EVENT_LOG\/\fR +directory to write git trace2 event log to +.SS "The complete list of recognized repo commands are:" .TP abandon Permanently abandon a development branch @@ -91,3 +126,4 @@ version Display the version of repo .PP See 'repo help ' for more information on a specific command. +Bug reports: https://bugs.chromium.org/p/gerrit/issues/entry?template=Repo+tool+issue diff --git a/release/update-manpages b/release/update-manpages index 3aeee206..f841f306 100755 --- a/release/update-manpages +++ b/release/update-manpages @@ -59,7 +59,7 @@ def main(argv): cmdlist.append(['help2man', '-N', '-n', 'repository management tool built on top of git', '-S', 'repo', '-m', 'Repo Manual', f'--version-string={version}', '-o', MANDIR.joinpath('repo.1'), TOPDIR.joinpath('repo'), - '-h', 'help --all']) + '-h', '--help-all']) with tempfile.TemporaryDirectory() as tempdir: repo_dir = Path(tempdir) / '.repo' diff --git a/subcmds/help.py b/subcmds/help.py index f302e75c..1a60ef45 100644 --- a/subcmds/help.py +++ b/subcmds/help.py @@ -50,14 +50,21 @@ Displays detailed usage information about a command. def _PrintAllCommands(self): print('usage: repo COMMAND [ARGS]') + self.PrintAllCommandsBody() + + def PrintAllCommandsBody(self): print('The complete list of recognized repo commands are:') commandNames = list(sorted(all_commands)) self._PrintCommands(commandNames) print("See 'repo help ' for more information on a " 'specific command.') + print('Bug reports:', Wrapper().BUG_URL) def _PrintCommonCommands(self): print('usage: repo COMMAND [ARGS]') + self.PrintCommonCommandsBody() + + def PrintCommonCommandsBody(self): print('The most commonly used repo commands are:') def gitc_supported(cmd):