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

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: Revert "Add support in gclient for pre-DEPS hooks" Created 7 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 | 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 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
48 # 48 #
49 # Example: 49 # Example:
50 # hooks = [ 50 # hooks = [
51 # { "pattern": "\\.(gif|jpe?g|pr0n|png)$", 51 # { "pattern": "\\.(gif|jpe?g|pr0n|png)$",
52 # "action": ["python", "image_indexer.py", "--all"]}, 52 # "action": ["python", "image_indexer.py", "--all"]},
53 # { "pattern": ".", 53 # { "pattern": ".",
54 # "name": "gyp", 54 # "name": "gyp",
55 # "action": ["python", "src/build/gyp_chromium"]}, 55 # "action": ["python", "src/build/gyp_chromium"]},
56 # ] 56 # ]
57 # 57 #
58 # Pre-DEPS Hooks
59 # DEPS files may optionally contain a list named "pre_deps_hooks". These are
60 # the same as normal hooks, except that they run before the DEPS are
61 # processed. Pre-DEPS run with "sync" and "revert" unless the --noprehooks
62 # flag is used.
63 #
64 # Specifying a target OS 58 # Specifying a target OS
65 # An optional key named "target_os" may be added to a gclient file to specify 59 # An optional key named "target_os" may be added to a gclient file to specify
66 # one or more additional operating systems that should be considered when 60 # one or more additional operating systems that should be considered when
67 # processing the deps_os dict of a DEPS file. 61 # processing the deps_os dict of a DEPS file.
68 # 62 #
69 # Example: 63 # Example:
70 # target_os = [ "android" ] 64 # target_os = [ "android" ]
71 # 65 #
72 # If the "target_os_only" key is also present and true, then *only* the 66 # If the "target_os_only" key is also present and true, then *only* the
73 # operating systems listed in "target_os" will be used. 67 # operating systems listed in "target_os" will be used.
(...skipping 211 matching lines...) Expand 10 before | Expand all | Expand 10 after
285 def __init__(self, parent, name, url, safesync_url, managed, custom_deps, 279 def __init__(self, parent, name, url, safesync_url, managed, custom_deps,
286 custom_vars, custom_hooks, deps_file, should_process): 280 custom_vars, custom_hooks, deps_file, should_process):
287 gclient_utils.WorkItem.__init__(self, name) 281 gclient_utils.WorkItem.__init__(self, name)
288 DependencySettings.__init__( 282 DependencySettings.__init__(
289 self, parent, url, safesync_url, managed, custom_deps, custom_vars, 283 self, parent, url, safesync_url, managed, custom_deps, custom_vars,
290 custom_hooks, deps_file, should_process) 284 custom_hooks, deps_file, should_process)
291 285
292 # This is in both .gclient and DEPS files: 286 # This is in both .gclient and DEPS files:
293 self._deps_hooks = [] 287 self._deps_hooks = []
294 288
295 self._pre_deps_hooks = []
296
297 # Calculates properties: 289 # Calculates properties:
298 self._parsed_url = None 290 self._parsed_url = None
299 self._dependencies = [] 291 self._dependencies = []
300 # A cache of the files affected by the current operation, necessary for 292 # A cache of the files affected by the current operation, necessary for
301 # hooks. 293 # hooks.
302 self._file_list = [] 294 self._file_list = []
303 # If it is not set to True, the dependency wasn't processed for its child 295 # If it is not set to True, the dependency wasn't processed for its child
304 # dependency, i.e. its DEPS wasn't read. 296 # dependency, i.e. its DEPS wasn't read.
305 self._deps_parsed = False 297 self._deps_parsed = False
306 # This dependency has been processed, i.e. checked out 298 # This dependency has been processed, i.e. checked out
307 self._processed = False 299 self._processed = False
308 # This dependency had its pre-DEPS hooks run
309 self._pre_deps_hooks_ran = False
310 # This dependency had its hook run 300 # This dependency had its hook run
311 self._hooks_ran = False 301 self._hooks_ran = False
312 # This is the scm used to checkout self.url. It may be used by dependencies 302 # This is the scm used to checkout self.url. It may be used by dependencies
313 # to get the datetime of the revision we checked out. 303 # to get the datetime of the revision we checked out.
314 self._used_scm = None 304 self._used_scm = None
315 # The actual revision we ended up getting, or None if that information is 305 # The actual revision we ended up getting, or None if that information is
316 # unavailable 306 # unavailable
317 self._got_revision = None 307 self._got_revision = None
318 308
319 if not self.name and self.parent: 309 if not self.name and self.parent:
(...skipping 231 matching lines...) Expand 10 before | Expand all | Expand 10 after
551 hook_names_to_suppress = [c.get('name', '') for c in self.custom_hooks] 541 hook_names_to_suppress = [c.get('name', '') for c in self.custom_hooks]
552 for hook in local_scope.get('hooks', []): 542 for hook in local_scope.get('hooks', []):
553 if hook.get('name', '') not in hook_names_to_suppress: 543 if hook.get('name', '') not in hook_names_to_suppress:
554 hooks_to_run.append(hook) 544 hooks_to_run.append(hook)
555 545
556 # add the replacements and any additions 546 # add the replacements and any additions
557 for hook in self.custom_hooks: 547 for hook in self.custom_hooks:
558 if 'action' in hook: 548 if 'action' in hook:
559 hooks_to_run.append(hook) 549 hooks_to_run.append(hook)
560 550
561 self._pre_deps_hooks = [self.GetHookAction(hook, []) for hook in
562 local_scope.get('pre_deps_hooks', [])]
563
564 self.add_dependencies_and_close(deps_to_add, hooks_to_run) 551 self.add_dependencies_and_close(deps_to_add, hooks_to_run)
565 logging.info('ParseDepsFile(%s) done' % self.name) 552 logging.info('ParseDepsFile(%s) done' % self.name)
566 553
567 def add_dependencies_and_close(self, deps_to_add, hooks): 554 def add_dependencies_and_close(self, deps_to_add, hooks):
568 """Adds the dependencies, hooks and mark the parsing as done.""" 555 """Adds the dependencies, hooks and mark the parsing as done."""
569 for dep in deps_to_add: 556 for dep in deps_to_add:
570 if dep.verify_validity(): 557 if dep.verify_validity():
571 self.add_dependency(dep) 558 self.add_dependency(dep)
572 self._mark_as_parsed(hooks) 559 self._mark_as_parsed(hooks)
573 560
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after
654 continue 641 continue
655 prefix = os.path.commonprefix( 642 prefix = os.path.commonprefix(
656 [self.root.root_dir.lower(), file_list[i].lower()]) 643 [self.root.root_dir.lower(), file_list[i].lower()])
657 file_list[i] = file_list[i][len(prefix):] 644 file_list[i] = file_list[i][len(prefix):]
658 # Strip any leading path separators. 645 # Strip any leading path separators.
659 while file_list[i].startswith(('\\', '/')): 646 while file_list[i].startswith(('\\', '/')):
660 file_list[i] = file_list[i][1:] 647 file_list[i] = file_list[i][1:]
661 648
662 # Always parse the DEPS file. 649 # Always parse the DEPS file.
663 self.ParseDepsFile() 650 self.ParseDepsFile()
651
664 self._run_is_done(file_list or [], parsed_url) 652 self._run_is_done(file_list or [], parsed_url)
665 if command in ('update', 'revert') and not options.noprehooks:
666 self.RunPreDepsHooks()
667 653
668 if self.recursion_limit: 654 if self.recursion_limit:
669 # Parse the dependencies of this dependency. 655 # Parse the dependencies of this dependency.
670 for s in self.dependencies: 656 for s in self.dependencies:
671 work_queue.enqueue(s) 657 work_queue.enqueue(s)
672 658
673 if command == 'recurse': 659 if command == 'recurse':
674 if not isinstance(parsed_url, self.FileImpl): 660 if not isinstance(parsed_url, self.FileImpl):
675 # Skip file only checkout. 661 # Skip file only checkout.
676 scm = gclient_scm.GetScmName(parsed_url) 662 scm = gclient_scm.GetScmName(parsed_url)
(...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after
798 # failed. Users of this script may wish to treat hook action failures 784 # failed. Users of this script may wish to treat hook action failures
799 # differently from VC failures. 785 # differently from VC failures.
800 print >> sys.stderr, 'Error: %s' % str(e) 786 print >> sys.stderr, 'Error: %s' % str(e)
801 sys.exit(2) 787 sys.exit(2)
802 finally: 788 finally:
803 elapsed_time = time.time() - start_time 789 elapsed_time = time.time() - start_time
804 if elapsed_time > 10: 790 if elapsed_time > 10:
805 print "Hook '%s' took %.2f secs" % ( 791 print "Hook '%s' took %.2f secs" % (
806 gclient_utils.CommandToStr(hook), elapsed_time) 792 gclient_utils.CommandToStr(hook), elapsed_time)
807 793
808 def RunPreDepsHooks(self):
809 assert self.processed
810 assert self.deps_parsed
811 assert not self.pre_deps_hooks_ran
812 assert not self.hooks_ran
813 for s in self.dependencies:
814 assert not s.processed
815 self._pre_deps_hooks_ran = True
816 for hook in self.pre_deps_hooks:
817 try:
818 start_time = time.time()
819 gclient_utils.CheckCallAndFilterAndHeader(
820 hook, cwd=self.root.root_dir, always=True)
821 except (gclient_utils.Error, subprocess2.CalledProcessError), e:
822 # Use a discrete exit status code of 2 to indicate that a hook action
823 # failed. Users of this script may wish to treat hook action failures
824 # differently from VC failures.
825 print >> sys.stderr, 'Error: %s' % str(e)
826 sys.exit(2)
827 finally:
828 elapsed_time = time.time() - start_time
829 if elapsed_time > 10:
830 print "Hook '%s' took %.2f secs" % (
831 gclient_utils.CommandToStr(hook), elapsed_time)
832
833
834 def subtree(self, include_all): 794 def subtree(self, include_all):
835 """Breadth first recursion excluding root node.""" 795 """Breadth first recursion excluding root node."""
836 dependencies = self.dependencies 796 dependencies = self.dependencies
837 for d in dependencies: 797 for d in dependencies:
838 if d.should_process or include_all: 798 if d.should_process or include_all:
839 yield d 799 yield d
840 for d in dependencies: 800 for d in dependencies:
841 for i in d.subtree(include_all): 801 for i in d.subtree(include_all):
842 yield i 802 yield i
843 803
(...skipping 19 matching lines...) Expand all
863 def dependencies(self): 823 def dependencies(self):
864 return tuple(self._dependencies) 824 return tuple(self._dependencies)
865 825
866 @property 826 @property
867 @gclient_utils.lockedmethod 827 @gclient_utils.lockedmethod
868 def deps_hooks(self): 828 def deps_hooks(self):
869 return tuple(self._deps_hooks) 829 return tuple(self._deps_hooks)
870 830
871 @property 831 @property
872 @gclient_utils.lockedmethod 832 @gclient_utils.lockedmethod
873 def pre_deps_hooks(self):
874 return tuple(self._pre_deps_hooks)
875
876 @property
877 @gclient_utils.lockedmethod
878 def parsed_url(self): 833 def parsed_url(self):
879 return self._parsed_url 834 return self._parsed_url
880 835
881 @property 836 @property
882 @gclient_utils.lockedmethod 837 @gclient_utils.lockedmethod
883 def deps_parsed(self): 838 def deps_parsed(self):
884 """This is purely for debugging purposes. It's not used anywhere.""" 839 """This is purely for debugging purposes. It's not used anywhere."""
885 return self._deps_parsed 840 return self._deps_parsed
886 841
887 @property 842 @property
888 @gclient_utils.lockedmethod 843 @gclient_utils.lockedmethod
889 def processed(self): 844 def processed(self):
890 return self._processed 845 return self._processed
891 846
892 @property 847 @property
893 @gclient_utils.lockedmethod 848 @gclient_utils.lockedmethod
894 def pre_deps_hooks_ran(self):
895 return self._pre_deps_hooks_ran
896
897 @property
898 @gclient_utils.lockedmethod
899 def hooks_ran(self): 849 def hooks_ran(self):
900 return self._hooks_ran 850 return self._hooks_ran
901 851
902 @property 852 @property
903 @gclient_utils.lockedmethod 853 @gclient_utils.lockedmethod
904 def file_list(self): 854 def file_list(self):
905 return tuple(self._file_list) 855 return tuple(self._file_list)
906 856
907 @property 857 @property
908 def used_scm(self): 858 def used_scm(self):
(...skipping 689 matching lines...) Expand 10 before | Expand all | Expand 10 after
1598 } 1548 }
1599 } 1549 }
1600 } 1550 }
1601 """) 1551 """)
1602 def CMDsync(parser, args): 1552 def CMDsync(parser, args):
1603 """Checkout/update all modules.""" 1553 """Checkout/update all modules."""
1604 parser.add_option('-f', '--force', action='store_true', 1554 parser.add_option('-f', '--force', action='store_true',
1605 help='force update even for unchanged modules') 1555 help='force update even for unchanged modules')
1606 parser.add_option('-n', '--nohooks', action='store_true', 1556 parser.add_option('-n', '--nohooks', action='store_true',
1607 help='don\'t run hooks after the update is complete') 1557 help='don\'t run hooks after the update is complete')
1608 parser.add_option('-p', '--noprehooks', action='store_true',
1609 help='don\'t run pre-DEPS hooks', default=False)
1610 parser.add_option('-r', '--revision', action='append', 1558 parser.add_option('-r', '--revision', action='append',
1611 dest='revisions', metavar='REV', default=[], 1559 dest='revisions', metavar='REV', default=[],
1612 help='Enforces revision/hash for the solutions with the ' 1560 help='Enforces revision/hash for the solutions with the '
1613 'format src@rev. The src@ part is optional and can be ' 1561 'format src@rev. The src@ part is optional and can be '
1614 'skipped. -r can be used multiple times when .gclient ' 1562 'skipped. -r can be used multiple times when .gclient '
1615 'has multiple solutions configured and will work even ' 1563 'has multiple solutions configured and will work even '
1616 'if the src@ part is skipped. Note that specifying ' 1564 'if the src@ part is skipped. Note that specifying '
1617 '--revision means your safesync_url gets ignored.') 1565 '--revision means your safesync_url gets ignored.')
1618 parser.add_option('--with_branch_heads', action='store_true', 1566 parser.add_option('--with_branch_heads', action='store_true',
1619 help='Clone git "branch_heads" refspecs in addition to ' 1567 help='Clone git "branch_heads" refspecs in addition to '
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after
1705 """Reverts all modifications in every dependencies. 1653 """Reverts all modifications in every dependencies.
1706 1654
1707 That's the nuclear option to get back to a 'clean' state. It removes anything 1655 That's the nuclear option to get back to a 'clean' state. It removes anything
1708 that shows up in svn status.""" 1656 that shows up in svn status."""
1709 parser.add_option('--deps', dest='deps_os', metavar='OS_LIST', 1657 parser.add_option('--deps', dest='deps_os', metavar='OS_LIST',
1710 help='override deps for the specified (comma-separated) ' 1658 help='override deps for the specified (comma-separated) '
1711 'platform(s); \'all\' will process all deps_os ' 1659 'platform(s); \'all\' will process all deps_os '
1712 'references') 1660 'references')
1713 parser.add_option('-n', '--nohooks', action='store_true', 1661 parser.add_option('-n', '--nohooks', action='store_true',
1714 help='don\'t run hooks after the revert is complete') 1662 help='don\'t run hooks after the revert is complete')
1715 parser.add_option('-p', '--noprehooks', action='store_true',
1716 help='don\'t run pre-DEPS hooks', default=False)
1717 parser.add_option('--upstream', action='store_true', 1663 parser.add_option('--upstream', action='store_true',
1718 help='Make repo state match upstream branch.') 1664 help='Make repo state match upstream branch.')
1719 (options, args) = parser.parse_args(args) 1665 (options, args) = parser.parse_args(args)
1720 # --force is implied. 1666 # --force is implied.
1721 options.force = True 1667 options.force = True
1722 options.reset = False 1668 options.reset = False
1723 options.delete_unversioned_trees = False 1669 options.delete_unversioned_trees = False
1724 client = GClient.LoadCurrentConfig(options) 1670 client = GClient.LoadCurrentConfig(options)
1725 if not client: 1671 if not client:
1726 raise gclient_utils.Error('client not configured; see \'gclient config\'') 1672 raise gclient_utils.Error('client not configured; see \'gclient config\'')
(...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after
1840 self.error('--jobs must be 1 or higher') 1786 self.error('--jobs must be 1 or higher')
1841 1787
1842 # These hacks need to die. 1788 # These hacks need to die.
1843 if not hasattr(options, 'revisions'): 1789 if not hasattr(options, 'revisions'):
1844 # GClient.RunOnDeps expects it even if not applicable. 1790 # GClient.RunOnDeps expects it even if not applicable.
1845 options.revisions = [] 1791 options.revisions = []
1846 if not hasattr(options, 'head'): 1792 if not hasattr(options, 'head'):
1847 options.head = None 1793 options.head = None
1848 if not hasattr(options, 'nohooks'): 1794 if not hasattr(options, 'nohooks'):
1849 options.nohooks = True 1795 options.nohooks = True
1850 if not hasattr(options, 'noprehooks'):
1851 options.noprehooks = True
1852 if not hasattr(options, 'deps_os'): 1796 if not hasattr(options, 'deps_os'):
1853 options.deps_os = None 1797 options.deps_os = None
1854 if not hasattr(options, 'manually_grab_svn_rev'): 1798 if not hasattr(options, 'manually_grab_svn_rev'):
1855 options.manually_grab_svn_rev = None 1799 options.manually_grab_svn_rev = None
1856 if not hasattr(options, 'force'): 1800 if not hasattr(options, 'force'):
1857 options.force = None 1801 options.force = None
1858 return (options, args) 1802 return (options, args)
1859 1803
1860 1804
1861 def disable_buffering(): 1805 def disable_buffering():
(...skipping 27 matching lines...) Expand all
1889 raise 1833 raise
1890 except (gclient_utils.Error, subprocess2.CalledProcessError), e: 1834 except (gclient_utils.Error, subprocess2.CalledProcessError), e:
1891 print >> sys.stderr, 'Error: %s' % str(e) 1835 print >> sys.stderr, 'Error: %s' % str(e)
1892 return 1 1836 return 1
1893 1837
1894 1838
1895 if '__main__' == __name__: 1839 if '__main__' == __name__:
1896 sys.exit(Main(sys.argv[1:])) 1840 sys.exit(Main(sys.argv[1:]))
1897 1841
1898 # vim: ts=2:sw=2:tw=80:et: 1842 # 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