OLD | NEW |
1 #!/usr/bin/python | 1 #!/usr/bin/python |
2 # | 2 # |
3 # Copyright (c) 2011 The Chromium OS Authors. All rights reserved. | 3 # Copyright (c) 2011 The Chromium OS Authors. All rights reserved. |
4 # Use of this source code is governed by a BSD-style license that can be | 4 # Use of this source code is governed by a BSD-style license that can be |
5 # found in the LICENSE file. | 5 # found in the LICENSE file. |
6 | 6 |
7 """Main file for the chromite shell.""" | 7 """Main file for the chromite shell.""" |
8 | 8 |
9 # Python imports | 9 # Python imports |
10 import optparse | 10 import optparse |
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
86 else: | 86 else: |
87 choice = text_menu.TextMenu(possible_choices, 'Which chromite command', | 87 choice = text_menu.TextMenu(possible_choices, 'Which chromite command', |
88 menu_width=0) | 88 menu_width=0) |
89 | 89 |
90 if choice is None: | 90 if choice is None: |
91 cros_lib.Die('OK, cancelling...') | 91 cros_lib.Die('OK, cancelling...') |
92 else: | 92 else: |
93 return possible_cmds[choice] | 93 return possible_cmds[choice] |
94 | 94 |
95 | 95 |
| 96 def _ParseArguments(parser, argv): |
| 97 '''Helper function to separate arguments for a main program and sub-command. |
| 98 |
| 99 We split arguments into ones we understand, and ones to pass on to |
| 100 sub-commands. For the former, we put them through the given optparse and |
| 101 return the result options and sub-command name. For the latter, we just |
| 102 return a list of options and arguments not intended for us. |
| 103 |
| 104 We want to parse only the options that we understand at the top level of |
| 105 Chromite. Our heuristic here is that anything after the first positional |
| 106 parameter (which we assume is the command) is ignored at this level, and |
| 107 is passed down to the command level to handle. |
| 108 |
| 109 TODO(sjg): Revisit this to include tolerant option parser instead |
| 110 http://codereview.chromium.org/6469035/ |
| 111 |
| 112 Args: |
| 113 parser: Option parser. |
| 114 argv: List of program arguments |
| 115 |
| 116 Returns: |
| 117 options: Top level options (returned from optparse). |
| 118 cmd_str: Subcommand to run |
| 119 cmd_args: Arguments intended for subcommands. |
| 120 ''' |
| 121 our_args = [] |
| 122 cmd_args = list(argv) |
| 123 cmd_str = '' |
| 124 args = [] # Nothing until we call optparse |
| 125 while not cmd_str: |
| 126 if our_args: |
| 127 (options, args) = parser.parse_args(our_args) |
| 128 if len(args) > 1: |
| 129 cmd_str = args[1].lower() |
| 130 elif cmd_args: |
| 131 # We don't have a command yet. Transfer a positional arg from from |
| 132 # cmd_args to our_args to see if that does the trick. We move over any |
| 133 # options we find also. |
| 134 while cmd_args: |
| 135 arg = cmd_args.pop(0) |
| 136 our_args.append(arg) |
| 137 if not arg.startswith( '-'): |
| 138 break |
| 139 else: |
| 140 # No more cmd_args to consume. |
| 141 break |
| 142 |
| 143 # We must run the parser, even if it dies due to lack of arguments |
| 144 if not args: |
| 145 (options, args) = parser.parse_args(our_args) |
| 146 return options, cmd_str, cmd_args |
| 147 |
96 def main(): | 148 def main(): |
97 """Main function for the chromite shell.""" | 149 """Main function for the chromite shell.""" |
98 | 150 |
99 # Hack it so that argv[0] is 'chromite' so that it doesn't tell user to run | 151 # Hack it so that argv[0] is 'chromite' so that it doesn't tell user to run |
100 # 'main.py' in help commands... | 152 # 'main.py' in help commands... |
101 # TODO(dianders): Remove this hack, since it is ugly. Shouldn't be needed | 153 # TODO(dianders): Remove this hack, since it is ugly. Shouldn't be needed |
102 # once we change the way that the chromite wrapper works. | 154 # once we change the way that the chromite wrapper works. |
103 sys.argv[0] = 'chromite' | 155 sys.argv[0] = 'chromite' |
104 | 156 |
105 # Support EnterChroot(). | 157 # Support EnterChroot(). |
(...skipping 15 matching lines...) Expand all Loading... |
121 """%(prog)s [chromite_options] [cmd [args]]\n""" | 173 """%(prog)s [chromite_options] [cmd [args]]\n""" |
122 """\n""" | 174 """\n""" |
123 """The chromite script is a wrapper to make it easy to do various\n""" | 175 """The chromite script is a wrapper to make it easy to do various\n""" |
124 """build tasks. For a list of commands, run without any arguments.""" | 176 """build tasks. For a list of commands, run without any arguments.""" |
125 ) % {'prog': os.path.basename(sys.argv[0])} | 177 ) % {'prog': os.path.basename(sys.argv[0])} |
126 | 178 |
127 parser = optparse.OptionParser() | 179 parser = optparse.OptionParser() |
128 | 180 |
129 # Verbose defaults to full for now, just to keep people acclimatized to | 181 # Verbose defaults to full for now, just to keep people acclimatized to |
130 # vast amounts of comforting output. | 182 # vast amounts of comforting output. |
131 parser.add_option('-v', dest='verbose', default=3, | 183 parser.add_option('-v', dest='verbose', default=3, type='int', |
132 help='Control verbosity: 0=silent, 1=progress, 3=full') | 184 help='Control verbosity: 0=silent, 1=progress, 3=full') |
133 parser.add_option('-q', action='store_const', dest='verbose', const=0, | 185 parser.add_option('-q', action='store_const', dest='verbose', const=0, |
134 help='Be quieter (sets verbosity to 1)') | 186 help='Be quieter (sets verbosity to 1)') |
135 if not cros_lib.IsInsideChroot(): | 187 if not cros_lib.IsInsideChroot(): |
136 parser.add_option('--chroot', action='store', type='string', | 188 parser.add_option('--chroot', action='store', type='string', |
137 dest='chroot_name', default='chroot', | 189 dest='chroot_name', default='chroot', |
138 help="Chroot spec to use. Can be an absolute path to a spec file " | 190 help="Chroot spec to use. Can be an absolute path to a spec file " |
139 "or a substring of a chroot spec name (without .spec suffix)") | 191 "or a substring of a chroot spec name (without .spec suffix)") |
140 parser.usage = help_str | 192 parser.usage = help_str |
141 try: | 193 |
142 (options, args) = parser.parse_args() | 194 # Parse the arguments and separate them into top-level and subcmd arguments. |
143 except: | 195 options, cmd_str, cmd_args = _ParseArguments(parser, sys.argv) |
144 sys.exit(1) | |
145 | 196 |
146 # Set up the cros system. | 197 # Set up the cros system. |
147 cros_env = chromite_env.ChromiteEnv() | 198 cros_env = chromite_env.ChromiteEnv() |
148 | 199 |
149 # Configure the operation setup. | 200 # Configure the operation setup. |
150 oper = cros_env.GetOperation() | 201 oper = cros_env.GetOperation() |
151 oper.verbose = options.verbose >= 3 | 202 oper.verbose = options.verbose >= 3 |
152 oper.progress = options.verbose >= 1 | 203 oper.progress = options.verbose >= 1 |
153 | 204 |
154 # Look for special "--chroot" argument to allow for alternate chroots | 205 # Look for special "--chroot" argument to allow for alternate chroots |
155 if not cros_lib.IsInsideChroot(): | 206 if not cros_lib.IsInsideChroot(): |
156 chroot_spec_path = utils.FindSpec(options.chroot_name, | 207 chroot_spec_path = utils.FindSpec(options.chroot_name, |
157 spec_type=utils.CHROOT_SPEC_TYPE) | 208 spec_type=utils.CHROOT_SPEC_TYPE) |
158 | 209 |
159 oper.Info('Using chroot "%s"' % os.path.relpath(chroot_spec_path)) | 210 oper.Info('Using chroot "%s"' % os.path.relpath(chroot_spec_path)) |
160 | 211 |
161 chroot_config = utils.ReadConfig(chroot_spec_path) | 212 chroot_config = utils.ReadConfig(chroot_spec_path) |
162 else: | 213 else: |
163 # Already in the chroot; no need to get config... | 214 # Already in the chroot; no need to get config... |
164 chroot_config = None | 215 chroot_config = None |
165 | 216 |
166 # Get command and arguments | |
167 if args: | |
168 cmd_str = args[0].lower() | |
169 args = args[1:] | |
170 else: | |
171 cmd_str = '' | |
172 | |
173 # Validate the subcmd, popping a menu if needed. | 217 # Validate the subcmd, popping a menu if needed. |
174 cmd_str = _FindCommand(cmd_str) | 218 cmd_str = _FindCommand(cmd_str) |
175 oper.Info("Running command '%s'." % cmd_str) | 219 oper.Info("Running command '%s'." % cmd_str) |
176 | 220 |
177 # Finally, call the function w/ standard argv. | 221 # Finally, call the function w/ standard argv. |
178 cmd_cls = _COMMAND_HANDLERS[_COMMAND_STRS.index(cmd_str)] | 222 cmd_cls = _COMMAND_HANDLERS[_COMMAND_STRS.index(cmd_str)] |
179 cmd_obj = cmd_cls() | 223 cmd_obj = cmd_cls() |
180 cmd_obj.SetChromiteEnv(cros_env) | 224 cmd_obj.SetChromiteEnv(cros_env) |
181 try: | 225 try: |
182 cmd_obj.Run([cmd_str] + args, chroot_config=chroot_config) | 226 cmd_obj.Run([cmd_str] + cmd_args, chroot_config=chroot_config) |
183 | 227 |
184 # Handle an error in one of the scripts: print a message and exit. | 228 # Handle an error in one of the scripts: print a message and exit. |
185 except chromite_env.ChromiteError, msg: | 229 except chromite_env.ChromiteError, msg: |
186 sys.exit(1) | 230 sys.exit(1) |
187 | 231 |
188 if __name__ == '__main__': | 232 if __name__ == '__main__': |
189 main() | 233 main() |
OLD | NEW |