Bug 1520006 - [mach] Fix bug in 'mach completion', r=nalexander
authorAndrew Halberstadt <ahalberstadt@mozilla.com>
Mon, 14 Jan 2019 21:20:55 +0000
changeset 513814 797e7094701d
parent 513813 4b9bf0633280
child 513815 627f1def8aeb
push id1953
push userffxbld-merge
push dateMon, 11 Mar 2019 12:10:20 +0000
treeherdermozilla-release@9c35dcbaa899 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersnalexander
bugs1520006, 1518586
milestone66.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1520006 - [mach] Fix bug in 'mach completion', r=nalexander This fixes an issue from bug 1518586. It stemmed from the fact that I misunderstood how the 'parser' attribute was being used in mach commands and didn't do enough testing. This patch fixes things such that we check that 'parser' is not None, as well as add the completion targets from 'handler.arguments'. Differential Revision: https://phabricator.services.mozilla.com/D16501
python/mach/mach/commands/commandinfo.py
--- a/python/mach/mach/commands/commandinfo.py
+++ b/python/mach/mach/commands/commandinfo.py
@@ -67,24 +67,39 @@ class BuiltinCommands(object):
         is_help = 'help' in args
         command = None
         for i, arg in enumerate(args):
             if arg in all_commands:
                 command = arg
                 args = args[i+1:]
                 break
 
+        # If no command is typed yet, just offer the commands.
         if not command:
             print("\n".join(all_commands))
             return
 
         handler = self.context.commands.command_handlers[command]
+        # If a subcommand was typed, update the handler.
         for arg in args:
             if arg in handler.subcommand_handlers:
                 handler = handler.subcommand_handlers[arg]
                 break
 
-        parser = handler.parser
         targets = sorted(handler.subcommand_handlers.keys())
-        if not is_help:
-            targets.append('help')
-            targets.extend(chain(*[action.option_strings for action in parser._actions]))
+        if is_help:
+            print("\n".join(targets))
+            return
+
+        targets.append('help')
+
+        # The 'option_strings' are of the form [('-f', '--foo'), ('-b', '--bar'), ...].
+        option_strings = [item[0] for item in handler.arguments]
+        # Filter out positional arguments (we don't want to complete their metavar).
+        option_strings = [opt for opt in option_strings if opt[0].startswith('-')]
+        targets.extend(chain(*option_strings))
+
+        # If the command uses its own ArgumentParser, extract options from there as well.
+        if handler.parser:
+            targets.extend(chain(*[action.option_strings
+                                   for action in handler.parser._actions]))
+
         print("\n".join(targets))