Commit 62af4e40 authored by Edward Lesmes's avatar Edward Lesmes Committed by Commit Bot

gclient setdep: Add support for more use cases

Add support for more ways to express revisions in DEPS files, notably
"<origin-url>@<revision>" which is needed for src-internal.

Bug: 760633
Change-Id: I86724b9c077c6101a0c424d80460123d15533da8
Reviewed-on: https://chromium-review.googlesource.com/988493
Commit-Queue: Edward Lesmes <ehmaldonado@chromium.org>
Reviewed-by: 's avatarAaron Gable <agable@chromium.org>
parent dc2c0b97
......@@ -495,7 +495,8 @@ def RenderDEPSFile(gclient_dict):
def _UpdateAstString(tokens, node, value):
position = node.lineno, node.col_offset
tokens[position][1] = repr(value)
quote_char = tokens[position][1][0]
tokens[position][1] = quote_char + value + quote_char
node.s = value
......@@ -554,17 +555,15 @@ def SetCIPD(gclient_dict, dep_name, package_name, new_version):
def SetRevision(gclient_dict, dep_name, new_revision):
if not isinstance(gclient_dict, _NodeDict) or gclient_dict.tokens is None:
raise ValueError(
"Can't use SetRevision for the given gclient dict. It contains no "
"formatting information.")
tokens = gclient_dict.tokens
if 'deps' not in gclient_dict or dep_name not in gclient_dict['deps']:
raise ValueError(
"Could not find any dependency called %s." % dep_name)
def _GetVarName(node):
if isinstance(node, ast.Call):
return node.args[0].s
elif node.s.endswith('}'):
last_brace = node.s.rfind('{')
return node.s[last_brace+1:-1]
return None
def _UpdateRevision(dep_dict, dep_key):
def _UpdateRevision(dep_dict, dep_key, new_revision):
dep_node = dep_dict.GetNode(dep_key)
if dep_node is None:
raise ValueError(
......@@ -573,15 +572,31 @@ def SetRevision(gclient_dict, dep_name, new_revision):
node = dep_node
if isinstance(node, ast.BinOp):
node = node.right
if isinstance(node, ast.Call):
SetVar(gclient_dict, node.args[0].s, new_revision)
if not isinstance(node, ast.Call) and not isinstance(node, ast.Str):
raise ValueError(
"Unsupported dependency revision format. Please file a bug.")
var_name = _GetVarName(node)
if var_name is not None:
SetVar(gclient_dict, var_name, new_revision)
else:
if '@' in node.s:
new_revision = node.s.split('@')[0] + '@' + new_revision
_UpdateAstString(tokens, node, new_revision)
value = _gclient_eval(dep_node, gclient_dict.get('vars', None),
expand_vars=True, filename='<unknown>')
dep_dict.SetNode(dep_key, value, dep_node)
dep_dict.SetNode(dep_key, new_revision, node)
if not isinstance(gclient_dict, _NodeDict) or gclient_dict.tokens is None:
raise ValueError(
"Can't use SetRevision for the given gclient dict. It contains no "
"formatting information.")
tokens = gclient_dict.tokens
if 'deps' not in gclient_dict or dep_name not in gclient_dict['deps']:
raise ValueError(
"Could not find any dependency called %s." % dep_name)
if isinstance(gclient_dict['deps'][dep_name], _NodeDict):
_UpdateRevision(gclient_dict['deps'][dep_name], 'url')
_UpdateRevision(gclient_dict['deps'][dep_name], 'url', new_revision)
else:
_UpdateRevision(gclient_dict['deps'], dep_name)
_UpdateRevision(gclient_dict['deps'], dep_name, new_revision)
......@@ -8,7 +8,6 @@ import itertools
import logging
import os
import sys
import textwrap
import unittest
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
......@@ -19,44 +18,6 @@ import gclient
import gclient_eval
_SAMPLE_DEPS_FILE = textwrap.dedent("""\
vars = {
'git_repo': 'https://example.com/repo.git',
# Some comment with bad indentation
'dep_2_rev': '1ced',
# Some more comments with bad indentation
# and trailing whitespaces """ + """
'dep_3_rev': '5p1e5',
}
deps = {
'src/dep': Var('git_repo') + '/dep' + '@' + 'deadbeef',
# Some comment
'src/android/dep_2': {
'url': Var('git_repo') + '/dep_2' + '@' + Var('dep_2_rev'),
'condition': 'checkout_android',
},
'src/dep_3': Var('git_repo') + '/dep_3@' + Var('dep_3_rev'),
'src/cipd/package': {
'packages': [
{
'package': 'some/cipd/package',
'version': 'version:1234',
},
{
'package': 'another/cipd/package',
'version': 'version:5678',
},
],
'condition': 'checkout_android',
'dep_type': 'cipd',
},
}
""")
class GClientEvalTest(unittest.TestCase):
def test_str(self):
self.assertEqual('foo', gclient_eval._gclient_eval('"foo"'))
......@@ -277,51 +238,226 @@ class EvaluateConditionTest(unittest.TestCase):
class SetVarTest(unittest.TestCase):
def test_sets_var(self):
local_scope = gclient_eval.Exec(_SAMPLE_DEPS_FILE, True)
local_scope = gclient_eval.Exec('\n'.join([
'vars = {',
' "foo": "bar",',
'}',
]))
gclient_eval.SetVar(local_scope, 'dep_2_rev', 'c0ffee')
gclient_eval.SetVar(local_scope, 'foo', 'baz')
result = gclient_eval.RenderDEPSFile(local_scope)
self.assertEqual(
result,
_SAMPLE_DEPS_FILE.replace('1ced', 'c0ffee'))
self.assertEqual(result, '\n'.join([
'vars = {',
' "foo": "baz",',
'}',
]))
def test_preserves_formatting(self):
local_scope = gclient_eval.Exec('\n'.join([
'vars = {',
' # Comment with trailing space ',
' "foo": \'bar\',',
'}',
]))
gclient_eval.SetVar(local_scope, 'foo', 'baz')
result = gclient_eval.RenderDEPSFile(local_scope)
self.assertEqual(result, '\n'.join([
'vars = {',
' # Comment with trailing space ',
' "foo": \'baz\',',
'}',
]))
class SetCipdTest(unittest.TestCase):
def test_sets_cipd(self):
local_scope = gclient_eval.Exec(_SAMPLE_DEPS_FILE, True)
local_scope = gclient_eval.Exec('\n'.join([
'deps = {',
' "src/cipd/package": {',
' "packages": [',
' {',
' "package": "some/cipd/package",',
' "version": "version:1234",',
' },',
' {',
' "package": "another/cipd/package",',
' "version": "version:5678",',
' },',
' ],',
' "condition": "checkout_android",',
' "dep_type": "cipd",',
' },',
'}',
]))
gclient_eval.SetCIPD(
local_scope, 'src/cipd/package', 'another/cipd/package', '6.789')
result = gclient_eval.RenderDEPSFile(local_scope)
self.assertEqual(result, _SAMPLE_DEPS_FILE.replace('5678', '6.789'))
self.assertEqual(result, '\n'.join([
'deps = {',
' "src/cipd/package": {',
' "packages": [',
' {',
' "package": "some/cipd/package",',
' "version": "version:1234",',
' },',
' {',
' "package": "another/cipd/package",',
' "version": "version:6.789",',
' },',
' ],',
' "condition": "checkout_android",',
' "dep_type": "cipd",',
' },',
'}',
]))
class SetRevisionTest(unittest.TestCase):
def setUp(self):
self.local_scope = gclient_eval.Exec(_SAMPLE_DEPS_FILE, True)
def assert_changes_revision(self, before, after):
local_scope = gclient_eval.Exec('\n'.join(before))
gclient_eval.SetRevision(local_scope, 'src/dep', 'deadfeed')
self.assertEqual('\n'.join(after), gclient_eval.RenderDEPSFile(local_scope))
def test_sets_revision(self):
gclient_eval.SetRevision(
self.local_scope, 'src/dep', 'deadfeed')
result = gclient_eval.RenderDEPSFile(self.local_scope)
before = [
'deps = {',
' "src/dep": "https://example.com/dep.git@deadbeef",',
'}',
]
after = [
'deps = {',
' "src/dep": "https://example.com/dep.git@deadfeed",',
'}',
]
self.assert_changes_revision(before, after)
self.assertEqual(result, _SAMPLE_DEPS_FILE.replace('deadbeef', 'deadfeed'))
def test_sets_revision_new_line(self):
before = [
'deps = {',
' "src/dep": "https://example.com/dep.git@"',
' + "deadbeef",',
'}',
]
after = [
'deps = {',
' "src/dep": "https://example.com/dep.git@"',
' + "deadfeed",',
'}',
]
self.assert_changes_revision(before, after)
def test_sets_revision_inside_dict(self):
gclient_eval.SetRevision(
self.local_scope, 'src/dep_3', '0ff1ce')
result = gclient_eval.RenderDEPSFile(self.local_scope)
before = [
'deps = {',
' "src/dep": {',
' "url": "https://example.com/dep.git@deadbeef",',
' "condition": "some_condition",',
' },',
'}',
]
after = [
'deps = {',
' "src/dep": {',
' "url": "https://example.com/dep.git@deadfeed",',
' "condition": "some_condition",',
' },',
'}',
]
self.assert_changes_revision(before, after)
self.assertEqual(result, _SAMPLE_DEPS_FILE.replace('5p1e5', '0ff1ce'))
def test_follows_var_braces(self):
before = [
'vars = {',
' "dep_revision": "deadbeef",',
'}',
'deps = {',
' "src/dep": "https://example.com/dep.git@{dep_revision}",',
'}',
]
after = [
'vars = {',
' "dep_revision": "deadfeed",',
'}',
'deps = {',
' "src/dep": "https://example.com/dep.git@{dep_revision}",',
'}',
]
self.assert_changes_revision(before, after)
def test_sets_revision_in_vars(self):
gclient_eval.SetRevision(
self.local_scope, 'src/android/dep_2', 'c0ffee')
result = gclient_eval.RenderDEPSFile(self.local_scope)
def test_follows_var_braces_newline(self):
before = [
'vars = {',
' "dep_revision": "deadbeef",',
'}',
'deps = {',
' "src/dep": "https://example.com/dep.git"',
' + "@{dep_revision}",',
'}',
]
after = [
'vars = {',
' "dep_revision": "deadfeed",',
'}',
'deps = {',
' "src/dep": "https://example.com/dep.git"',
' + "@{dep_revision}",',
'}',
]
self.assert_changes_revision(before, after)
def test_follows_var_function(self):
before = [
'vars = {',
' "dep_revision": "deadbeef",',
'}',
'deps = {',
' "src/dep": "https://example.com/dep.git@" + Var("dep_revision"),',
'}',
]
after = [
'vars = {',
' "dep_revision": "deadfeed",',
'}',
'deps = {',
' "src/dep": "https://example.com/dep.git@" + Var("dep_revision"),',
'}',
]
self.assert_changes_revision(before, after)
self.assertEqual(result, _SAMPLE_DEPS_FILE.replace('1ced', 'c0ffee'))
def test_preserves_formatting(self):
before = [
'vars = {',
' # Some coment on deadbeef ',
' "dep_revision": "deadbeef",',
'}',
'deps = {',
' "src/dep": {',
' "url": "https://example.com/dep.git@" + Var("dep_revision"),',
'',
' "condition": "some_condition",',
' },',
'}',
]
after = [
'vars = {',
' # Some coment on deadbeef ',
' "dep_revision": "deadfeed",',
'}',
'deps = {',
' "src/dep": {',
' "url": "https://example.com/dep.git@" + Var("dep_revision"),',
'',
' "condition": "some_condition",',
' },',
'}',
]
self.assert_changes_revision(before, after)
class ParseTest(unittest.TestCase):
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment