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

Side by Side Diff: gclient.py

Issue 25322002: Add support in gclient for pre-DEPS hooks (Closed) Base URL: https://chromium.googlesource.com/chromium/tools/depot_tools.git@master
Patch Set: Add asserts, tests Created 7 years, 2 months 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 | testing_support/fake_repos.py » ('j') | 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 (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
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
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
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
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
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
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:
OLDNEW
« no previous file with comments | « no previous file | testing_support/fake_repos.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698