| Index: gclient.py
|
| diff --git a/gclient.py b/gclient.py
|
| index 94a981d50248079d0e3fa5d6f7891b766125aa79..a92cce05c0426d817b7ed9bfe6a99b0c394ad7ae 100755
|
| --- a/gclient.py
|
| +++ b/gclient.py
|
| @@ -78,6 +78,7 @@
|
|
|
| __version__ = '0.7'
|
|
|
| +import ast
|
| import copy
|
| import json
|
| import logging
|
| @@ -103,6 +104,57 @@ import subcommand
|
| import subprocess2
|
| from third_party import colorama
|
|
|
| +CHROMIUM_SRC_URL = 'https://chromium.googlesource.com/chromium/src.git'
|
| +
|
| +
|
| +def ast_dict_index(dnode, key):
|
| + """Search an ast.Dict for the argument key, and return its index."""
|
| + idx = [i for i in range(len(dnode.keys)) if (
|
| + type(dnode.keys[i]) is ast.Str and dnode.keys[i].s == key)]
|
| + if not idx:
|
| + return -1
|
| + elif len(idx) > 1:
|
| + raise gclient_utils.Error('Multiple dict entries with same key in AST')
|
| + return idx[-1]
|
| +
|
| +def ast2str(node, indent=0):
|
| + """Return a pretty-printed rendition of an ast.Node."""
|
| + t = type(node)
|
| + if t is ast.Module:
|
| + return '\n'.join([ast2str(x, indent) for x in node.body])
|
| + elif t is ast.Assign:
|
| + return ((' ' * indent) +
|
| + ' = '.join([ast2str(x) for x in node.targets] +
|
| + [ast2str(node.value, indent)]) + '\n')
|
| + elif t is ast.Name:
|
| + return node.id
|
| + elif t is ast.List:
|
| + if not node.elts:
|
| + return '[]'
|
| + elif len(node.elts) == 1:
|
| + return '[' + ast2str(node.elts[0], indent) + ']'
|
| + return ('[\n' + (' ' * (indent + 1)) +
|
| + (',\n' + (' ' * (indent + 1))).join(
|
| + [ast2str(x, indent + 1) for x in node.elts]) +
|
| + '\n' + (' ' * indent) + ']')
|
| + elif t is ast.Dict:
|
| + if not node.keys:
|
| + return '{}'
|
| + elif len(node.keys) == 1:
|
| + return '{%s: %s}' % (ast2str(node.keys[0]),
|
| + ast2str(node.values[0], indent + 1))
|
| + return ('{\n' + (' ' * (indent + 1)) +
|
| + (',\n' + (' ' * (indent + 1))).join(
|
| + ['%s: %s' % (ast2str(node.keys[i]),
|
| + ast2str(node.values[i], indent + 1))
|
| + for i in range(len(node.keys))]) +
|
| + '\n' + (' ' * indent) + '}')
|
| + elif t is ast.Str:
|
| + return "'%s'" % node.s
|
| + else:
|
| + raise gclient_utils.Error("Unexpected AST node at line %d, column %d: %s"
|
| + % (node.lineno, node.col_offset, t))
|
| +
|
|
|
| class GClientKeywords(object):
|
| class FromImpl(object):
|
| @@ -168,7 +220,10 @@ class DependencySettings(GClientKeywords):
|
| # These are not mutable:
|
| self._parent = parent
|
| self._safesync_url = safesync_url
|
| - self._deps_file = deps_file
|
| + if url == CHROMIUM_SRC_URL:
|
| + self._deps_file = 'DEPS'
|
| + else:
|
| + self._deps_file = deps_file
|
| self._url = url
|
| # 'managed' determines whether or not this dependency is synced/updated by
|
| # gclient after gclient checks it out initially. The difference between
|
| @@ -1196,6 +1251,79 @@ want to set 'managed': False in .gclient.
|
| self._options.config_filename),
|
| self.config_content)
|
|
|
| + def MigrateConfigToGit(self, path, options):
|
| + svn_url_re = re.compile('^(https?://src\.chromium\.org/svn|'
|
| + 'svn://svn\.chromium\.org/chrome)/'
|
| + '(trunk|branches/[^/]+)/src')
|
| + old_git_re = re.compile('^(https?://git\.chromium\.org|'
|
| + 'ssh://([a-zA-Z_][a-zA-Z0-9_-]*@)?'
|
| + 'gerrit\.chromium\.org(:2941[89])?)/'
|
| + 'chromium/src\.git')
|
| + # Scan existing .gclient file for obsolete settings. It would be simpler
|
| + # to traverse self.dependencies, but working with the AST allows the code to
|
| + # dump an updated .gclient file that preserves the ordering of the original.
|
| + a = ast.parse(self.config_content, options.config_filename, 'exec')
|
| + modified = False
|
| + solutions = [elem for elem in a.body if 'solutions' in
|
| + [target.id for target in elem.targets]]
|
| + if not solutions:
|
| + return self
|
| + solutions = solutions[-1]
|
| + for solution in solutions.value.elts:
|
| + # Check for obsolete URL's
|
| + url_idx = ast_dict_index(solution, 'url')
|
| + if url_idx == -1:
|
| + continue
|
| + url_val = solution.values[url_idx]
|
| + if type(url_val) is not ast.Str:
|
| + continue
|
| + if (svn_url_re.match(url_val.s.strip())):
|
| + raise gclient_utils.Error(
|
| +"""
|
| +The chromium code repository has migrated completely to git.
|
| +Your SVN-based checkout is now obsolete; you need to create a brand-new
|
| +git checkout by following these instructions:
|
| +
|
| +http://www.chromium.org/developers/how-tos/get-the-code
|
| +""")
|
| + if (old_git_re.match(url_val.s.strip())):
|
| + url_val.s = CHROMIUM_SRC_URL
|
| + modified = True
|
| +
|
| + # Check for obsolete deps_file
|
| + if url_val.s == CHROMIUM_SRC_URL:
|
| + deps_file_idx = ast_dict_index(solution, 'deps_file')
|
| + if deps_file_idx == -1:
|
| + continue
|
| + deps_file_val = solution.values[deps_file_idx]
|
| + if type(deps_file_val) is not ast.Str:
|
| + continue
|
| + if deps_file_val.s == '.DEPS.git':
|
| + solution.keys[deps_file_idx:deps_file_idx + 1] = []
|
| + solution.values[deps_file_idx:deps_file_idx + 1] = []
|
| + modified = True
|
| +
|
| + if not modified:
|
| + return self
|
| +
|
| + print(
|
| +"""
|
| +WARNING: gclient detected an obsolete setting in your %s file. The file has
|
| +been automagically updated. The previous version is available at %s.old.
|
| +""" % (options.config_filename, options.config_filename))
|
| +
|
| + # Replace existing .gclient with the updated version.
|
| + # Return a new GClient instance based on the new content.
|
| + new_content = ast2str(a)
|
| + dot_gclient_fn = os.path.join(path, options.config_filename)
|
| + os.rename(dot_gclient_fn, dot_gclient_fn + '.old')
|
| + fh = open(dot_gclient_fn, 'w')
|
| + fh.write(new_content)
|
| + fh.close()
|
| + client = GClient(path, options)
|
| + client.SetConfig(new_content)
|
| + return client
|
| +
|
| @staticmethod
|
| def LoadCurrentConfig(options):
|
| """Searches for and loads a .gclient file relative to the current working
|
| @@ -1210,6 +1338,7 @@ want to set 'managed': False in .gclient.
|
| client = GClient(path, options)
|
| client.SetConfig(gclient_utils.FileRead(
|
| os.path.join(path, options.config_filename)))
|
| + client = client.MigrateConfigToGit(path, options)
|
|
|
| if (options.revisions and
|
| len(client.dependencies) > 1 and
|
| @@ -1646,8 +1775,6 @@ def CMDconfig(parser, args):
|
| 'to have the main solution untouched by gclient '
|
| '(gclient will check out unmanaged dependencies but '
|
| 'will never sync them)')
|
| - parser.add_option('--git-deps', action='store_true',
|
| - help='sets the deps file to ".DEPS.git" instead of "DEPS"')
|
| parser.add_option('--cache-dir',
|
| help='(git only) Cache all git repos into this dir and do '
|
| 'shared clones from the cache, instead of cloning '
|
| @@ -1673,8 +1800,6 @@ def CMDconfig(parser, args):
|
| # specify an alternate relpath for the given URL.
|
| name = options.name
|
| deps_file = options.deps_file
|
| - if options.git_deps:
|
| - deps_file = '.DEPS.git'
|
| safesync_url = ''
|
| if len(args) > 1:
|
| safesync_url = args[1]
|
|
|