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 239 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
250 | 250 |
251 if v.get(project_id): | 251 if v.get(project_id): |
252 raise ValueError('An override is already defined for [%s] (%s)' % ( | 252 raise ValueError('An override is already defined for [%s] (%s)' % ( |
253 project_id, v[project_id])) | 253 project_id, v[project_id])) |
254 path = os.path.abspath(os.path.expanduser(path)) | 254 path = os.path.abspath(os.path.expanduser(path)) |
255 if not os.path.isdir(path): | 255 if not os.path.isdir(path): |
256 raise ValueError('Override path [%s] is not a directory' % (path,)) | 256 raise ValueError('Override path [%s] is not a directory' % (path,)) |
257 v[project_id] = path | 257 v[project_id] = path |
258 | 258 |
259 | 259 |
260 def depgraph(config_file, package_deps, args): | |
261 from recipe_engine import depgraph | |
262 from recipe_engine import loader | |
263 | |
264 universe = loader.RecipeUniverse(package_deps, config_file) | |
265 | |
266 depgraph.main(universe, package_deps.root_package, | |
267 args.ignore_package, args.output, args.recipe_filter) | |
268 | |
269 | |
270 def refs(config_file, package_deps, args): | 260 def refs(config_file, package_deps, args): |
271 from recipe_engine import refs | 261 from recipe_engine import refs |
272 from recipe_engine import loader | 262 from recipe_engine import loader |
273 | 263 |
274 universe = loader.RecipeUniverse(package_deps, config_file) | 264 universe = loader.RecipeUniverse(package_deps, config_file) |
275 | 265 |
276 refs.main(universe, package_deps.root_package, args.modules, args.transitive) | 266 refs.main(universe, package_deps.root_package, args.modules, args.transitive) |
277 | 267 |
278 | 268 |
279 def doc(config_file, package_deps, args): | 269 def doc(config_file, package_deps, args): |
(...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
393 | 383 |
394 return post_process_args | 384 return post_process_args |
395 | 385 |
396 | 386 |
397 def main(): | 387 def main(): |
398 parser = argparse.ArgumentParser( | 388 parser = argparse.ArgumentParser( |
399 description='Interact with the recipe system.') | 389 description='Interact with the recipe system.') |
400 | 390 |
401 common_postprocess_func = add_common_args(parser) | 391 common_postprocess_func = add_common_args(parser) |
402 | 392 |
403 from recipe_engine import fetch, lint_test, bundle | 393 from recipe_engine import fetch, lint_test, bundle, depgraph |
404 to_add = [fetch, lint_test, bundle] | 394 to_add = [fetch, lint_test, bundle, depgraph] |
405 | 395 |
406 subp = parser.add_subparsers() | 396 subp = parser.add_subparsers() |
407 for module in to_add: | 397 for module in to_add: |
408 module.add_subparser(subp) | 398 module.add_subparser(subp) |
409 | 399 |
410 test_p = subp.add_parser( | 400 test_p = subp.add_parser( |
411 'test', | 401 'test', |
412 description='Generate or check expectations by simulation') | 402 description='Generate or check expectations by simulation') |
413 test_p.set_defaults(command='test') | 403 test_p.set_defaults(command='test') |
414 test_p.add_argument('args', nargs=argparse.REMAINDER) | 404 test_p.add_argument('args', nargs=argparse.REMAINDER) |
(...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
517 autoroll_p.add_argument( | 507 autoroll_p.add_argument( |
518 '--output-json', | 508 '--output-json', |
519 type=os.path.abspath, | 509 type=os.path.abspath, |
520 help='A json file to output information about the roll to.') | 510 help='A json file to output information about the roll to.') |
521 autoroll_p.add_argument( | 511 autoroll_p.add_argument( |
522 '--verbose-json', | 512 '--verbose-json', |
523 action='store_true', | 513 action='store_true', |
524 help=('Emit even more data in the output-json file. ' | 514 help=('Emit even more data in the output-json file. ' |
525 'Requires --output-json.')) | 515 'Requires --output-json.')) |
526 | 516 |
527 depgraph_p = subp.add_parser( | |
528 'depgraph', | |
529 description=( | |
530 'Produce graph of recipe and recipe module dependencies. Example: ' | |
531 './recipes.py --package infra/config/recipes.cfg depgraph | tred | ' | |
532 'dot -Tpdf > graph.pdf')) | |
533 depgraph_p.set_defaults(command='depgraph') | |
534 depgraph_p.add_argument( | |
535 '--output', type=argparse.FileType('w'), default=sys.stdout, | |
536 help='The file to write output to') | |
537 depgraph_p.add_argument( | |
538 '--ignore-package', action='append', default=[], | |
539 help='Ignore a recipe package (e.g. recipe_engine). Can be passed ' | |
540 'multiple times') | |
541 depgraph_p.add_argument( | |
542 '--recipe-filter', default='', | |
543 help='A recipe substring to examine. If present, the depgraph will ' | |
544 'include a recipe section containing recipes whose names contain ' | |
545 'this substring. It will also filter all nodes of the graph to only ' | |
546 'include modules touched by the filtered recipes.') | |
547 | |
548 refs_p = subp.add_parser( | 517 refs_p = subp.add_parser( |
549 'refs', | 518 'refs', |
550 description='List places referencing given recipe module(s).') | 519 description='List places referencing given recipe module(s).') |
551 refs_p.set_defaults(command='refs') | 520 refs_p.set_defaults(command='refs') |
552 refs_p.add_argument('modules', nargs='+', help='Module(s) to query for') | 521 refs_p.add_argument('modules', nargs='+', help='Module(s) to query for') |
553 refs_p.add_argument('--transitive', action='store_true', | 522 refs_p.add_argument('--transitive', action='store_true', |
554 help='Compute transitive closure of the references') | 523 help='Compute transitive closure of the references') |
555 | 524 |
556 doc_kinds=('binarypb', 'jsonpb', 'textpb', 'markdown(github)', | 525 doc_kinds=('binarypb', 'jsonpb', 'textpb', 'markdown(github)', |
557 'markdown(gitiles)') | 526 'markdown(gitiles)') |
(...skipping 126 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
684 | 653 |
685 if hasattr(args, 'func'): | 654 if hasattr(args, 'func'): |
686 return args.func(package_deps, args) | 655 return args.func(package_deps, args) |
687 | 656 |
688 if args.command == 'test': | 657 if args.command == 'test': |
689 return test(config_file, package_deps, args) | 658 return test(config_file, package_deps, args) |
690 elif args.command == 'run': | 659 elif args.command == 'run': |
691 return run(config_file, package_deps, args) | 660 return run(config_file, package_deps, args) |
692 elif args.command == 'autoroll': | 661 elif args.command == 'autoroll': |
693 return autoroll(repo_root, config_file, args) | 662 return autoroll(repo_root, config_file, args) |
694 elif args.command == 'depgraph': | |
695 return depgraph(config_file, package_deps, args) | |
696 elif args.command == 'refs': | 663 elif args.command == 'refs': |
697 return refs(config_file, package_deps, args) | 664 return refs(config_file, package_deps, args) |
698 elif args.command == 'doc': | 665 elif args.command == 'doc': |
699 return doc(config_file, package_deps, args) | 666 return doc(config_file, package_deps, args) |
700 else: | 667 else: |
701 print """Dear sir or madam, | 668 print """Dear sir or madam, |
702 It has come to my attention that a quite impossible condition has come | 669 It has come to my attention that a quite impossible condition has come |
703 to pass in the specification you have issued a request for us to fulfill. | 670 to pass in the specification you have issued a request for us to fulfill. |
704 It is with a heavy heart that I inform you that, at the present juncture, | 671 It is with a heavy heart that I inform you that, at the present juncture, |
705 there is no conceivable next action to be taken upon your request, and as | 672 there is no conceivable next action to be taken upon your request, and as |
(...skipping 23 matching lines...) Expand all Loading... |
729 | 696 |
730 if not isinstance(ret, int): | 697 if not isinstance(ret, int): |
731 if ret is None: | 698 if ret is None: |
732 ret = 0 | 699 ret = 0 |
733 else: | 700 else: |
734 print >> sys.stderr, ret | 701 print >> sys.stderr, ret |
735 ret = 1 | 702 ret = 1 |
736 sys.stdout.flush() | 703 sys.stdout.flush() |
737 sys.stderr.flush() | 704 sys.stderr.flush() |
738 os._exit(ret) | 705 os._exit(ret) |
OLD | NEW |