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

Unified Diff: gclient.py

Issue 2917009: Reapply gclient.py refactor for the third time. (Closed)
Patch Set: Fix runhooks with hooks defined in From(File()) Created 10 years, 5 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « no previous file | gclient_utils.py » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: gclient.py
diff --git a/gclient.py b/gclient.py
index 788b96b92040054a207efb34c56b0cbd58a55a5d..42a6938dd0c287836f24459eda8b508a9cf95e93 100644
--- a/gclient.py
+++ b/gclient.py
@@ -49,9 +49,8 @@ Hooks
]
"""
-__version__ = "0.4.1"
+__version__ = "0.5"
-import errno
import logging
import optparse
import os
@@ -97,22 +96,6 @@ class GClientKeywords(object):
return 'From(%s, %s)' % (repr(self.module_name),
repr(self.sub_target_name))
- def GetUrl(self, target_name, sub_deps_base_url, root_dir, sub_deps):
- """Resolve the URL for this From entry."""
- sub_deps_target_name = target_name
- if self.sub_target_name:
- sub_deps_target_name = self.sub_target_name
- url = sub_deps[sub_deps_target_name]
- if url.startswith('/'):
- # If it's a relative URL, we need to resolve the URL relative to the
- # sub deps base URL.
- if not isinstance(sub_deps_base_url, basestring):
- sub_deps_base_url = sub_deps_base_url.GetPath()
- scm = gclient_scm.CreateSCM(sub_deps_base_url, root_dir,
- None)
- url = scm.FullUrlForRelativeUrl(url)
- return url
-
class FileImpl(object):
"""Used to implement the File('') syntax which lets you sync a single file
from a SVN repo."""
@@ -160,6 +143,7 @@ class Dependency(GClientKeywords):
self.parent = parent
self.name = name
self.url = url
+ self.parsed_url = None
# These 2 are only set in .gclient and not in DEPS files.
self.safesync_url = safesync_url
self.custom_vars = custom_vars or {}
@@ -167,12 +151,18 @@ class Dependency(GClientKeywords):
self.deps_hooks = []
self.dependencies = []
self.deps_file = deps_file or self.DEPS_FILE
+ # A cache of the files affected by the current operation, necessary for
+ # hooks.
+ self.file_list = []
self.deps_parsed = False
self.direct_reference = False
# Sanity checks
if not self.name and self.parent:
raise gclient_utils.Error('Dependency without name')
+ if self.name in [d.name for d in self.tree(False)]:
+ raise gclient_utils.Error('Dependency %s specified more than once' %
+ self.name)
if not isinstance(self.url,
(basestring, self.FromImpl, self.FileImpl, None.__class__)):
raise gclient_utils.Error('dependency url must be either a string, None, '
@@ -182,16 +172,67 @@ class Dependency(GClientKeywords):
raise gclient_utils.Error('deps_file name must not be a path, just a '
'filename. %s' % self.deps_file)
+ def LateOverride(self, url):
+ overriden_url = self.get_custom_deps(self.name, url)
+ if overriden_url != url:
+ self.parsed_url = overriden_url
+ logging.debug('%s, %s was overriden to %s' % (self.name, url,
+ self.parsed_url))
+ elif isinstance(url, self.FromImpl):
+ ref = [dep for dep in self.tree(True) if url.module_name == dep.name]
+ if not len(ref) == 1:
+ raise Exception('Failed to find one reference to %s. %s' % (
+ url.module_name, ref))
+ ref = ref[0]
+ sub_target = url.sub_target_name or url
+ # Make sure the referenced dependency DEPS file is loaded and file the
+ # inner referenced dependency.
+ ref.ParseDepsFile(False)
+ found_dep = None
+ for d in ref.dependencies:
+ if d.name == sub_target:
+ found_dep = d
+ break
+ if not found_dep:
+ raise Exception('Couldn\'t find %s in %s, referenced by %s' % (
+ sub_target, ref.name, self.name))
+ # Call LateOverride() again.
+ self.parsed_url = found_dep.LateOverride(found_dep.url)
+ logging.debug('%s, %s to %s' % (self.name, url, self.parsed_url))
+ elif isinstance(url, basestring):
+ parsed_url = urlparse.urlparse(url)
+ if not parsed_url[0]:
+ # A relative url. Fetch the real base.
+ path = parsed_url[2]
+ if not path.startswith('/'):
+ raise gclient_utils.Error(
+ 'relative DEPS entry \'%s\' must begin with a slash' % url)
+ # Create a scm just to query the full url.
+ parent_url = self.parent.parsed_url
+ if isinstance(parent_url, self.FileImpl):
+ parent_url = parent_url.file_location
+ scm = gclient_scm.CreateSCM(parent_url, self.root_dir(), None)
+ self.parsed_url = scm.FullUrlForRelativeUrl(url)
+ else:
+ self.parsed_url = url
+ logging.debug('%s, %s -> %s' % (self.name, url, self.parsed_url))
+ elif isinstance(url, self.FileImpl):
+ self.parsed_url = url
+ logging.debug('%s, %s -> %s (File)' % (self.name, url, self.parsed_url))
+ return self.parsed_url
+
def ParseDepsFile(self, direct_reference):
"""Parses the DEPS file for this dependency."""
if direct_reference:
# Maybe it was referenced earlier by a From() keyword but it's now
# directly referenced.
self.direct_reference = direct_reference
+ if self.deps_parsed:
+ return
self.deps_parsed = True
filepath = os.path.join(self.root_dir(), self.name, self.deps_file)
if not os.path.isfile(filepath):
- return {}
+ return
deps_content = gclient_utils.FileRead(filepath)
# Eval the content.
@@ -242,110 +283,105 @@ class Dependency(GClientKeywords):
# dependency local path.
rel_deps[os.path.normpath(os.path.join(self.name, d))] = url
deps = rel_deps
- # TODO(maruel): Add these dependencies into self.dependencies.
- return deps
-
- def _ParseAllDeps(self, solution_urls):
- """Parse the complete list of dependencies for the client.
-
- Args:
- solution_urls: A dict mapping module names (as relative paths) to URLs
- corresponding to the solutions specified by the client. This parameter
- is passed as an optimization.
-
- Returns:
- A dict mapping module names (as relative paths) to URLs corresponding
- to the entire set of dependencies to checkout for the given client.
-
- Raises:
- Error: If a dependency conflicts with another dependency or of a solution.
- """
- deps = {}
- for solution in self.dependencies:
- solution_deps = solution.ParseDepsFile(True)
-
- # If a line is in custom_deps, but not in the solution, we want to append
- # this line to the solution.
- for d in solution.custom_deps:
- if d not in solution_deps:
- solution_deps[d] = solution.custom_deps[d]
-
- for d in solution_deps:
- if d in solution.custom_deps:
- # Dependency is overriden.
- url = solution.custom_deps[d]
- if url is None:
- continue
- else:
- url = solution_deps[d]
- # if we have a From reference dependent on another solution, then
- # just skip the From reference. When we pull deps for the solution,
- # we will take care of this dependency.
- #
- # If multiple solutions all have the same From reference, then we
- # should only add one to our list of dependencies.
- if isinstance(url, self.FromImpl):
- if url.module_name in solution_urls:
- # Already parsed.
- continue
- if d in deps and type(deps[d]) != str:
- if url.module_name == deps[d].module_name:
- continue
- elif isinstance(url, str):
- parsed_url = urlparse.urlparse(url)
- scheme = parsed_url[0]
- if not scheme:
- # A relative url. Fetch the real base.
- path = parsed_url[2]
- if path[0] != "/":
- raise gclient_utils.Error(
- "relative DEPS entry \"%s\" must begin with a slash" % d)
- # Create a scm just to query the full url.
- scm = gclient_scm.CreateSCM(solution.url, self.root_dir(),
- None)
- url = scm.FullUrlForRelativeUrl(url)
- if d in deps and deps[d] != url:
- raise gclient_utils.Error(
- "Solutions have conflicting versions of dependency \"%s\"" % d)
- if d in solution_urls and solution_urls[d] != url:
- raise gclient_utils.Error(
- "Dependency \"%s\" conflicts with specified solution" % d)
- # Grab the dependency.
- deps[d] = url
- return deps
-
- def _RunHooks(self, command, file_list, is_using_git):
- """Evaluates all hooks, running actions as needed.
- """
- # Hooks only run for these command types.
- if not command in ('update', 'revert', 'runhooks'):
- return
-
- # Hooks only run when --nohooks is not specified
- if self._options.nohooks:
- return
-
- # Get any hooks from the .gclient file.
- hooks = self.deps_hooks[:]
- # Add any hooks found in DEPS files.
- for d in self.dependencies:
- hooks.extend(d.deps_hooks)
+ # Convert the deps into real Dependency.
+ for name, url in deps.iteritems():
+ if name in [s.name for s in self.dependencies]:
+ raise
+ self.dependencies.append(Dependency(self, name, url))
+ # Sort by name.
+ self.dependencies.sort(key=lambda x: x.name)
+ logging.info('Loaded: %s' % str(self))
+
+ def RunCommandRecursively(self, options, revision_overrides,
+ command, args, pm):
+ """Runs 'command' before parsing the DEPS in case it's a initial checkout
+ or a revert."""
+ assert self.file_list == []
+ # 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', None)
+ self.LateOverride(self.url)
+ if run_scm and self.parsed_url:
+ if isinstance(self.parsed_url, self.FileImpl):
+ # Special support for single-file checkout.
+ if not command in (None, 'cleanup', 'diff', 'pack', 'status'):
+ options.revision = self.parsed_url.GetRevision()
+ scm = gclient_scm.SVNWrapper(self.parsed_url.GetPath(),
+ self.root_dir(),
+ self.name)
+ scm.RunCommand('updatesingle', options,
+ args + [self.parsed_url.GetFilename()],
+ self.file_list)
+ else:
+ options.revision = revision_overrides.get(self.name)
+ scm = gclient_scm.CreateSCM(self.parsed_url, self.root_dir(), self.name)
+ scm.RunCommand(command, options, args, self.file_list)
+ self.file_list = [os.path.join(self.name, f.strip())
+ for f in self.file_list]
+ options.revision = None
+ if pm:
+ # The + 1 comes from the fact that .gclient is considered a step in
+ # itself, .i.e. this code is called one time for the .gclient. This is not
+ # conceptually correct but it simplifies code.
+ pm._total = len(self.tree(False)) + 1
+ pm.update()
+ if self.recursion_limit():
+ # Then we can parse the DEPS file.
+ self.ParseDepsFile(True)
+ if pm:
+ pm._total = len(self.tree(False)) + 1
+ pm.update(0)
+ # Parse the dependencies of this dependency.
+ for s in self.dependencies:
+ # TODO(maruel): All these can run concurrently! No need for threads,
+ # just buffer stdout&stderr on pipes and flush as they complete.
+ # Watch out for stdin.
+ s.RunCommandRecursively(options, revision_overrides, command, args, pm)
+
+ def RunHooksRecursively(self, options):
+ """Evaluates all hooks, running actions as needed. RunCommandRecursively()
+ must have been called before to load the DEPS."""
# If "--force" was specified, run all hooks regardless of what files have
- # changed. If the user is using git, then we don't know what files have
- # changed so we always run all hooks.
- if self._options.force or is_using_git:
- for hook_dict in hooks:
- self._RunHookAction(hook_dict, [])
- return
+ # changed.
+ if self.deps_hooks and self.direct_reference:
+ # TODO(maruel): If the user is using git or git-svn, then we don't know
+ # what files have changed so we always run all hooks. It'd be nice to fix
+ # that.
+ if (options.force or
+ isinstance(self.parsed_url, self.FileImpl) or
+ gclient_scm.GetScmName(self.parsed_url) in ('git', None) or
+ os.path.isdir(os.path.join(self.root_dir(), self.name, '.git'))):
+ for hook_dict in self.deps_hooks:
+ self._RunHookAction(hook_dict, [])
+ else:
+ # TODO(phajdan.jr): We should know exactly when the paths are absolute.
+ # Convert all absolute paths to relative.
+ for i in range(len(self.file_list)):
+ # It depends on the command being executed (like runhooks vs sync).
+ if not os.path.isabs(self.file_list[i]):
+ continue
- # Run hooks on the basis of whether the files from the gclient operation
- # match each hook's pattern.
- for hook_dict in hooks:
- pattern = re.compile(hook_dict['pattern'])
- matching_file_list = [f for f in file_list if pattern.search(f)]
- if matching_file_list:
- self._RunHookAction(hook_dict, matching_file_list)
+ prefix = os.path.commonprefix([self.root_dir().lower(),
+ self.file_list[i].lower()])
+ self.file_list[i] = self.file_list[i][len(prefix):]
+
+ # Strip any leading path separators.
+ while (self.file_list[i].startswith('\\') or
+ self.file_list[i].startswith('/')):
+ self.file_list[i] = self.file_list[i][1:]
+
+ # Run hooks on the basis of whether the files from the gclient operation
+ # match each hook's pattern.
+ for hook_dict in self.deps_hooks:
+ pattern = re.compile(hook_dict['pattern'])
+ matching_file_list = [f for f in self.file_list if pattern.search(f)]
+ if matching_file_list:
+ self._RunHookAction(hook_dict, matching_file_list)
+ if self.recursion_limit():
+ for s in self.dependencies:
+ s.RunHooksRecursively(options)
def _RunHookAction(self, hook_dict, matching_file_list):
"""Runs the action from a single hook."""
@@ -389,7 +425,7 @@ class Dependency(GClientKeywords):
def __str__(self):
out = []
for i in ('name', 'url', 'safesync_url', 'custom_deps', 'custom_vars',
- 'deps_hooks'):
+ 'deps_hooks', 'file_list'):
# 'deps_file'
if self.__dict__[i]:
out.append('%s: %s' % (i, self.__dict__[i]))
@@ -505,19 +541,23 @@ solutions = [
'safesync_url' : safesync_url,
})
- def _SaveEntries(self, entries):
+ def _SaveEntries(self):
"""Creates a .gclient_entries file to record the list of unique checkouts.
The .gclient_entries file lives in the same directory as .gclient.
"""
# Sometimes pprint.pformat will use {', sometimes it'll use { ' ... It
# makes testing a bit too fun.
- result = pprint.pformat(entries, 2)
- if result.startswith('{\''):
- result = '{ \'' + result[2:]
- text = 'entries = \\\n' + result + '\n'
+ result = 'entries = {\n'
+ for entry in self.tree(False):
+ # Skip over File() dependencies as we can't version them.
+ if not isinstance(entry.parsed_url, self.FileImpl):
+ result += ' %s: %s,\n' % (pprint.pformat(entry.name),
+ pprint.pformat(entry.parsed_url))
+ result += '}\n'
file_path = os.path.join(self.root_dir(), self._options.entries_filename)
- gclient_utils.FileWrite(file_path, text)
+ logging.info(result)
+ gclient_utils.FileWrite(file_path, result)
def _ReadEntries(self):
"""Read the .gclient_entries file for the given client.
@@ -578,117 +618,34 @@ solutions = [
if not self.dependencies:
raise gclient_utils.Error('No solution specified')
revision_overrides = self._EnforceRevisions()
-
- # When running runhooks --force, 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 = not (command == 'runhooks' and self._options.force)
-
- entries = {}
- file_list = []
- # Run on the base solutions first.
- for solution in self.dependencies:
- name = solution.name
- if name in entries:
- raise gclient_utils.Error("solution %s specified more than once" % name)
- url = solution.url
- entries[name] = url
- if run_scm and url:
- self._options.revision = revision_overrides.get(name)
- scm = gclient_scm.CreateSCM(url, self.root_dir(), name)
- scm.RunCommand(command, self._options, args, file_list)
- file_list = [os.path.join(name, f.strip()) for f in file_list]
- self._options.revision = None
-
- # Process the dependencies next (sort alphanumerically to ensure that
- # containing directories get populated first and for readability)
- deps = self._ParseAllDeps(entries)
- deps_to_process = deps.keys()
- deps_to_process.sort()
-
- # First pass for direct dependencies.
- if command == 'update' and not self._options.verbose:
- pm = Progress('Syncing projects', len(deps_to_process))
- for d in deps_to_process:
- if command == 'update' and not self._options.verbose:
- pm.update()
- if type(deps[d]) == str:
- url = deps[d]
- entries[d] = url
- if run_scm:
- self._options.revision = revision_overrides.get(d)
- scm = gclient_scm.CreateSCM(url, self.root_dir(), d)
- scm.RunCommand(command, self._options, args, file_list)
- self._options.revision = None
- elif isinstance(deps[d], self.FileImpl):
- if command in (None, 'cleanup', 'diff', 'pack', 'status'):
- continue
- file_dep = deps[d]
- self._options.revision = file_dep.GetRevision()
- if run_scm:
- scm = gclient_scm.SVNWrapper(file_dep.GetPath(), self.root_dir(), d)
- scm.RunCommand('updatesingle', self._options,
- args + [file_dep.GetFilename()], file_list)
-
+ pm = None
if command == 'update' and not self._options.verbose:
+ pm = Progress('Syncing projects', len(self.tree(False)) + 1)
+ self.RunCommandRecursively(self._options, revision_overrides,
+ command, args, pm)
+ if pm:
pm.end()
- # Second pass for inherited deps (via the From keyword)
- for d in deps_to_process:
- if isinstance(deps[d], self.FromImpl):
- # Getting the URL from the sub_deps file can involve having to resolve
- # a File() or having to resolve a relative URL. To resolve relative
- # URLs, we need to pass in the orignal sub deps URL.
- sub_deps_base_url = deps[deps[d].module_name]
- sub_deps = Dependency(self, deps[d].module_name, sub_deps_base_url
- ).ParseDepsFile(False)
- url = deps[d].GetUrl(d, sub_deps_base_url, self.root_dir(), sub_deps)
- entries[d] = url
- if run_scm:
- self._options.revision = revision_overrides.get(d)
- scm = gclient_scm.CreateSCM(url, self.root_dir(), d)
- scm.RunCommand(command, self._options, args, file_list)
- self._options.revision = None
-
- # Convert all absolute paths to relative.
- for i in range(len(file_list)):
- # TODO(phajdan.jr): We should know exactly when the paths are absolute.
- # It depends on the command being executed (like runhooks vs sync).
- if not os.path.isabs(file_list[i]):
- continue
-
- prefix = os.path.commonprefix([self.root_dir().lower(),
- file_list[i].lower()])
- file_list[i] = file_list[i][len(prefix):]
-
- # Strip any leading path separators.
- while file_list[i].startswith('\\') or file_list[i].startswith('/'):
- file_list[i] = file_list[i][1:]
-
- is_using_git = gclient_utils.IsUsingGit(self.root_dir(), entries.keys())
- self._RunHooks(command, file_list, is_using_git)
+ # Once all the dependencies have been processed, it's now safe to run the
+ # hooks.
+ if not self._options.nohooks:
+ self.RunHooksRecursively(self._options)
if command == 'update':
# Notify the user if there is an orphaned entry in their working copy.
# Only delete the directory if there are no changes in it, and
# delete_unversioned_trees is set to true.
- prev_entries = self._ReadEntries()
- for entry in prev_entries:
+ entries = [i.name for i in self.tree(False)]
+ for entry, prev_url in self._ReadEntries().iteritems():
# Fix path separator on Windows.
entry_fixed = entry.replace('/', os.path.sep)
e_dir = os.path.join(self.root_dir(), entry_fixed)
# Use entry and not entry_fixed there.
if entry not in entries and os.path.exists(e_dir):
- modified_files = False
- if isinstance(prev_entries, list):
- # old .gclient_entries format was list, now dict
- modified_files = gclient_scm.scm.SVN.CaptureStatus(e_dir)
- else:
- file_list = []
- scm = gclient_scm.CreateSCM(prev_entries[entry], self.root_dir(),
- entry_fixed)
- scm.status(self._options, [], file_list)
- modified_files = file_list != []
+ file_list = []
+ scm = gclient_scm.CreateSCM(prev_url, self.root_dir(), entry_fixed)
+ scm.status(self._options, [], file_list)
+ modified_files = file_list != []
if not self._options.delete_unversioned_trees or modified_files:
# There are modified files in this entry. Keep warning until
# removed.
@@ -701,7 +658,7 @@ solutions = [
entry_fixed, self.root_dir()))
gclient_utils.RemoveDirectory(e_dir)
# record the current list of entries for next time
- self._SaveEntries(entries)
+ self._SaveEntries()
return 0
def PrintRevInfo(self):
@@ -717,82 +674,55 @@ solutions = [
"""
if not self.dependencies:
raise gclient_utils.Error('No solution specified')
+ # Load all the settings.
+ self.RunCommandRecursively(self._options, {}, None, [], None)
- # Inner helper to generate base url and rev tuple
def GetURLAndRev(name, original_url):
- if not original_url:
+ """Returns the revision-qualified SCM url."""
+ if original_url is None:
return None
+ if isinstance(original_url, self.FileImpl):
+ original_url = original_url.file_location
url, _ = gclient_utils.SplitUrlRevision(original_url)
scm = gclient_scm.CreateSCM(original_url, self.root_dir(), name)
+ if not os.path.isdir(scm.checkout_path):
+ return None
return '%s@%s' % (url, scm.revinfo(self._options, [], None))
- # text of the snapshot gclient file
- new_gclient = ""
- # Dictionary of { path : SCM url } to ensure no duplicate solutions
- solution_names = {}
- entries = {}
- # Run on the base solutions first.
- for solution in self.dependencies:
- # Dictionary of { path : SCM url } to describe the gclient checkout
- name = solution.name
- if name in solution_names:
- raise gclient_utils.Error("solution %s specified more than once" % name)
- url = GetURLAndRev(name, solution.url)
- entries[name] = url
- solution_names[name] = url
-
- # Process the dependencies next (sort alphanumerically to ensure that
- # containing directories get populated first and for readability)
- deps = self._ParseAllDeps(entries)
- deps_to_process = deps.keys()
- deps_to_process.sort()
-
- # First pass for direct dependencies.
- for d in deps_to_process:
- if type(deps[d]) == str:
- entries[d] = GetURLAndRev(d, deps[d])
- elif isinstance(deps[d], self.FileImpl):
- entries[d] = GetURLAndRev(d, deps[d].file_location)
-
- # Second pass for inherited deps (via the From keyword)
- for d in deps_to_process:
- if isinstance(deps[d], self.FromImpl):
- deps_parent_url = entries[deps[d].module_name]
- if deps_parent_url.find("@") < 0:
- raise gclient_utils.Error("From %s missing revisioned url" %
- deps[d].module_name)
- sub_deps_base_url = deps[deps[d].module_name]
- sub_deps = Dependency(self, deps[d].module_name, sub_deps_base_url
- ).ParseDepsFile(False)
- url = deps[d].GetUrl(d, sub_deps_base_url, self.root_dir(), sub_deps)
- entries[d] = GetURLAndRev(d, url)
-
- # Build the snapshot configuration string
if self._options.snapshot:
- url = entries.pop(name)
-
- # Build the snapshot configuration string
- if self._options.snapshot:
- url = entries.pop(name)
- custom_deps = ''.join([' \"%s\": \"%s\",\n' % (x, entries[x])
- for x in sorted(entries.keys())])
-
- new_gclient += self.DEFAULT_SNAPSHOT_SOLUTION_TEXT % {
- 'solution_name': name,
- 'solution_url': url,
- 'safesync_url' : '',
- 'solution_deps': custom_deps,
- }
+ new_gclient = ''
+ # First level at .gclient
+ for d in self.dependencies:
+ entries = {}
+ def GrabDeps(sol):
+ """Recursively grab dependencies."""
+ for i in sol.dependencies:
+ entries[i.name] = GetURLAndRev(i.name, i.parsed_url)
+ GrabDeps(i)
+ GrabDeps(d)
+ custom_deps = []
+ for k in sorted(entries.keys()):
+ if entries[k]:
+ # Quotes aren't escaped...
+ custom_deps.append(' \"%s\": \'%s\',\n' % (k, entries[k]))
+ else:
+ custom_deps.append(' \"%s\": None,\n' % k)
+ new_gclient += self.DEFAULT_SNAPSHOT_SOLUTION_TEXT % {
+ 'solution_name': d.name,
+ 'solution_url': d.url,
+ 'safesync_url' : d.safesync_url or '',
+ 'solution_deps': ''.join(custom_deps),
+ }
+ # Print the snapshot configuration file
+ print(self.DEFAULT_SNAPSHOT_FILE_TEXT % {'solution_list': new_gclient})
else:
- print(';\n'.join(['%s: %s' % (x, entries[x])
- for x in sorted(entries.keys())]))
-
- # Print the snapshot configuration file
- if self._options.snapshot:
- config = self.DEFAULT_SNAPSHOT_FILE_TEXT % {'solution_list': new_gclient}
- snapclient = GClient(self.root_dir(), self._options)
- snapclient.SetConfig(config)
- print(snapclient.config_content)
+ entries = sorted(self.tree(False), key=lambda i: i.name)
+ for entry in entries:
+ entry_url = GetURLAndRev(entry.name, entry.parsed_url)
+ line = '%s: %s' % (entry.name, entry_url)
+ if not entry is entries[-1]:
+ line += ';'
+ print line
def ParseDepsFile(self, direct_reference):
"""No DEPS to parse for a .gclient file."""
@@ -1113,8 +1043,7 @@ def CMDrevinfo(parser, args):
'references')
parser.add_option('-s', '--snapshot', action='store_true',
help='creates a snapshot .gclient file of the current '
- 'version of all repositories to reproduce the tree, '
- 'implies -a')
+ 'version of all repositories to reproduce the tree')
(options, args) = parser.parse_args(args)
client = GClient.LoadCurrentConfig(options)
if not client:
« no previous file with comments | « no previous file | gclient_utils.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698