Chromium Code Reviews| Index: shell/subcmd.py |
| diff --git a/shell/subcmd.py b/shell/subcmd.py |
| index b93f65d5a4b826acea9e0bc8e0b716b577bf63c6..9b406972afac75fa2d0be2902ed8de623b338b53 100644 |
| --- a/shell/subcmd.py |
| +++ b/shell/subcmd.py |
| @@ -5,6 +5,15 @@ |
| """ChromiteCmd abstract class and related functions.""" |
| +# Python imports |
| +import os |
| +import sys |
| + |
|
sosa
2011/02/02 01:16:19
Don't need dbl lines here
diandersAtChromium
2011/02/02 01:49:10
Done.
|
| + |
| +# Local imports |
| +from chromite.lib import cros_build_lib as cros_lib |
| +from chromite.shell import utils |
| + |
| class ChromiteCmd(object): |
| """The abstract base class of commands listed at the top level of chromite.""" |
| @@ -27,3 +36,94 @@ class ChromiteCmd(object): |
| """ |
| # Must be implemented by subclass... |
| raise NotImplementedError() |
| + |
| + |
| +class WrappedChrootCmd(ChromiteCmd): |
| + """Superclass for any command that is simply wrapped by chromite. |
| + |
| + These are commands where: |
| + - We parse the command line only enough to figure out what board they |
| + want. All othe command line parsing is handled by the wrapped command. |
| + Because of this, the board name _needs_ to be specified first. |
| + - Everything else (arg parsing, help, etc) is handled by the wrapped command. |
| + The usage string will be a little messed up, but hopefully that's OK. |
| + """ |
| + |
| + def __init__(self, target_cmd, host_cmd, need_args=False): |
| + """WrappedChrootCmd constructor. |
| + |
| + Args: |
| + target_cmd: We'll put this at the start of argv when calling a target |
| + command. We'll substiture %s with the target. |
| + Like - ['my_command-%s'] or ['my_command', '--board=%s'] |
| + host_cmd: We'll put this at the start of argv when calling a host command. |
| + Like - ['my_command'] or ['sudo', 'my_command'] |
| + need_args: If True, we'll prompt for arguments if they weren't specified. |
| + This makes the most sense when someone runs chromite with no arguments |
| + and then walks through the menus. It's not ideal, but less sucky than |
| + just quitting. |
| + """ |
| + # Call superclass constructor. |
| + super(WrappedChrootCmd, self).__init__() |
| + |
| + # Save away params for use later in Run(). |
| + self._target_cmd = target_cmd |
| + self._host_cmd = host_cmd |
| + self._need_args = need_args |
| + |
| + def Run(self, raw_argv, chroot_config=None, argv=None, build_config=None): |
| + """Run the command. |
| + |
| + Args: |
| + raw_argv: Command line arguments, including this command's name, but not |
| + the chromite command name or chromite options. |
| + chroot_config: A SafeConfigParser for the chroot config; or None chromite |
| + was called from within the chroot. |
| + argv: None when called normally, but contains argv with board stripped off |
| + if we call ourselves with utils.EnterChroot(). |
| + build_config: None when called normally, but contains the SafeConfigParser |
| + for the build config if we call ourselves with utils.EnterChroot(). |
| + Note that even when called through utils.EnterChroot(), could still |
| + be None if user chose 'HOST' as the target. |
| + """ |
| + # If we didn't get called through EnterChroot, we need to read the build |
| + # config. |
| + if argv is None: |
| + # We look for the build config without calling OptionParser. This means |
| + # that the board _needs_ to be first (if it's specified) and all options |
| + # will be passed straight to our subcommand. |
| + argv, build_config = utils.GetBuildConfigFromArgs(raw_argv[1:]) |
| + |
| + # Enter the chroot if needed... |
| + if not cros_lib.IsInsideChroot(): |
| + utils.EnterChroot(chroot_config, (self, 'Run'), raw_argv, argv=argv, |
| + build_config=build_config) |
| + else: |
| + # We'll put CWD as src/scripts when running the command. Since everyone |
| + # running by hand has their cwd there, it is probably the safest. |
| + cwd = os.path.join(utils.SRCROOT_PATH, 'src', 'scripts') |
| + |
| + # Get command to call. If build_config is None, it means host. |
| + if build_config is None: |
| + argv_prefix = self._host_cmd |
| + else: |
| + # Make argv_prefix w/ target. |
| + target_name = build_config.get('BUILD', 'target') |
| + argv_prefix = [arg % target_name for arg in self._target_cmd] |
| + |
| + # Not a great way to to specify arguments, but works for now... Wrapped |
| + # commands are not wonderful interfaces anyway... |
| + if self._need_args and not argv: |
| + while True: |
| + sys.stderr.write('arg %d (blank to exit): ' % (len(argv)+1)) |
| + arg = raw_input() |
| + if not arg: |
| + break |
| + argv.append(arg) |
| + |
| + # Add the prefix... |
| + argv = argv_prefix + argv |
| + |
| + # Run, ignoring errors since some commands (ahem, cros_workon) seem to |
| + # return errors from things like --help. |
| + cros_lib.RunCommand(argv, cwd=cwd, ignore_sigint=True, error_ok=True) |