diff --git a/command.py b/command.py index f708832e..be2d6a6e 100644 --- a/command.py +++ b/command.py @@ -84,18 +84,34 @@ class Command(object): usage = 'repo %s' % self.NAME epilog = 'Run `repo help %s` to view the detailed manual.' % self.NAME self._optparse = optparse.OptionParser(usage=usage, epilog=epilog) + self._CommonOptions(self._optparse) self._Options(self._optparse) return self._optparse - def _Options(self, p): - """Initialize the option parser. + def _CommonOptions(self, p, opt_v=True): + """Initialize the option parser with common options. + + These will show up for *all* subcommands, so use sparingly. + NB: Keep in sync with repo:InitParser(). """ + g = p.add_option_group('Logging options') + opts = ['-v'] if opt_v else [] + g.add_option(*opts, '--verbose', + dest='output_mode', action='store_true', + help='show all output') + g.add_option('-q', '--quiet', + dest='output_mode', action='store_false', + help='only show errors') + if self.PARALLEL_JOBS is not None: p.add_option( '-j', '--jobs', type=int, default=self.PARALLEL_JOBS, help='number of jobs to run in parallel (default: %s)' % self.PARALLEL_JOBS) + def _Options(self, p): + """Initialize the option parser with subcommand-specific options.""" + def _RegisteredEnvironmentOptions(self): """Get options that can be set from environment variables. @@ -120,6 +136,11 @@ class Command(object): self.OptionParser.print_usage() sys.exit(1) + def CommonValidateOptions(self, opt, args): + """Validate common options.""" + opt.quiet = opt.output_mode is False + opt.verbose = opt.output_mode is True + def ValidateOptions(self, opt, args): """Validate the user options & arguments before executing. diff --git a/main.py b/main.py index 9abda6a9..8aba2ec2 100755 --- a/main.py +++ b/main.py @@ -257,6 +257,7 @@ class _Repo(object): git_trace2_event_log.CommandEvent(name='repo', subcommands=[name]) try: + cmd.CommonValidateOptions(copts, cargs) cmd.ValidateOptions(copts, cargs) result = cmd.Execute(copts, cargs) except (DownloadError, ManifestInvalidRevisionError, diff --git a/repo b/repo index 604f800b..cf9f1863 100755 --- a/repo +++ b/repo @@ -281,6 +281,8 @@ def GetParser(gitc_init=False): def InitParser(parser, gitc_init=False): """Setup the CLI parser.""" + # NB: Keep in sync with command.py:_CommonOptions(). + # Logging. group = parser.add_option_group('Logging options') group.add_option('-v', '--verbose', diff --git a/subcmds/abandon.py b/subcmds/abandon.py index b82a2dbf..ea3f4ed0 100644 --- a/subcmds/abandon.py +++ b/subcmds/abandon.py @@ -37,10 +37,6 @@ It is equivalent to "git branch -D ". PARALLEL_JOBS = DEFAULT_LOCAL_JOBS def _Options(self, p): - super()._Options(p) - p.add_option('-q', '--quiet', - action='store_true', default=False, - help='be quiet') p.add_option('--all', dest='all', action='store_true', help='delete all branches in all projects') diff --git a/subcmds/cherry_pick.py b/subcmds/cherry_pick.py index 4b7f1412..fc4998c3 100644 --- a/subcmds/cherry_pick.py +++ b/subcmds/cherry_pick.py @@ -32,9 +32,6 @@ The change id will be updated, and a reference to the old change id will be added. """ - def _Options(self, p): - pass - def ValidateOptions(self, opt, args): if len(args) != 1: self.Usage() diff --git a/subcmds/diff.py b/subcmds/diff.py index 81868176..cdc262e6 100644 --- a/subcmds/diff.py +++ b/subcmds/diff.py @@ -32,7 +32,6 @@ to the Unix 'patch' command. PARALLEL_JOBS = DEFAULT_LOCAL_JOBS def _Options(self, p): - super()._Options(p) p.add_option('-u', '--absolute', dest='absolute', action='store_true', help='Paths are relative to the repository root') diff --git a/subcmds/forall.py b/subcmds/forall.py index f0ce97cb..4a631fb7 100644 --- a/subcmds/forall.py +++ b/subcmds/forall.py @@ -129,8 +129,6 @@ without iterating through the remaining projects. del parser.rargs[0] def _Options(self, p): - super()._Options(p) - p.add_option('-r', '--regex', dest='regex', action='store_true', help="Execute the command only on projects matching regex or wildcard expression") @@ -153,13 +151,10 @@ without iterating through the remaining projects. help='Silently skip & do not exit non-zero due missing ' 'checkouts') - g = p.add_option_group('Output') + g = p.get_option_group('--quiet') g.add_option('-p', dest='project_header', action='store_true', help='Show project headers before output') - g.add_option('-v', '--verbose', - dest='verbose', action='store_true', - help='Show command error messages') p.add_option('--interactive', action='store_true', help='force interactive usage') diff --git a/subcmds/grep.py b/subcmds/grep.py index 49feaf6b..9a4a8a36 100644 --- a/subcmds/grep.py +++ b/subcmds/grep.py @@ -82,8 +82,11 @@ contain a line that matches both expressions: if value is not None: pt.append(value) + def _CommonOptions(self, p): + """Override common options slightly.""" + super()._CommonOptions(p, opt_v=False) + def _Options(self, p): - super()._Options(p) g = p.add_option_group('Sources') g.add_option('--cached', action='callback', callback=self._carry_option, diff --git a/subcmds/init.py b/subcmds/init.py index a23e529d..4182262e 100644 --- a/subcmds/init.py +++ b/subcmds/init.py @@ -79,6 +79,9 @@ manifest, a subsequent `repo sync` (or `repo sync -d`) is necessary to update the working directory files. """ + def _CommonOptions(self, p): + """Disable due to re-use of Wrapper().""" + def _Options(self, p, gitc_init=False): Wrapper().InitParser(p, gitc_init=gitc_init) @@ -436,9 +439,6 @@ to update the working directory files. % ('.'.join(str(x) for x in MIN_GIT_VERSION_SOFT),), file=sys.stderr) - opt.quiet = opt.output_mode is False - opt.verbose = opt.output_mode is True - rp = self.manifest.repoProject # Handle new --repo-url requests. diff --git a/subcmds/rebase.py b/subcmds/rebase.py index cf536e9d..e0186d4d 100644 --- a/subcmds/rebase.py +++ b/subcmds/rebase.py @@ -39,7 +39,8 @@ branch but need to incorporate new upstream changes "underneath" them. """ def _Options(self, p): - p.add_option('-i', '--interactive', + g = p.get_option_group('--quiet') + g.add_option('-i', '--interactive', dest="interactive", action="store_true", help="interactive rebase (single project only)") @@ -52,9 +53,6 @@ branch but need to incorporate new upstream changes "underneath" them. p.add_option('--no-ff', dest='ff', default=True, action='store_false', help='Pass --no-ff to git rebase') - p.add_option('-q', '--quiet', - dest='quiet', action='store_true', - help='Pass --quiet to git rebase') p.add_option('--autosquash', dest='autosquash', action='store_true', help='Pass --autosquash to git rebase') diff --git a/subcmds/stage.py b/subcmds/stage.py index 98b30221..ff0f1738 100644 --- a/subcmds/stage.py +++ b/subcmds/stage.py @@ -38,7 +38,8 @@ The '%prog' command stages files to prepare the next commit. """ def _Options(self, p): - p.add_option('-i', '--interactive', + g = p.get_option_group('--quiet') + g.add_option('-i', '--interactive', dest='interactive', action='store_true', help='use interactive staging') diff --git a/subcmds/start.py b/subcmds/start.py index 04589fb2..2593ace6 100644 --- a/subcmds/start.py +++ b/subcmds/start.py @@ -38,7 +38,6 @@ revision specified in the manifest. PARALLEL_JOBS = DEFAULT_LOCAL_JOBS def _Options(self, p): - super()._Options(p) p.add_option('--all', dest='all', action='store_true', help='begin branch in all projects') diff --git a/subcmds/status.py b/subcmds/status.py index 6c8e22e5..dc223a00 100644 --- a/subcmds/status.py +++ b/subcmds/status.py @@ -80,12 +80,9 @@ the following meanings: PARALLEL_JOBS = DEFAULT_LOCAL_JOBS def _Options(self, p): - super()._Options(p) p.add_option('-o', '--orphans', dest='orphans', action='store_true', help="include objects in working directory outside of repo projects") - p.add_option('-q', '--quiet', action='store_true', - help="only print the name of modified projects") def _StatusHelper(self, quiet, project): """Obtains the status for a specific project. diff --git a/subcmds/sync.py b/subcmds/sync.py index b8abb1a7..e7079879 100644 --- a/subcmds/sync.py +++ b/subcmds/sync.py @@ -167,13 +167,14 @@ later is required to fix a server side protocol bug. """ PARALLEL_JOBS = 1 - def _Options(self, p, show_smart=True): + def _CommonOptions(self, p): try: self.PARALLEL_JOBS = self.manifest.default.sync_j except ManifestParseError: pass - super()._Options(p) + super()._CommonOptions(p) + def _Options(self, p, show_smart=True): p.add_option('--jobs-network', default=None, type=int, metavar='JOBS', help='number of network jobs to run in parallel (defaults to --jobs)') p.add_option('--jobs-checkout', default=None, type=int, metavar='JOBS', @@ -211,12 +212,6 @@ later is required to fix a server side protocol bug. p.add_option('-c', '--current-branch', dest='current_branch_only', action='store_true', help='fetch only current branch from server') - p.add_option('-v', '--verbose', - dest='output_mode', action='store_true', - help='show all sync output') - p.add_option('-q', '--quiet', - dest='output_mode', action='store_false', - help='only show errors') p.add_option('-m', '--manifest-name', dest='manifest_name', help='temporary manifest to use for this sync', metavar='NAME.xml') @@ -770,9 +765,6 @@ later is required to fix a server side protocol bug. soft_limit, _ = _rlimit_nofile() self.jobs = min(self.jobs, (soft_limit - 5) // 3) - opt.quiet = opt.output_mode is False - opt.verbose = opt.output_mode is True - if opt.manifest_name: self.manifest.Override(opt.manifest_name)