Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(97)

Side by Side Diff: recipes.py

Issue 2511213002: Move ENV into custom deps, allow it to be random. (Closed)
Patch Set: Comments. Created 4 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 """
11 11
12 import argparse 12 import argparse
13 import collections 13 import collections
14 import json 14 import json
15 import logging 15 import logging
16 import os 16 import os
17 import shutil
17 import subprocess 18 import subprocess
18 import sys 19 import sys
20 import tempfile
19 21
20 ROOT_DIR = os.path.dirname(os.path.abspath(__file__)) 22 ROOT_DIR = os.path.dirname(os.path.abspath(__file__))
21 sys.path.insert(0, ROOT_DIR) 23 sys.path.insert(0, ROOT_DIR)
22 24
23 from recipe_engine import env 25 from recipe_engine import env
24 from recipe_engine import arguments_pb2 26 from recipe_engine import arguments_pb2
25 from google.protobuf import json_format as jsonpb 27 from google.protobuf import json_format as jsonpb
26 from google.protobuf import text_format as textpb 28 from google.protobuf import text_format as textpb
27 29
28 def get_package_config(args): 30 def get_package_config(args):
(...skipping 338 matching lines...) Expand 10 before | Expand all | Expand 10 after
367 """Creates a properties dictionary from an arguments_pb2.PropertyMap entry. 369 """Creates a properties dictionary from an arguments_pb2.PropertyMap entry.
368 370
369 Args: 371 Args:
370 pmap (arguments_pb2.PropertyMap): Map to convert to dictionary form. 372 pmap (arguments_pb2.PropertyMap): Map to convert to dictionary form.
371 Returns (dict): A dictionary derived from the properties in "pmap". 373 Returns (dict): A dictionary derived from the properties in "pmap".
372 """ 374 """
373 return dict((k, _op_property_value(pmap[k])) for k in pmap) 375 return dict((k, _op_property_value(pmap[k])) for k in pmap)
374 376
375 377
376 def main(): 378 def main():
377 from recipe_engine import package
378
379 # Super-annoyingly, we need to manually parse for simulation_test since 379 # Super-annoyingly, we need to manually parse for simulation_test since
380 # argparse is bonkers and doesn't allow us to forward --help to subcommands. 380 # argparse is bonkers and doesn't allow us to forward --help to subcommands.
381 # Save old_args for if we're using bootstrap 381 # Save old_args for if we're using bootstrap
382 original_sys_argv = sys.argv[:] 382 original_sys_argv = sys.argv[:]
383 if 'simulation_test' in sys.argv: 383 if 'simulation_test' in sys.argv:
384 index = sys.argv.index('simulation_test') 384 index = sys.argv.index('simulation_test')
385 sys.argv = sys.argv[:index+1] + [json.dumps(sys.argv[index+1:])] 385 sys.argv = sys.argv[:index+1] + [json.dumps(sys.argv[index+1:])]
386 386
387 parser = argparse.ArgumentParser( 387 parser = argparse.ArgumentParser(
388 description='Interact with the recipe system.') 388 description='Interact with the recipe system.')
389 389
390 parser.add_argument( 390 parser.add_argument(
391 '--package', 391 '--package',
392 help='Path to recipes.cfg of the recipe package to operate on' 392 help='Path to recipes.cfg of the recipe package to operate on'
393 ', usually in infra/config/recipes.cfg') 393 ', usually in infra/config/recipes.cfg')
394 parser.add_argument( 394 parser.add_argument(
395 '--deps-path', 395 '--deps-path',
396 help='Path where recipe engine dependencies will be extracted.') 396 help='Path where recipe engine dependencies will be extracted. Specify '
397 '"-" to use a temporary directory for deps, which will be cleaned '
398 'up on exit.')
397 parser.add_argument( 399 parser.add_argument(
398 '--verbose', '-v', action='count', 400 '--verbose', '-v', action='count',
399 help='Increase logging verboisty') 401 help='Increase logging verboisty')
400 # TODO(phajdan.jr): Figure out if we need --no-fetch; remove if not. 402 # TODO(phajdan.jr): Figure out if we need --no-fetch; remove if not.
401 parser.add_argument( 403 parser.add_argument(
402 '--no-fetch', action='store_true', 404 '--no-fetch', action='store_true',
403 help='Disable automatic fetching') 405 help='Disable automatic fetching')
404 parser.add_argument('-O', '--project-override', metavar='ID=PATH', 406 parser.add_argument('-O', '--project-override', metavar='ID=PATH',
405 action=ProjectOverrideAction, 407 action=ProjectOverrideAction,
406 help='Override a project repository path with a local one.') 408 help='Override a project repository path with a local one.')
(...skipping 147 matching lines...) Expand 10 before | Expand all | Expand 10 after
554 556
555 args = parser.parse_args() 557 args = parser.parse_args()
556 558
557 # Load/parse operational arguments. 559 # Load/parse operational arguments.
558 op_args = arguments_pb2.Arguments() 560 op_args = arguments_pb2.Arguments()
559 if args.operational_args_path is not None: 561 if args.operational_args_path is not None:
560 with open(args.operational_args_path) as fd: 562 with open(args.operational_args_path) as fd:
561 data = fd.read() 563 data = fd.read()
562 jsonpb.Parse(data, op_args) 564 jsonpb.Parse(data, op_args)
563 565
564 if args.use_bootstrap and not os.environ.pop('RECIPES_RUN_BOOTSTRAP', None):
565 subprocess.check_call(
566 [sys.executable, 'bootstrap/bootstrap.py', '--deps-file',
567 'bootstrap/deps.pyl', 'ENV'],
568 cwd=os.path.dirname(os.path.realpath(__file__)))
569
570 os.environ['RECIPES_RUN_BOOTSTRAP'] = '1'
571 args = sys.argv
572 return subprocess.call(
573 [os.path.join(
574 os.path.dirname(os.path.realpath(__file__)), 'ENV/bin/python'),
575 os.path.join(ROOT_DIR, 'recipes.py')] + original_sys_argv[1:])
576
577 if args.verbose > 1: 566 if args.verbose > 1:
578 logging.getLogger().setLevel(logging.DEBUG) 567 logging.getLogger().setLevel(logging.DEBUG)
579 elif args.verbose > 0: 568 elif args.verbose > 0:
580 logging.getLogger().setLevel(logging.INFO) 569 logging.getLogger().setLevel(logging.INFO)
581 570
571 # If we're using a temporary deps directory, create it.
572 temp_deps_dir = None
573 try:
574 # When bootstrapping, re-use the calling wrapper's deps directory instead of
575 # creating a new one.
576 args.deps_path = os.environ.pop('RECIPES_RUN_BOOTSTRAP_DEPS_DIR',
577 args.deps_path)
578 if args.deps_path == '-':
579 # "-" means use a temporary deps path.
580 temp_deps_dir = tempfile.mkdtemp(dir=ROOT_DIR, suffix='_deps')
581 args.deps_path = temp_deps_dir
582
583 if args.deps_path:
584 logging.warning('(Not Bad) Using custom deps path: %s', args.deps_path)
585
586 # If we're bootstrapping, construct our bootstrap environment. If we're
587 # using a custom deps path, install our enviornment there too.
588 if args.use_bootstrap and not os.environ.pop('RECIPES_RUN_BOOTSTRAP', None):
589 # Propagate our deps path, if specified, so we re-use our temporary
590 # directory.
591 if args.deps_path:
592 env_path = os.path.join(args.deps_path, '.ENV')
593 os.environ['RECIPES_RUN_BOOTSTRAP_DEPS_DIR'] = args.deps_path
594 else:
595 env_path = os.path.join(ROOT_DIR, 'ENV')
596
597 logging.debug('Installing bootstrap environment into: %s', env_path)
598 subprocess.check_call(
599 [
600 sys.executable,
601 os.path.join(ROOT_DIR, 'bootstrap', 'bootstrap.py'),
602 '--deps-file', os.path.join(ROOT_DIR, 'bootstrap', 'deps.pyl'),
603 env_path,
604 ],
605 cwd=ROOT_DIR)
606
607 # Mark that we're bootstrapping, so the next invocation falls through to
608 # standard recipe operation.
609 os.environ['RECIPES_RUN_BOOTSTRAP'] = '1'
610 args = sys.argv
611 return subprocess.call(
612 [
613 os.path.join(env_path, 'bin', 'python'),
614 os.path.join(ROOT_DIR, 'recipes.py'),
615 ] + original_sys_argv[1:])
616
617 # Standard recipe engine operation.
618 return _real_main(args, op_args)
619
620 finally:
621 # If we're using a temporary deps directory, clean it up here.
622 if temp_deps_dir:
623 logging.info('Cleaning up temporary deps path: %s', temp_deps_dir)
624
625 # Remove as much of the temporary directory as we can. If something goes
626 # wrong, log the error, but don't actually raise anything.
627 def on_error(_function, path, excinfo):
628 logging.error('Error cleaning up temporary deps file: %s', path,
629 exc_info=excinfo)
630 shutil.rmtree(temp_deps_dir, onerror=on_error)
631
632
633 def _real_main(args, op_args):
634 from recipe_engine import package
635
582 # Commands which do not require config_file, package_deps, and other objects 636 # Commands which do not require config_file, package_deps, and other objects
583 # initialized later. 637 # initialized later.
584 if args.command == 'remote': 638 if args.command == 'remote':
585 return remote(args) 639 return remote(args)
586 640
587 repo_root, config_file = get_package_config(args) 641 repo_root, config_file = get_package_config(args)
588 642
589 try: 643 try:
590 # TODO(phajdan.jr): gracefully handle inconsistent deps when rolling. 644 # TODO(phajdan.jr): gracefully handle inconsistent deps when rolling.
591 # This fails if the starting point does not have consistent dependency 645 # This fails if the starting point does not have consistent dependency
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after
652 706
653 if not isinstance(ret, int): 707 if not isinstance(ret, int):
654 if ret is None: 708 if ret is None:
655 ret = 0 709 ret = 0
656 else: 710 else:
657 print >> sys.stderr, ret 711 print >> sys.stderr, ret
658 ret = 1 712 ret = 1
659 sys.stdout.flush() 713 sys.stdout.flush()
660 sys.stderr.flush() 714 sys.stderr.flush()
661 os._exit(ret) 715 os._exit(ret)
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698