Index: gclient.py |
diff --git a/gclient.py b/gclient.py |
index 749003fa8d59271146e61a8ac00b5c3a933434d5..c5e4979cd58fee60a08d38adfe5da533eaa525d8 100755 |
--- a/gclient.py |
+++ b/gclient.py |
@@ -55,6 +55,11 @@ |
# "action": ["python", "src/build/gyp_chromium"]}, |
# ] |
# |
+# Pre-DEPS Hooks |
+# DEPS files may optionally contain a list named "pre_deps_hooks". These are |
+# the same as normal hooks, except that they run before the DEPS are |
+# processed. Pre-DEPS hooks always run unless the --noprehooks flag is used. |
+# |
# Specifying a target OS |
# An optional key named "target_os" may be added to a gclient file to specify |
# one or more additional operating systems that should be considered when |
@@ -286,6 +291,8 @@ class Dependency(gclient_utils.WorkItem, DependencySettings): |
# This is in both .gclient and DEPS files: |
self._deps_hooks = [] |
+ self._pre_deps_hooks = [] |
+ |
# Calculates properties: |
self._parsed_url = None |
self._dependencies = [] |
@@ -297,6 +304,8 @@ class Dependency(gclient_utils.WorkItem, DependencySettings): |
self._deps_parsed = False |
# This dependency has been processed, i.e. checked out |
self._processed = False |
+ # This dependency had its pre-DEPS hooks run |
+ self._pre_deps_hooks_ran = False |
# This dependency had its hook run |
self._hooks_ran = False |
# This is the scm used to checkout self.url. It may be used by dependencies |
@@ -548,6 +557,9 @@ class Dependency(gclient_utils.WorkItem, DependencySettings): |
if 'action' in hook: |
hooks_to_run.append(hook) |
+ self._pre_deps_hooks = [self.GetHookAction(hook, []) for hook in |
+ local_scope.get('pre_deps_hooks', [])] |
+ |
self.add_dependencies_and_close(deps_to_add, hooks_to_run) |
logging.info('ParseDepsFile(%s) done' % self.name) |
@@ -648,8 +660,9 @@ class Dependency(gclient_utils.WorkItem, DependencySettings): |
# Always parse the DEPS file. |
self.ParseDepsFile() |
- |
self._run_is_done(file_list or [], parsed_url) |
+ if not options.noprehooks: |
+ self.RunPreDepsHooks() |
if self.recursion_limit: |
# Parse the dependencies of this dependency. |
@@ -791,6 +804,32 @@ class Dependency(gclient_utils.WorkItem, DependencySettings): |
print "Hook '%s' took %.2f secs" % ( |
gclient_utils.CommandToStr(hook), elapsed_time) |
+ def RunPreDepsHooks(self): |
+ assert self.processed |
+ assert self.deps_parsed |
+ assert not self.pre_deps_hooks_ran |
+ assert not self.hooks_ran |
+ for s in self.dependencies: |
+ assert not s.processed |
+ self._pre_deps_hooks_ran = True |
+ for hook in self.pre_deps_hooks: |
+ try: |
+ start_time = time.time() |
+ gclient_utils.CheckCallAndFilterAndHeader( |
+ hook, cwd=self.root.root_dir, always=True) |
+ except (gclient_utils.Error, subprocess2.CalledProcessError), e: |
+ # Use a discrete exit status code of 2 to indicate that a hook action |
+ # failed. Users of this script may wish to treat hook action failures |
+ # differently from VC failures. |
+ print >> sys.stderr, 'Error: %s' % str(e) |
+ sys.exit(2) |
+ finally: |
+ elapsed_time = time.time() - start_time |
+ if elapsed_time > 10: |
+ print "Hook '%s' took %.2f secs" % ( |
+ gclient_utils.CommandToStr(hook), elapsed_time) |
+ |
+ |
def subtree(self, include_all): |
"""Breadth first recursion excluding root node.""" |
dependencies = self.dependencies |
@@ -830,6 +869,11 @@ class Dependency(gclient_utils.WorkItem, DependencySettings): |
@property |
@gclient_utils.lockedmethod |
+ def pre_deps_hooks(self): |
+ return tuple(self._pre_deps_hooks) |
+ |
+ @property |
+ @gclient_utils.lockedmethod |
def parsed_url(self): |
return self._parsed_url |
@@ -846,6 +890,11 @@ class Dependency(gclient_utils.WorkItem, DependencySettings): |
@property |
@gclient_utils.lockedmethod |
+ def pre_deps_hooks_ran(self): |
+ return self._pre_deps_hooks_ran |
+ |
+ @property |
+ @gclient_utils.lockedmethod |
def hooks_ran(self): |
return self._hooks_ran |
@@ -1555,6 +1604,8 @@ def CMDsync(parser, args): |
help='force update even for unchanged modules') |
parser.add_option('-n', '--nohooks', action='store_true', |
help='don\'t run hooks after the update is complete') |
+ parser.add_option('-p', '--noprehooks', action='store_true', |
+ help='don\'t run pre-DEPS hooks') |
parser.add_option('-r', '--revision', action='append', |
dest='revisions', metavar='REV', default=[], |
help='Enforces revision/hash for the solutions with the ' |
@@ -1660,6 +1711,8 @@ def CMDrevert(parser, args): |
'references') |
parser.add_option('-n', '--nohooks', action='store_true', |
help='don\'t run hooks after the revert is complete') |
+ parser.add_option('-p', '--noprehooks', action='store_true', |
+ help='don\'t run pre-DEPS hooks') |
parser.add_option('--upstream', action='store_true', |
help='Make repo state match upstream branch.') |
(options, args) = parser.parse_args(args) |
@@ -1793,6 +1846,8 @@ class OptionParser(optparse.OptionParser): |
options.head = None |
if not hasattr(options, 'nohooks'): |
options.nohooks = True |
+ if not hasattr(options, 'noprehooks'): |
+ options.noprehooks = False |
iannucci
2013/10/09 16:41:24
Hm... I don't think any of these are really necess
borenet
2013/10/10 18:24:29
If I understand correctly, these are defaults for
|
if not hasattr(options, 'deps_os'): |
options.deps_os = None |
if not hasattr(options, 'manually_grab_svn_rev'): |