| Index: shell/subcmds/shell_cmd.py
|
| diff --git a/shell/subcmds/shell_cmd.py b/shell/subcmds/shell_cmd.py
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..4c3c550252b067c92399082989ee9802babb4e71
|
| --- /dev/null
|
| +++ b/shell/subcmds/shell_cmd.py
|
| @@ -0,0 +1,124 @@
|
| +# Copyright (c) 2011 The Chromium OS Authors. All rights reserved.
|
| +# Use of this source code is governed by a BSD-style license that can be
|
| +# found in the LICENSE file.
|
| +
|
| +"""Implementation of the 'shell' chromite command."""
|
| +
|
| +# Python imports
|
| +import optparse
|
| +import os
|
| +
|
| +
|
| +# Local imports
|
| +import chromite.lib.cros_build_lib as cros_lib
|
| +from chromite.shell import utils
|
| +from chromite.shell import subcmd
|
| +
|
| +
|
| +def _SplitEnvFromArgs(argv):
|
| + """Split environment settings from arguments.
|
| +
|
| + This function will just loop over the arguments, looking for ones with an '='
|
| + character in them. As long as it finds them, it takes them out of the arg
|
| + list adds them to a dictionary. As soon as it finds the first argument
|
| + without an '=', it stops looping.
|
| +
|
| + NOTE: Some doctests below test for equality with ==, since dicts with more
|
| + than one item may be arbitrarily ordered.
|
| +
|
| + >>> result = _SplitEnvFromArgs(['abc=1', 'def=two', 'three'])
|
| + >>> result == ({'abc': '1', 'def': 'two'}, ['three'])
|
| + True
|
| +
|
| + >>> _SplitEnvFromArgs(['one', 'two', 'three'])
|
| + ({}, ['one', 'two', 'three'])
|
| +
|
| + >>> _SplitEnvFromArgs(['abc=1', 'three', 'def=two'])
|
| + ({'abc': '1'}, ['three', 'def=two'])
|
| +
|
| + >>> result = _SplitEnvFromArgs(['abc=1', 'ghi=4 4', 'def=two'])
|
| + >>> result == ({'abc': '1', 'ghi': '4 4', 'def': 'two'}, [])
|
| + True
|
| +
|
| + >>> _SplitEnvFromArgs(['abc=1', 'abc=2', 'three'])
|
| + ({'abc': '2'}, ['three'])
|
| +
|
| + >>> _SplitEnvFromArgs([])
|
| + ({}, [])
|
| +
|
| + Args:
|
| + argv: The arguments to parse; this list is not modified. Should
|
| + not include "argv[0]"
|
| + Returns:
|
| + env: A dict containing key=value paris.
|
| + argv: A new list containing anything left after.
|
| + """
|
| + # Copy the list so we don't screw with caller...
|
| + argv = list(argv)
|
| +
|
| + env = {}
|
| + while argv:
|
| + if '=' in argv[0]:
|
| + key, val = argv.pop(0).split('=', 2)
|
| + env[key] = val
|
| + else:
|
| + break
|
| +
|
| + return env, argv
|
| +
|
| +
|
| +class ShellCmd(subcmd.ChromiteCmd):
|
| + """Start a shell in the chroot.
|
| +
|
| + This can either just start a simple interactive shell, it can be used to
|
| + run an arbirtary command inside the chroot and then exit.
|
| + """
|
| +
|
| + def Run(self, raw_argv, chroot_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.
|
| + """
|
| + # Parse options for command...
|
| + # ...note that OptionParser will eat the '--' if it's there, which is what
|
| + # we want..
|
| + usage_str = ('usage: %%prog [chromite_options] %s [options] [VAR=value] '
|
| + '[-- command [arg1] [arg2] ...]') % raw_argv[0]
|
| + parser = optparse.OptionParser(usage=usage_str)
|
| + (_, argv) = parser.parse_args(raw_argv[1:])
|
| +
|
| + # Enter the chroot if needed...
|
| + if not cros_lib.IsInsideChroot():
|
| + utils.EnterChroot(chroot_config, (self, 'Run'), raw_argv)
|
| + 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')
|
| +
|
| + # By default, no special environment...
|
| + env = None
|
| +
|
| + if not argv:
|
| + # If no arguments, we'll just start bash.
|
| + argv = ['bash']
|
| + else:
|
| + # Parse the command line, looking at the beginning for VAR=value type
|
| + # statements. I couldn't figure out a way to get bash to do this for
|
| + # me.
|
| + user_env, argv = _SplitEnvFromArgs(argv)
|
| + if not argv:
|
| + cros_lib.Die('No command specified')
|
| +
|
| + # If there was some environment, use it to override the standard
|
| + # environment.
|
| + if user_env:
|
| + env = dict(os.environ)
|
| + env.update(user_env)
|
| +
|
| + # Don't show anything special for errors; we'll let the shell report them.
|
| + cros_lib.RunCommand(argv, cwd=cwd, env=env, error_ok=True,
|
| + ignore_sigint=True)
|
|
|