Index: gclient.py |
diff --git a/gclient.py b/gclient.py |
index 3e8a7962290a3b63832adc2ad3469ae7ad2d6a53..6676a46d3d2cedc14de3fbffc9aa60cfcb1a57ec 100755 |
--- a/gclient.py |
+++ b/gclient.py |
@@ -761,7 +761,7 @@ class Dependency(gclient_utils.WorkItem, DependencySettings): |
# When running runhooks, there's no need to consult the SCM. |
# All known hooks are expected to run unconditionally regardless of working |
# copy state, so skip the SCM status check. |
- run_scm = command not in ('runhooks', 'recurse', None) |
+ run_scm = command not in ('flatten', 'runhooks', 'recurse', None) |
parsed_url = self.LateOverride(self.url) |
file_list = [] if not options.nohooks else None |
revision_override = revision_overrides.pop(self.name, None) |
@@ -1655,6 +1655,98 @@ def CMDrecurse(parser, args): |
progress=not options.no_progress) |
+@subcommand.usage('[command] [--verify] [args ...]') |
+def CMDflatten(parser, args): |
+ """Flattens the solutions into a single DEPS file.""" |
+ # Stop parsing at the first non-arg so that these go through to the command |
+ parser.add_option('--verify', action='store_true', |
+ help='Verifies that each dependencies is pinned at a ' |
+ 'specific revision.') |
agable
2016/11/02 17:53:26
And that the .gclient_entries file matches what's
Dirk Pranke
2016/11/02 19:01:22
I'm not sure how useful that is, but I'm not actua
Michael Moss
2016/11/02 20:50:30
Assuming --verify ends up using gitiles requests,
|
+ options, args = parser.parse_args(args) |
+ root_and_entries = gclient_utils.GetGClientRootAndEntries() |
+ if not root_and_entries: |
+ print( |
+ 'You need to run gclient sync at least once to use \'flatten\'.\n' |
+ 'This is because .gclient_entries needs to exist and be up to date.', |
+ file=sys.stderr) |
+ return 1 |
+ |
+ options.nohooks = True |
+ client = GClient.LoadCurrentConfig(options) |
+ res = client.RunOnDeps('flatten', args, ignore_requirements=True, |
+ progress=False) |
+ if res: |
+ return res |
+ |
+ deps = {} |
+ hooks = [] |
+ unpinned_deps = {} |
+ |
+ for solution in client.dependencies: |
+ _FlattenSolution(solution, deps, hooks, unpinned_deps) |
+ |
+ if options.verify and unpinned_deps: |
+ for name in unpinned_deps: |
+ print("'%s' is not pinned to a Git revision" % name) |
+ return 1 |
+ |
+ flattened_deps = ('%s\n%s\n' % |
+ (_DepsToVarString(deps), _HooksToVarString(hooks))) |
+ print(flattened_deps) |
+ return 0 |
+ |
+ |
+def _FlattenSolution(solution, deps, hooks, unpinned_deps): |
+ _AddDep(solution, deps, unpinned_deps) |
+ for dep in solution.dependencies: |
+ _FlattenDep(dep, deps, hooks, unpinned_deps) |
+ hooks.extend(solution.deps_hooks) |
+ |
+ |
+def _FlattenDep(dep, deps, hooks, unpinned_deps): |
+ _AddDep(dep, deps, unpinned_deps) |
+ for recurse_dep_name in sorted(dep.recursedeps or []): |
+ for sub_dep in dep.dependencies: |
+ if recurse_dep_name == dep.name: |
+ _FlattenDep(sub_dep, deps, hooks, unpinned_deps) |
+ break |
+ hooks.extend(dep.deps_hooks) |
+ |
+ |
+def _AddDep(dep, deps, unpinned_deps): |
+ assert dep.name not in deps |
+ deps[dep.name] = dep.url |
+ _, revision = gclient_utils.SplitUrlRevision(dep.url) |
+ if not revision or not gclient_utils.IsGitSha(revision): |
+ unpinned_deps[dep.name] = dep.url |
+ |
+ |
+def _DepsToVarString(deps): |
+ s = "deps = {\n" |
+ for name in sorted(deps): |
+ s += " '%s': '%s',\n" % (name, deps[name]) |
+ s += "}\n" |
+ return s |
+ |
+ |
+def _HooksToVarString(hooks): |
+ s = "hooks = [\n" |
+ for hook in hooks: |
+ s += " {\n" |
agable
2016/11/02 17:53:26
Make this a triple-quoted multi-line template stri
Dirk Pranke
2016/11/02 19:01:22
I originally didn't do this because I thought hand
|
+ if 'name' in hook: |
+ s += " 'name': '%s',\n" % hook['name'] |
+ if 'pattern' in hook: |
+ s += " 'pattern': '%s',\n" % hook['pattern'] |
+ s += " 'action': [\n" |
+ s += " " |
+ s += ",\n ".join("'%s'" % arg for arg in hook['action']) |
+ s += ",\n" |
+ s += " ],\n" |
+ s += " },\n" |
+ s += "}" |
+ return s |
+ |
+ |
@subcommand.usage('[args ...]') |
def CMDfetch(parser, args): |
"""Fetches upstream commits for all modules. |