OLD | NEW |
1 #!/usr/bin/env python | 1 #!/usr/bin/env python |
2 # Copyright 2015 The LUCI Authors. All rights reserved. | 2 # Copyright 2015 The LUCI Authors. All rights reserved. |
3 # Use of this source code is governed under the Apache License, Version 2.0 | 3 # Use of this source code is governed under the Apache License, Version 2.0 |
4 # that can be found in the LICENSE file. | 4 # that can be found in the LICENSE file. |
5 | 5 |
6 """Tool to interact with recipe repositories. | 6 """Tool to interact with recipe repositories. |
7 | 7 |
8 This tool operates on the nearest ancestor directory containing an | 8 This tool operates on the nearest ancestor directory containing an |
9 infra/config/recipes.cfg. | 9 infra/config/recipes.cfg. |
10 """ | 10 """ |
(...skipping 204 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
215 | 215 |
216 if args.recipes_dir: | 216 if args.recipes_dir: |
217 print package_spec.recipes_path | 217 print package_spec.recipes_path |
218 | 218 |
219 | 219 |
220 def main(): | 220 def main(): |
221 from recipe_engine import package | 221 from recipe_engine import package |
222 | 222 |
223 # Super-annoyingly, we need to manually parse for simulation_test since | 223 # Super-annoyingly, we need to manually parse for simulation_test since |
224 # argparse is bonkers and doesn't allow us to forward --help to subcommands. | 224 # argparse is bonkers and doesn't allow us to forward --help to subcommands. |
| 225 # Save old_args for if we're using bootstrap |
| 226 original_sys_argv = sys.argv[:] |
225 if 'simulation_test' in sys.argv: | 227 if 'simulation_test' in sys.argv: |
226 index = sys.argv.index('simulation_test') | 228 index = sys.argv.index('simulation_test') |
227 sys.argv = sys.argv[:index+1] + [json.dumps(sys.argv[index+1:])] | 229 sys.argv = sys.argv[:index+1] + [json.dumps(sys.argv[index+1:])] |
228 | 230 |
229 parser = argparse.ArgumentParser( | 231 parser = argparse.ArgumentParser( |
230 description='Interact with the recipe system.') | 232 description='Interact with the recipe system.') |
231 | 233 |
232 parser.add_argument( | 234 parser.add_argument( |
233 '--package', | 235 '--package', |
234 help='Path to recipes.cfg of the recipe package to operate on' | 236 help='Path to recipes.cfg of the recipe package to operate on' |
235 ', usually in infra/config/recipes.cfg') | 237 ', usually in infra/config/recipes.cfg') |
236 parser.add_argument( | 238 parser.add_argument( |
237 '--deps-path', | 239 '--deps-path', |
238 help='Path where recipe engine dependencies will be extracted.') | 240 help='Path where recipe engine dependencies will be extracted.') |
239 parser.add_argument( | 241 parser.add_argument( |
240 '--verbose', '-v', action='store_true', | 242 '--verbose', '-v', action='store_true', |
241 help='Increase logging verboisty') | 243 help='Increase logging verboisty') |
242 # TODO(phajdan.jr): Figure out if we need --no-fetch; remove if not. | 244 # TODO(phajdan.jr): Figure out if we need --no-fetch; remove if not. |
243 parser.add_argument( | 245 parser.add_argument( |
244 '--no-fetch', action='store_true', | 246 '--no-fetch', action='store_true', |
245 help='Disable automatic fetching') | 247 help='Disable automatic fetching') |
246 parser.add_argument( | 248 parser.add_argument( |
247 '--bootstrap-script', | 249 '--bootstrap-script', |
248 help='Path to the script used to bootstrap this tool (internal use only)') | 250 help='Path to the script used to bootstrap this tool (internal use only)') |
249 parser.add_argument('-O', '--project-override', metavar='ID=PATH', | 251 parser.add_argument('-O', '--project-override', metavar='ID=PATH', |
250 action=ProjectOverrideAction, | 252 action=ProjectOverrideAction, |
251 help='Override a project repository path with a local one.') | 253 help='Override a project repository path with a local one.') |
| 254 parser.add_argument( |
| 255 '--use-bootstrap', action='store_true', |
| 256 help='Use bootstrap/bootstrap.py to create a isolated python virtualenv' |
| 257 ' with required python dependencies.') |
252 | 258 |
253 subp = parser.add_subparsers() | 259 subp = parser.add_subparsers() |
254 | 260 |
255 fetch_p = subp.add_parser( | 261 fetch_p = subp.add_parser( |
256 'fetch', | 262 'fetch', |
257 description='Fetch and update dependencies.') | 263 description='Fetch and update dependencies.') |
258 fetch_p.set_defaults(command='fetch') | 264 fetch_p.set_defaults(command='fetch') |
259 | 265 |
260 simulation_test_p = subp.add_parser( | 266 simulation_test_p = subp.add_parser( |
261 'simulation_test', | 267 'simulation_test', |
(...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
369 info_p = subp.add_parser( | 375 info_p = subp.add_parser( |
370 'info', | 376 'info', |
371 description='Query information about the current recipe package') | 377 description='Query information about the current recipe package') |
372 info_p.set_defaults(command='info') | 378 info_p.set_defaults(command='info') |
373 info_p.add_argument( | 379 info_p.add_argument( |
374 '--recipes-dir', action='store_true', | 380 '--recipes-dir', action='store_true', |
375 help='Get the subpath where the recipes live relative to repository root') | 381 help='Get the subpath where the recipes live relative to repository root') |
376 | 382 |
377 args = parser.parse_args() | 383 args = parser.parse_args() |
378 | 384 |
| 385 if args.use_bootstrap and not os.environ.pop('RECIPES_RUN_BOOTSTRAP', None): |
| 386 subprocess.check_call( |
| 387 [sys.executable, 'bootstrap/bootstrap.py', '--deps-file', |
| 388 'bootstrap/deps.pyl', 'ENV'], |
| 389 cwd=os.path.dirname(os.path.realpath(__file__))) |
| 390 |
| 391 os.environ['RECIPES_RUN_BOOTSTRAP'] = '1' |
| 392 args = sys.argv |
| 393 return subprocess.call( |
| 394 ['ENV/bin/python'] + original_sys_argv, |
| 395 cwd=os.path.dirname(os.path.realpath(__file__))) |
| 396 |
379 if args.verbose: | 397 if args.verbose: |
380 logging.getLogger().setLevel(logging.INFO) | 398 logging.getLogger().setLevel(logging.INFO) |
381 | 399 |
382 # Commands which do not require config_file, package_deps, and other objects | 400 # Commands which do not require config_file, package_deps, and other objects |
383 # initialized later. | 401 # initialized later. |
384 if args.command == 'remote_run': | 402 if args.command == 'remote_run': |
385 return remote_run(args) | 403 return remote_run(args) |
386 | 404 |
387 repo_root, config_file = get_package_config(args) | 405 repo_root, config_file = get_package_config(args) |
388 | 406 |
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
443 ret = main() | 461 ret = main() |
444 if not isinstance(ret, int): | 462 if not isinstance(ret, int): |
445 if ret is None: | 463 if ret is None: |
446 ret = 0 | 464 ret = 0 |
447 else: | 465 else: |
448 print >> sys.stderr, ret | 466 print >> sys.stderr, ret |
449 ret = 1 | 467 ret = 1 |
450 sys.stdout.flush() | 468 sys.stdout.flush() |
451 sys.stderr.flush() | 469 sys.stderr.flush() |
452 os._exit(ret) | 470 os._exit(ret) |
OLD | NEW |