|
|
|
@ -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]
|
|
|
|
|