OLD | NEW |
(Empty) | |
| 1 # Copyright (c) 2011 The Chromium OS Authors. All rights reserved. |
| 2 # Use of this source code is governed by a BSD-style license that can be |
| 3 # found in the LICENSE file. |
| 4 |
| 5 """Implementation of the 'shell' chromite command.""" |
| 6 |
| 7 # Python imports |
| 8 import optparse |
| 9 import os |
| 10 |
| 11 |
| 12 # Local imports |
| 13 import chromite.lib.cros_build_lib as cros_lib |
| 14 from chromite.shell import utils |
| 15 from chromite.shell import subcmd |
| 16 |
| 17 |
| 18 def _SplitEnvFromArgs(argv): |
| 19 """Split environment settings from arguments. |
| 20 |
| 21 This function will just loop over the arguments, looking for ones with an '=' |
| 22 character in them. As long as it finds them, it takes them out of the arg |
| 23 list adds them to a dictionary. As soon as it finds the first argument |
| 24 without an '=', it stops looping. |
| 25 |
| 26 NOTE: Some doctests below test for equality with ==, since dicts with more |
| 27 than one item may be arbitrarily ordered. |
| 28 |
| 29 >>> result = _SplitEnvFromArgs(['abc=1', 'def=two', 'three']) |
| 30 >>> result == ({'abc': '1', 'def': 'two'}, ['three']) |
| 31 True |
| 32 |
| 33 >>> _SplitEnvFromArgs(['one', 'two', 'three']) |
| 34 ({}, ['one', 'two', 'three']) |
| 35 |
| 36 >>> _SplitEnvFromArgs(['abc=1', 'three', 'def=two']) |
| 37 ({'abc': '1'}, ['three', 'def=two']) |
| 38 |
| 39 >>> result = _SplitEnvFromArgs(['abc=1', 'ghi=4 4', 'def=two']) |
| 40 >>> result == ({'abc': '1', 'ghi': '4 4', 'def': 'two'}, []) |
| 41 True |
| 42 |
| 43 >>> _SplitEnvFromArgs(['abc=1', 'abc=2', 'three']) |
| 44 ({'abc': '2'}, ['three']) |
| 45 |
| 46 >>> _SplitEnvFromArgs([]) |
| 47 ({}, []) |
| 48 |
| 49 Args: |
| 50 argv: The arguments to parse; this list is not modified. Should |
| 51 not include "argv[0]" |
| 52 Returns: |
| 53 env: A dict containing key=value paris. |
| 54 argv: A new list containing anything left after. |
| 55 """ |
| 56 # Copy the list so we don't screw with caller... |
| 57 argv = list(argv) |
| 58 |
| 59 env = {} |
| 60 while argv: |
| 61 if '=' in argv[0]: |
| 62 key, val = argv.pop(0).split('=', 2) |
| 63 env[key] = val |
| 64 else: |
| 65 break |
| 66 |
| 67 return env, argv |
| 68 |
| 69 |
| 70 class ShellCmd(subcmd.ChromiteCmd): |
| 71 """Start a shell in the chroot. |
| 72 |
| 73 This can either just start a simple interactive shell, it can be used to |
| 74 run an arbirtary command inside the chroot and then exit. |
| 75 """ |
| 76 |
| 77 def Run(self, raw_argv, chroot_config=None): |
| 78 """Run the command. |
| 79 |
| 80 Args: |
| 81 raw_argv: Command line arguments, including this command's name, but not |
| 82 the chromite command name or chromite options. |
| 83 chroot_config: A SafeConfigParser for the chroot config; or None chromite |
| 84 was called from within the chroot. |
| 85 """ |
| 86 # Parse options for command... |
| 87 # ...note that OptionParser will eat the '--' if it's there, which is what |
| 88 # we want.. |
| 89 usage_str = ('usage: %%prog [chromite_options] %s [options] [VAR=value] ' |
| 90 '[-- command [arg1] [arg2] ...]') % raw_argv[0] |
| 91 parser = optparse.OptionParser(usage=usage_str) |
| 92 (_, argv) = parser.parse_args(raw_argv[1:]) |
| 93 |
| 94 # Enter the chroot if needed... |
| 95 if not cros_lib.IsInsideChroot(): |
| 96 utils.EnterChroot(chroot_config, (self, 'Run'), raw_argv) |
| 97 else: |
| 98 # We'll put CWD as src/scripts when running the command. Since everyone |
| 99 # running by hand has their cwd there, it is probably the safest. |
| 100 cwd = os.path.join(utils.SRCROOT_PATH, 'src', 'scripts') |
| 101 |
| 102 # By default, no special environment... |
| 103 env = None |
| 104 |
| 105 if not argv: |
| 106 # If no arguments, we'll just start bash. |
| 107 argv = ['bash'] |
| 108 else: |
| 109 # Parse the command line, looking at the beginning for VAR=value type |
| 110 # statements. I couldn't figure out a way to get bash to do this for |
| 111 # me. |
| 112 user_env, argv = _SplitEnvFromArgs(argv) |
| 113 if not argv: |
| 114 cros_lib.Die('No command specified') |
| 115 |
| 116 # If there was some environment, use it to override the standard |
| 117 # environment. |
| 118 if user_env: |
| 119 env = dict(os.environ) |
| 120 env.update(user_env) |
| 121 |
| 122 # Don't show anything special for errors; we'll let the shell report them. |
| 123 cros_lib.RunCommand(argv, cwd=cwd, env=env, error_ok=True, |
| 124 ignore_sigint=True) |
OLD | NEW |