Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 #!/usr/bin/env python | 1 #!/usr/bin/env python |
| 2 # Copyright (c) 2012 The Chromium Authors. All rights reserved. | 2 # Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 3 # Use of this source code is governed by a BSD-style license that can be | 3 # Use of this source code is governed by a BSD-style license that can be |
| 4 # found in the LICENSE file. | 4 # found in the LICENSE file. |
| 5 | 5 |
| 6 """Meta checkout manager supporting both Subversion and GIT.""" | 6 """Meta checkout manager supporting both Subversion and GIT.""" |
| 7 # Files | 7 # Files |
| 8 # .gclient : Current client configuration, written by 'config' command. | 8 # .gclient : Current client configuration, written by 'config' command. |
| 9 # Format is a Python script defining 'solutions', a list whose | 9 # Format is a Python script defining 'solutions', a list whose |
| 10 # entries each are maps binding the strings "name" and "url" | 10 # entries each are maps binding the strings "name" and "url" |
| (...skipping 268 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 279 def __init__(self, parent, name, url, safesync_url, managed, custom_deps, | 279 def __init__(self, parent, name, url, safesync_url, managed, custom_deps, |
| 280 custom_vars, custom_hooks, deps_file, should_process): | 280 custom_vars, custom_hooks, deps_file, should_process): |
| 281 gclient_utils.WorkItem.__init__(self, name) | 281 gclient_utils.WorkItem.__init__(self, name) |
| 282 DependencySettings.__init__( | 282 DependencySettings.__init__( |
| 283 self, parent, url, safesync_url, managed, custom_deps, custom_vars, | 283 self, parent, url, safesync_url, managed, custom_deps, custom_vars, |
| 284 custom_hooks, deps_file, should_process) | 284 custom_hooks, deps_file, should_process) |
| 285 | 285 |
| 286 # This is in both .gclient and DEPS files: | 286 # This is in both .gclient and DEPS files: |
| 287 self._deps_hooks = [] | 287 self._deps_hooks = [] |
| 288 | 288 |
| 289 self._pre_deps_hooks = [] | |
| 290 | |
| 289 # Calculates properties: | 291 # Calculates properties: |
| 290 self._parsed_url = None | 292 self._parsed_url = None |
| 291 self._dependencies = [] | 293 self._dependencies = [] |
| 292 # A cache of the files affected by the current operation, necessary for | 294 # A cache of the files affected by the current operation, necessary for |
| 293 # hooks. | 295 # hooks. |
| 294 self._file_list = [] | 296 self._file_list = [] |
| 295 # If it is not set to True, the dependency wasn't processed for its child | 297 # If it is not set to True, the dependency wasn't processed for its child |
| 296 # dependency, i.e. its DEPS wasn't read. | 298 # dependency, i.e. its DEPS wasn't read. |
| 297 self._deps_parsed = False | 299 self._deps_parsed = False |
| 298 # This dependency has been processed, i.e. checked out | 300 # This dependency has been processed, i.e. checked out |
| 299 self._processed = False | 301 self._processed = False |
| 302 # This dependency had its pre-DEPS hooks run | |
| 303 self._pre_deps_hooks_ran = False | |
| 300 # This dependency had its hook run | 304 # This dependency had its hook run |
| 301 self._hooks_ran = False | 305 self._hooks_ran = False |
| 302 # This is the scm used to checkout self.url. It may be used by dependencies | 306 # This is the scm used to checkout self.url. It may be used by dependencies |
| 303 # to get the datetime of the revision we checked out. | 307 # to get the datetime of the revision we checked out. |
| 304 self._used_scm = None | 308 self._used_scm = None |
| 305 # The actual revision we ended up getting, or None if that information is | 309 # The actual revision we ended up getting, or None if that information is |
| 306 # unavailable | 310 # unavailable |
| 307 self._got_revision = None | 311 self._got_revision = None |
| 308 | 312 |
| 309 if not self.name and self.parent: | 313 if not self.name and self.parent: |
| (...skipping 231 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 541 hook_names_to_suppress = [c.get('name', '') for c in self.custom_hooks] | 545 hook_names_to_suppress = [c.get('name', '') for c in self.custom_hooks] |
| 542 for hook in local_scope.get('hooks', []): | 546 for hook in local_scope.get('hooks', []): |
| 543 if hook.get('name', '') not in hook_names_to_suppress: | 547 if hook.get('name', '') not in hook_names_to_suppress: |
| 544 hooks_to_run.append(hook) | 548 hooks_to_run.append(hook) |
| 545 | 549 |
| 546 # add the replacements and any additions | 550 # add the replacements and any additions |
| 547 for hook in self.custom_hooks: | 551 for hook in self.custom_hooks: |
| 548 if 'action' in hook: | 552 if 'action' in hook: |
| 549 hooks_to_run.append(hook) | 553 hooks_to_run.append(hook) |
| 550 | 554 |
| 555 self._pre_deps_hooks = [self.GetHookAction(hook, []) for hook in | |
| 556 local_scope.get('pre_deps_hooks', [])] | |
| 557 | |
| 551 self.add_dependencies_and_close(deps_to_add, hooks_to_run) | 558 self.add_dependencies_and_close(deps_to_add, hooks_to_run) |
| 552 logging.info('ParseDepsFile(%s) done' % self.name) | 559 logging.info('ParseDepsFile(%s) done' % self.name) |
| 553 | 560 |
| 554 def add_dependencies_and_close(self, deps_to_add, hooks): | 561 def add_dependencies_and_close(self, deps_to_add, hooks): |
| 555 """Adds the dependencies, hooks and mark the parsing as done.""" | 562 """Adds the dependencies, hooks and mark the parsing as done.""" |
| 556 for dep in deps_to_add: | 563 for dep in deps_to_add: |
| 557 if dep.verify_validity(): | 564 if dep.verify_validity(): |
| 558 self.add_dependency(dep) | 565 self.add_dependency(dep) |
| 559 self._mark_as_parsed(hooks) | 566 self._mark_as_parsed(hooks) |
| 560 | 567 |
| (...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 641 continue | 648 continue |
| 642 prefix = os.path.commonprefix( | 649 prefix = os.path.commonprefix( |
| 643 [self.root.root_dir.lower(), file_list[i].lower()]) | 650 [self.root.root_dir.lower(), file_list[i].lower()]) |
| 644 file_list[i] = file_list[i][len(prefix):] | 651 file_list[i] = file_list[i][len(prefix):] |
| 645 # Strip any leading path separators. | 652 # Strip any leading path separators. |
| 646 while file_list[i].startswith(('\\', '/')): | 653 while file_list[i].startswith(('\\', '/')): |
| 647 file_list[i] = file_list[i][1:] | 654 file_list[i] = file_list[i][1:] |
| 648 | 655 |
| 649 # Always parse the DEPS file. | 656 # Always parse the DEPS file. |
| 650 self.ParseDepsFile() | 657 self.ParseDepsFile() |
| 651 | |
| 652 self._run_is_done(file_list or [], parsed_url) | 658 self._run_is_done(file_list or [], parsed_url) |
| 659 if not options.nohooks: | |
| 660 self.RunPreDepsHooks() | |
|
iannucci
2013/10/07 22:40:09
So, the bots generally run with --nohooks. If we w
borenet
2013/10/08 13:53:19
This sounds fine to me, if adding another flag is
| |
| 653 | 661 |
| 654 if self.recursion_limit: | 662 if self.recursion_limit: |
| 655 # Parse the dependencies of this dependency. | 663 # Parse the dependencies of this dependency. |
| 656 for s in self.dependencies: | 664 for s in self.dependencies: |
| 657 work_queue.enqueue(s) | 665 work_queue.enqueue(s) |
| 658 | 666 |
| 659 if command == 'recurse': | 667 if command == 'recurse': |
| 660 if not isinstance(parsed_url, self.FileImpl): | 668 if not isinstance(parsed_url, self.FileImpl): |
| 661 # Skip file only checkout. | 669 # Skip file only checkout. |
| 662 scm = gclient_scm.GetScmName(parsed_url) | 670 scm = gclient_scm.GetScmName(parsed_url) |
| (...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 784 # failed. Users of this script may wish to treat hook action failures | 792 # failed. Users of this script may wish to treat hook action failures |
| 785 # differently from VC failures. | 793 # differently from VC failures. |
| 786 print >> sys.stderr, 'Error: %s' % str(e) | 794 print >> sys.stderr, 'Error: %s' % str(e) |
| 787 sys.exit(2) | 795 sys.exit(2) |
| 788 finally: | 796 finally: |
| 789 elapsed_time = time.time() - start_time | 797 elapsed_time = time.time() - start_time |
| 790 if elapsed_time > 10: | 798 if elapsed_time > 10: |
| 791 print "Hook '%s' took %.2f secs" % ( | 799 print "Hook '%s' took %.2f secs" % ( |
| 792 gclient_utils.CommandToStr(hook), elapsed_time) | 800 gclient_utils.CommandToStr(hook), elapsed_time) |
| 793 | 801 |
| 802 def RunPreDepsHooks(self): | |
| 803 assert self.processed | |
| 804 assert self.deps_parsed | |
| 805 assert not self.pre_deps_hooks_ran | |
| 806 assert not self.hooks_ran | |
| 807 for s in self.dependencies: | |
| 808 assert not s.processed | |
| 809 self._pre_deps_hooks_ran = True | |
| 810 for hook in self.pre_deps_hooks: | |
| 811 try: | |
| 812 start_time = time.time() | |
| 813 gclient_utils.CheckCallAndFilterAndHeader( | |
| 814 hook, cwd=self.root.root_dir, always=True) | |
| 815 except (gclient_utils.Error, subprocess2.CalledProcessError), e: | |
| 816 # Use a discrete exit status code of 2 to indicate that a hook action | |
| 817 # failed. Users of this script may wish to treat hook action failures | |
| 818 # differently from VC failures. | |
| 819 print >> sys.stderr, 'Error: %s' % str(e) | |
| 820 sys.exit(2) | |
| 821 finally: | |
| 822 elapsed_time = time.time() - start_time | |
| 823 if elapsed_time > 10: | |
| 824 print "Hook '%s' took %.2f secs" % ( | |
| 825 gclient_utils.CommandToStr(hook), elapsed_time) | |
| 826 | |
| 827 | |
| 794 def subtree(self, include_all): | 828 def subtree(self, include_all): |
| 795 """Breadth first recursion excluding root node.""" | 829 """Breadth first recursion excluding root node.""" |
| 796 dependencies = self.dependencies | 830 dependencies = self.dependencies |
| 797 for d in dependencies: | 831 for d in dependencies: |
| 798 if d.should_process or include_all: | 832 if d.should_process or include_all: |
| 799 yield d | 833 yield d |
| 800 for d in dependencies: | 834 for d in dependencies: |
| 801 for i in d.subtree(include_all): | 835 for i in d.subtree(include_all): |
| 802 yield i | 836 yield i |
| 803 | 837 |
| (...skipping 19 matching lines...) Expand all Loading... | |
| 823 def dependencies(self): | 857 def dependencies(self): |
| 824 return tuple(self._dependencies) | 858 return tuple(self._dependencies) |
| 825 | 859 |
| 826 @property | 860 @property |
| 827 @gclient_utils.lockedmethod | 861 @gclient_utils.lockedmethod |
| 828 def deps_hooks(self): | 862 def deps_hooks(self): |
| 829 return tuple(self._deps_hooks) | 863 return tuple(self._deps_hooks) |
| 830 | 864 |
| 831 @property | 865 @property |
| 832 @gclient_utils.lockedmethod | 866 @gclient_utils.lockedmethod |
| 867 def pre_deps_hooks(self): | |
| 868 return tuple(self._pre_deps_hooks) | |
| 869 | |
| 870 @property | |
| 871 @gclient_utils.lockedmethod | |
| 833 def parsed_url(self): | 872 def parsed_url(self): |
| 834 return self._parsed_url | 873 return self._parsed_url |
| 835 | 874 |
| 836 @property | 875 @property |
| 837 @gclient_utils.lockedmethod | 876 @gclient_utils.lockedmethod |
| 838 def deps_parsed(self): | 877 def deps_parsed(self): |
| 839 """This is purely for debugging purposes. It's not used anywhere.""" | 878 """This is purely for debugging purposes. It's not used anywhere.""" |
| 840 return self._deps_parsed | 879 return self._deps_parsed |
| 841 | 880 |
| 842 @property | 881 @property |
| 843 @gclient_utils.lockedmethod | 882 @gclient_utils.lockedmethod |
| 844 def processed(self): | 883 def processed(self): |
| 845 return self._processed | 884 return self._processed |
| 846 | 885 |
| 847 @property | 886 @property |
| 848 @gclient_utils.lockedmethod | 887 @gclient_utils.lockedmethod |
| 888 def pre_deps_hooks_ran(self): | |
| 889 return self._pre_deps_hooks_ran | |
| 890 | |
| 891 @property | |
| 892 @gclient_utils.lockedmethod | |
| 849 def hooks_ran(self): | 893 def hooks_ran(self): |
| 850 return self._hooks_ran | 894 return self._hooks_ran |
| 851 | 895 |
| 852 @property | 896 @property |
| 853 @gclient_utils.lockedmethod | 897 @gclient_utils.lockedmethod |
| 854 def file_list(self): | 898 def file_list(self): |
| 855 return tuple(self._file_list) | 899 return tuple(self._file_list) |
| 856 | 900 |
| 857 @property | 901 @property |
| 858 def used_scm(self): | 902 def used_scm(self): |
| (...skipping 974 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1833 raise | 1877 raise |
| 1834 except (gclient_utils.Error, subprocess2.CalledProcessError), e: | 1878 except (gclient_utils.Error, subprocess2.CalledProcessError), e: |
| 1835 print >> sys.stderr, 'Error: %s' % str(e) | 1879 print >> sys.stderr, 'Error: %s' % str(e) |
| 1836 return 1 | 1880 return 1 |
| 1837 | 1881 |
| 1838 | 1882 |
| 1839 if '__main__' == __name__: | 1883 if '__main__' == __name__: |
| 1840 sys.exit(Main(sys.argv[1:])) | 1884 sys.exit(Main(sys.argv[1:])) |
| 1841 | 1885 |
| 1842 # vim: ts=2:sw=2:tw=80:et: | 1886 # vim: ts=2:sw=2:tw=80:et: |
| OLD | NEW |