| OLD | NEW | 
|---|
| 1 #!/usr/bin/env python | 1 #!/usr/bin/env python | 
| 2 # Copyright 2012 The LUCI Authors. All rights reserved. | 2 # Copyright 2012 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 """Front end tool to operate on .isolate files. | 6 """Front end tool to operate on .isolate files. | 
| 7 | 7 | 
| 8 This includes creating, merging or compiling them to generate a .isolated file. | 8 This includes creating, merging or compiling them to generate a .isolated file. | 
| 9 | 9 | 
| 10 See more information at | 10 See more information at | 
| (...skipping 461 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 472     """Loads state from disk.""" | 472     """Loads state from disk.""" | 
| 473     assert os.path.isabs(isolated_filepath), isolated_filepath | 473     assert os.path.isabs(isolated_filepath), isolated_filepath | 
| 474     isolated_basedir = os.path.dirname(isolated_filepath) | 474     isolated_basedir = os.path.dirname(isolated_filepath) | 
| 475     return cls( | 475     return cls( | 
| 476         isolated_filepath, | 476         isolated_filepath, | 
| 477         SavedState.load_file( | 477         SavedState.load_file( | 
| 478             isolatedfile_to_state(isolated_filepath), isolated_basedir)) | 478             isolatedfile_to_state(isolated_filepath), isolated_basedir)) | 
| 479 | 479 | 
| 480   def load_isolate( | 480   def load_isolate( | 
| 481       self, cwd, isolate_file, path_variables, config_variables, | 481       self, cwd, isolate_file, path_variables, config_variables, | 
| 482       extra_variables, blacklist, ignore_broken_items): | 482       extra_variables, blacklist, ignore_broken_items, collapse_symlinks): | 
| 483     """Updates self.isolated and self.saved_state with information loaded from a | 483     """Updates self.isolated and self.saved_state with information loaded from a | 
| 484     .isolate file. | 484     .isolate file. | 
| 485 | 485 | 
| 486     Processes the loaded data, deduce root_dir, relative_cwd. | 486     Processes the loaded data, deduce root_dir, relative_cwd. | 
| 487     """ | 487     """ | 
| 488     # Make sure to not depend on os.getcwd(). | 488     # Make sure to not depend on os.getcwd(). | 
| 489     assert os.path.isabs(isolate_file), isolate_file | 489     assert os.path.isabs(isolate_file), isolate_file | 
| 490     isolate_file = file_path.get_native_path_case(isolate_file) | 490     isolate_file = file_path.get_native_path_case(isolate_file) | 
| 491     logging.info( | 491     logging.info( | 
| 492         'CompleteState.load_isolate(%s, %s, %s, %s, %s, %s)', | 492         'CompleteState.load_isolate(%s, %s, %s, %s, %s, %s, %s)', | 
| 493         cwd, isolate_file, path_variables, config_variables, extra_variables, | 493         cwd, isolate_file, path_variables, config_variables, extra_variables, | 
| 494         ignore_broken_items) | 494         ignore_broken_items, collapse_symlinks) | 
| 495 | 495 | 
| 496     # Config variables are not affected by the paths and must be used to | 496     # Config variables are not affected by the paths and must be used to | 
| 497     # retrieve the paths, so update them first. | 497     # retrieve the paths, so update them first. | 
| 498     self.saved_state.update_config(config_variables) | 498     self.saved_state.update_config(config_variables) | 
| 499 | 499 | 
| 500     with fs.open(isolate_file, 'r') as f: | 500     with fs.open(isolate_file, 'r') as f: | 
| 501       # At that point, variables are not replaced yet in command and infiles. | 501       # At that point, variables are not replaced yet in command and infiles. | 
| 502       # infiles may contain directory entries and is in posix style. | 502       # infiles may contain directory entries and is in posix style. | 
| 503       command, infiles, read_only, isolate_cmd_dir = ( | 503       command, infiles, read_only, isolate_cmd_dir = ( | 
| 504           isolate_format.load_isolate_for_config( | 504           isolate_format.load_isolate_for_config( | 
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 543             '%s; %s' | 543             '%s; %s' | 
| 544             % (k, v, self.saved_state.root_dir, dest)) | 544             % (k, v, self.saved_state.root_dir, dest)) | 
| 545     # Normalize the files based to self.saved_state.root_dir. It is important to | 545     # Normalize the files based to self.saved_state.root_dir. It is important to | 
| 546     # keep the trailing os.path.sep at that step. | 546     # keep the trailing os.path.sep at that step. | 
| 547     infiles = [ | 547     infiles = [ | 
| 548       file_path.relpath( | 548       file_path.relpath( | 
| 549           file_path.normpath(os.path.join(isolate_cmd_dir, f)), | 549           file_path.normpath(os.path.join(isolate_cmd_dir, f)), | 
| 550           self.saved_state.root_dir) | 550           self.saved_state.root_dir) | 
| 551       for f in infiles | 551       for f in infiles | 
| 552     ] | 552     ] | 
| 553     follow_symlinks = sys.platform != 'win32' | 553     follow_symlinks = False | 
|  | 554     if not collapse_symlinks: | 
|  | 555       follow_symlinks = sys.platform != 'win32' | 
| 554     # Expand the directories by listing each file inside. Up to now, trailing | 556     # Expand the directories by listing each file inside. Up to now, trailing | 
| 555     # os.path.sep must be kept. | 557     # os.path.sep must be kept. | 
| 556     infiles = isolated_format.expand_directories_and_symlinks( | 558     infiles = isolated_format.expand_directories_and_symlinks( | 
| 557         self.saved_state.root_dir, | 559         self.saved_state.root_dir, | 
| 558         infiles, | 560         infiles, | 
| 559         tools.gen_blacklist(blacklist), | 561         tools.gen_blacklist(blacklist), | 
| 560         follow_symlinks, | 562         follow_symlinks, | 
| 561         ignore_broken_items) | 563         ignore_broken_items) | 
| 562 | 564 | 
| 563     # Finally, update the new data to be able to generate the foo.isolated file, | 565     # Finally, update the new data to be able to generate the foo.isolated file, | 
| 564     # the file that is used by run_isolated.py. | 566     # the file that is used by run_isolated.py. | 
| 565     self.saved_state.update_isolated(command, infiles, read_only, relative_cwd) | 567     self.saved_state.update_isolated(command, infiles, read_only, relative_cwd) | 
| 566     logging.debug(self) | 568     logging.debug(self) | 
| 567 | 569 | 
| 568   def files_to_metadata(self, subdir): | 570   def files_to_metadata(self, subdir, collapse_symlinks): | 
| 569     """Updates self.saved_state.files with the files' mode and hash. | 571     """Updates self.saved_state.files with the files' mode and hash. | 
| 570 | 572 | 
| 571     If |subdir| is specified, filters to a subdirectory. The resulting .isolated | 573     If |subdir| is specified, filters to a subdirectory. The resulting .isolated | 
| 572     file is tainted. | 574     file is tainted. | 
| 573 | 575 | 
| 574     See isolated_format.file_to_metadata() for more information. | 576     See isolated_format.file_to_metadata() for more information. | 
| 575     """ | 577     """ | 
| 576     for infile in sorted(self.saved_state.files): | 578     for infile in sorted(self.saved_state.files): | 
| 577       if subdir and not infile.startswith(subdir): | 579       if subdir and not infile.startswith(subdir): | 
| 578         self.saved_state.files.pop(infile) | 580         self.saved_state.files.pop(infile) | 
| 579       else: | 581       else: | 
| 580         filepath = os.path.join(self.root_dir, infile) | 582         filepath = os.path.join(self.root_dir, infile) | 
| 581         self.saved_state.files[infile] = isolated_format.file_to_metadata( | 583         self.saved_state.files[infile] = isolated_format.file_to_metadata( | 
| 582             filepath, | 584             filepath, | 
| 583             self.saved_state.files[infile], | 585             self.saved_state.files[infile], | 
| 584             self.saved_state.read_only, | 586             self.saved_state.read_only, | 
| 585             self.saved_state.algo) | 587             self.saved_state.algo, | 
|  | 588             collapse_symlinks) | 
| 586 | 589 | 
| 587   def save_files(self): | 590   def save_files(self): | 
| 588     """Saves self.saved_state and creates a .isolated file.""" | 591     """Saves self.saved_state and creates a .isolated file.""" | 
| 589     logging.debug('Dumping to %s' % self.isolated_filepath) | 592     logging.debug('Dumping to %s' % self.isolated_filepath) | 
| 590     self.saved_state.child_isolated_files = chromium_save_isolated( | 593     self.saved_state.child_isolated_files = chromium_save_isolated( | 
| 591         self.isolated_filepath, | 594         self.isolated_filepath, | 
| 592         self.saved_state.to_isolated(), | 595         self.saved_state.to_isolated(), | 
| 593         self.saved_state.path_variables, | 596         self.saved_state.path_variables, | 
| 594         self.saved_state.algo) | 597         self.saved_state.algo) | 
| 595     total_bytes = sum( | 598     total_bytes = sum( | 
| (...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 667             complete_state.saved_state.isolate_file, | 670             complete_state.saved_state.isolate_file, | 
| 668             isolatedfile_to_state(options.isolated)) | 671             isolatedfile_to_state(options.isolated)) | 
| 669         complete_state = CompleteState( | 672         complete_state = CompleteState( | 
| 670             options.isolated, | 673             options.isolated, | 
| 671             SavedState(complete_state.saved_state.isolated_basedir)) | 674             SavedState(complete_state.saved_state.isolated_basedir)) | 
| 672 | 675 | 
| 673   if not skip_update: | 676   if not skip_update: | 
| 674     # Then load the .isolate and expands directories. | 677     # Then load the .isolate and expands directories. | 
| 675     complete_state.load_isolate( | 678     complete_state.load_isolate( | 
| 676         cwd, isolate, options.path_variables, options.config_variables, | 679         cwd, isolate, options.path_variables, options.config_variables, | 
| 677         options.extra_variables, options.blacklist, options.ignore_broken_items) | 680         options.extra_variables, options.blacklist, options.ignore_broken_items, | 
|  | 681         options.collapse_symlinks) | 
| 678 | 682 | 
| 679   # Regenerate complete_state.saved_state.files. | 683   # Regenerate complete_state.saved_state.files. | 
| 680   if subdir: | 684   if subdir: | 
| 681     subdir = unicode(subdir) | 685     subdir = unicode(subdir) | 
| 682     # This is tricky here. If it is a path, take it from the root_dir. If | 686     # This is tricky here. If it is a path, take it from the root_dir. If | 
| 683     # it is a variable, it must be keyed from the directory containing the | 687     # it is a variable, it must be keyed from the directory containing the | 
| 684     # .isolate file. So translate all variables first. | 688     # .isolate file. So translate all variables first. | 
| 685     translated_path_variables = dict( | 689     translated_path_variables = dict( | 
| 686         (k, | 690         (k, | 
| 687           os.path.normpath(os.path.join(complete_state.saved_state.relative_cwd, | 691           os.path.normpath(os.path.join(complete_state.saved_state.relative_cwd, | 
| 688             v))) | 692             v))) | 
| 689         for k, v in complete_state.saved_state.path_variables.iteritems()) | 693         for k, v in complete_state.saved_state.path_variables.iteritems()) | 
| 690     subdir = isolate_format.eval_variables(subdir, translated_path_variables) | 694     subdir = isolate_format.eval_variables(subdir, translated_path_variables) | 
| 691     subdir = subdir.replace('/', os.path.sep) | 695     subdir = subdir.replace('/', os.path.sep) | 
| 692 | 696 | 
| 693   if not skip_update: | 697   if not skip_update: | 
| 694     complete_state.files_to_metadata(subdir) | 698     complete_state.files_to_metadata(subdir, options.collapse_symlinks) | 
| 695   return complete_state | 699   return complete_state | 
| 696 | 700 | 
| 697 | 701 | 
| 698 def create_isolate_tree(outdir, root_dir, files, relative_cwd, read_only): | 702 def create_isolate_tree(outdir, root_dir, files, relative_cwd, read_only): | 
| 699   """Creates a isolated tree usable for test execution. | 703   """Creates a isolated tree usable for test execution. | 
| 700 | 704 | 
| 701   Returns the current working directory where the isolated command should be | 705   Returns the current working directory where the isolated command should be | 
| 702   started in. | 706   started in. | 
| 703   """ | 707   """ | 
| 704   # Forcibly copy when the tree has to be read only. Otherwise the inode is | 708   # Forcibly copy when the tree has to be read only. Otherwise the inode is | 
| (...skipping 410 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 1115       '-i', '--isolate', | 1119       '-i', '--isolate', | 
| 1116       metavar='FILE', | 1120       metavar='FILE', | 
| 1117       help='.isolate file to load the dependency data from') | 1121       help='.isolate file to load the dependency data from') | 
| 1118   add_variable_option(group) | 1122   add_variable_option(group) | 
| 1119   group.add_option( | 1123   group.add_option( | 
| 1120       '--ignore_broken_items', action='store_true', | 1124       '--ignore_broken_items', action='store_true', | 
| 1121       default=bool(os.environ.get('ISOLATE_IGNORE_BROKEN_ITEMS')), | 1125       default=bool(os.environ.get('ISOLATE_IGNORE_BROKEN_ITEMS')), | 
| 1122       help='Indicates that invalid entries in the isolated file to be ' | 1126       help='Indicates that invalid entries in the isolated file to be ' | 
| 1123            'only be logged and not stop processing. Defaults to True if ' | 1127            'only be logged and not stop processing. Defaults to True if ' | 
| 1124            'env var ISOLATE_IGNORE_BROKEN_ITEMS is set') | 1128            'env var ISOLATE_IGNORE_BROKEN_ITEMS is set') | 
|  | 1129   group.add_option( | 
|  | 1130       '-L', '--collapse_symlinks', action='store_true', | 
|  | 1131       help='Treat any symlinks as if they were the normal underlying file') | 
| 1125   parser.add_option_group(group) | 1132   parser.add_option_group(group) | 
| 1126 | 1133 | 
| 1127 | 1134 | 
| 1128 def add_subdir_option(parser): | 1135 def add_subdir_option(parser): | 
| 1129   parser.add_option( | 1136   parser.add_option( | 
| 1130       '--subdir', | 1137       '--subdir', | 
| 1131       help='Filters to a subdirectory. Its behavior changes depending if it ' | 1138       help='Filters to a subdirectory. Its behavior changes depending if it ' | 
| 1132            'is a relative path as a string or as a path variable. Path ' | 1139            'is a relative path as a string or as a path variable. Path ' | 
| 1133            'variables are always keyed from the directory containing the ' | 1140            'variables are always keyed from the directory containing the ' | 
| 1134            '.isolate file. Anything else is keyed on the root directory.') | 1141            '.isolate file. Anything else is keyed on the root directory.') | 
| (...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 1217     print >> sys.stderr, 'Execution failure: %s' % e | 1224     print >> sys.stderr, 'Execution failure: %s' % e | 
| 1218     return 1 | 1225     return 1 | 
| 1219 | 1226 | 
| 1220 | 1227 | 
| 1221 if __name__ == '__main__': | 1228 if __name__ == '__main__': | 
| 1222   subprocess42.inhibit_os_error_reporting() | 1229   subprocess42.inhibit_os_error_reporting() | 
| 1223   fix_encoding.fix_encoding() | 1230   fix_encoding.fix_encoding() | 
| 1224   tools.disable_buffering() | 1231   tools.disable_buffering() | 
| 1225   colorama.init() | 1232   colorama.init() | 
| 1226   sys.exit(main(sys.argv[1:])) | 1233   sys.exit(main(sys.argv[1:])) | 
| OLD | NEW | 
|---|