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

Unified Diff: gclient.py

Issue 2837001: Make each solution dictionary an object. (Closed)
Patch Set: Include a fix in GetScmName() Created 10 years, 6 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_scm.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 9ea7ce08c5b27382836d94aaa5d0622434d23e8c..9721c55ff50db194276929c98a02c467dee42916 100644
--- a/gclient.py
+++ b/gclient.py
@@ -155,10 +155,38 @@ class GClientKeywords(object):
raise gclient_utils.Error("Var is not defined: %s" % var_name)
-class GClient(GClientKeywords):
- """Object that represent a gclient checkout."""
+class Dependency(GClientKeywords):
+ """Object that represents a dependency checkout."""
DEPS_FILE = 'DEPS'
+ def __init__(self, parent, name, url, safesync_url=None, custom_deps=None,
+ custom_vars=None, deps_file=None):
+ GClientKeywords.__init__(self)
+ self.parent = parent
+ self.name = name
+ self.url = url
+ # These 2 are only set in .gclient and not in DEPS files.
+ self.safesync_url = safesync_url
+ self.custom_vars = custom_vars or {}
+ self.custom_deps = custom_deps or {}
+ self.dependencies = []
+ self.deps_file = deps_file or self.DEPS_FILE
+ self._deps_hooks = []
+ # Sanity checks
+ if not self.name and self.parent:
+ raise gclient_utils.Error('Dependency without 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, '
+ 'File() or From() instead of %s' %
+ self.url.__class__.__name__)
+ if '/' in self.deps_file or '\\' in self.deps_file:
+ raise gclient_utils.Error('deps_file name must not be a path, just a '
+ 'filename. %s' % self.deps_file)
+
+
+class GClient(Dependency):
+ """Main gclient checkout root where .gclient resides."""
SUPPORTED_COMMANDS = [
'cleanup', 'diff', 'export', 'pack', 'revert', 'status', 'update',
'runhooks'
@@ -204,17 +232,16 @@ solutions = [
""")
def __init__(self, root_dir, options):
+ Dependency.__init__(self, None, None, None)
self._root_dir = root_dir
self._options = options
self.config_content = None
- self._config_dict = {}
- self._deps_hooks = []
def SetConfig(self, content):
- self._config_dict = {}
+ config_dict = {}
self.config_content = content
try:
- exec(content, self._config_dict)
+ exec(content, config_dict)
except SyntaxError, e:
try:
# Try to construct a human readable error message
@@ -228,6 +255,14 @@ solutions = [
else:
# Raise a new exception with the human readable message:
raise gclient_utils.Error('\n'.join(error_message))
+ for s in config_dict.get('solutions', []):
+ self.dependencies.append(Dependency(
+ self, s['name'], s['url'],
+ s.get('safesync_url', None),
+ s.get('custom_deps', {}),
+ s.get('custom_vars', {})))
+ # .gclient can have hooks.
+ self._deps_hooks = config_dict.get('hooks', [])
def SaveConfig(self):
gclient_utils.FileWrite(os.path.join(self.root_dir(),
@@ -239,9 +274,6 @@ solutions = [
os.path.join(self.root_dir(), self._options.config_filename))
self.SetConfig(client_source)
- def GetVar(self, key, default=None):
- return self._config_dict.get(key, default)
-
@staticmethod
def LoadCurrentConfig(options, from_dir=None):
"""Searches for and loads a .gclient file relative to the current working
@@ -355,7 +387,12 @@ solutions = [
deps.update(os_deps)
if 'hooks' in local_scope and parse_hooks:
- self._deps_hooks.extend(local_scope['hooks'])
+ # TODO(maruel): Temporary Hack. Since this function is misplaced, find the
+ # right 'self' to add the hooks.
+ for d in self.dependencies:
+ if d.name == solution_name:
+ d._deps_hooks.extend(local_scope['hooks'])
+ break
# If use_relative_paths is set in the DEPS file, regenerate
# the dictionary using paths relative to the directory containing
@@ -388,25 +425,23 @@ solutions = [
Error: If a dependency conflicts with another dependency or of a solution.
"""
deps = {}
- for solution in self.GetVar("solutions"):
- custom_vars = solution.get("custom_vars", {})
+ for solution in self.dependencies:
solution_deps = self._ParseSolutionDeps(
- solution["name"],
- solution_deps_content[solution["name"]],
- custom_vars,
+ solution.name,
+ solution_deps_content[solution.name],
+ solution.custom_vars,
True)
# If a line is in custom_deps, but not in the solution, we want to append
# this line to the solution.
- if "custom_deps" in solution:
- for d in solution["custom_deps"]:
- if d not in solution_deps:
- solution_deps[d] = solution["custom_deps"][d]
+ 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 "custom_deps" in solution and d in solution["custom_deps"]:
+ if d in solution.custom_deps:
# Dependency is overriden.
- url = solution["custom_deps"][d]
+ url = solution.custom_deps[d]
if url is None:
continue
else:
@@ -434,8 +469,8 @@ solutions = [
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)
+ 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(
@@ -480,9 +515,10 @@ solutions = [
return
# Get any hooks from the .gclient file.
- hooks = self.GetVar("hooks", [])
+ hooks = self._deps_hooks[:]
# Add any hooks found in DEPS files.
- hooks.extend(self._deps_hooks)
+ for d in self.dependencies:
+ hooks.extend(d._deps_hooks)
# 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
@@ -500,29 +536,29 @@ solutions = [
if matching_file_list:
self._RunHookAction(hook_dict, matching_file_list)
- def _EnforceRevisions(self, solutions):
+ def _EnforceRevisions(self):
"""Checks for revision overrides."""
revision_overrides = {}
if self._options.head:
return revision_overrides
- for s in solutions:
- if not s.get('safesync_url', None):
+ for s in self.dependencies:
+ if not s.safesync_url:
continue
- handle = urllib.urlopen(s['safesync_url'])
+ handle = urllib.urlopen(s.safesync_url)
rev = handle.read().strip()
handle.close()
if len(rev):
- self._options.revisions.append('%s@%s' % (s['name'], rev))
+ self._options.revisions.append('%s@%s' % (s.name, rev))
if not self._options.revisions:
return revision_overrides
# --revision will take over safesync_url.
- solutions_names = [s['name'] for s in solutions]
+ solutions_names = [s.name for s in self.dependencies]
index = 0
for revision in self._options.revisions:
if not '@' in revision:
# Support for --revision 123
revision = '%s@%s' % (solutions_names[index], revision)
- sol, rev = revision.split("@", 1)
+ sol, rev = revision.split('@', 1)
if not sol in solutions_names:
#raise gclient_utils.Error('%s is not a valid solution.' % sol)
print >> sys.stderr, ('Please fix your script, having invalid '
@@ -547,10 +583,9 @@ solutions = [
if not command in self.SUPPORTED_COMMANDS:
raise gclient_utils.Error("'%s' is an unsupported command" % command)
- solutions = self.GetVar("solutions")
- if not solutions:
+ if not self.dependencies:
raise gclient_utils.Error("No solution specified")
- revision_overrides = self._EnforceRevisions(solutions)
+ 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
@@ -561,15 +596,11 @@ solutions = [
entries_deps_content = {}
file_list = []
# Run on the base solutions first.
- for solution in solutions:
- name = solution["name"]
- deps_file = solution.get("deps_file", self.DEPS_FILE)
- if '/' in deps_file or '\\' in deps_file:
- raise gclient_utils.Error('deps_file name must not be a path, just a '
- 'filename.')
+ 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"]
+ url = solution.url
entries[name] = url
if run_scm and url:
self._options.revision = revision_overrides.get(name)
@@ -579,7 +610,7 @@ solutions = [
self._options.revision = None
try:
deps_content = gclient_utils.FileRead(
- os.path.join(self.root_dir(), name, deps_file))
+ os.path.join(self.root_dir(), name, solution.deps_file))
except IOError, e:
if e.errno != errno.ENOENT:
raise
@@ -703,8 +734,7 @@ solutions = [
The --snapshot option allows creating a .gclient file to reproduce the tree.
"""
- solutions = self.GetVar("solutions")
- if not solutions:
+ if not self.dependencies:
raise gclient_utils.Error("No solution specified")
# Inner helper to generate base url and rev tuple
@@ -720,15 +750,15 @@ solutions = [
entries = {}
entries_deps_content = {}
# Run on the base solutions first.
- for solution in solutions:
+ for solution in self.dependencies:
# Dictionary of { path : SCM url } to describe the gclient checkout
- name = solution["name"]
+ name = solution.name
if name in solution_names:
raise gclient_utils.Error("solution %s specified more than once" % name)
- (url, rev) = GetURLAndRev(name, solution["url"])
+ (url, rev) = GetURLAndRev(name, solution.url)
entries[name] = "%s@%s" % (url, rev)
solution_names[name] = "%s@%s" % (url, rev)
- deps_file = solution.get("deps_file", self.DEPS_FILE)
+ deps_file = solution.deps_file
if '/' in deps_file or '\\' in deps_file:
raise gclient_utils.Error('deps_file name must not be a path, just a '
'filename.')
« no previous file with comments | « no previous file | gclient_scm.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698