diff --git a/gclient.py b/gclient.py index 5e326dfc49..3c8ed83823 100755 --- a/gclient.py +++ b/gclient.py @@ -3347,6 +3347,11 @@ def CMDsetdep(parser, args): local_scope = gclient_eval.Exec(contents, options.deps_file, builtin_vars=builtin_vars) + # Create a set of all git submodules. + submodule_status = subprocess2.check_output(['git', 'submodule', + 'status']).decode('utf-8') + git_modules = {l.split()[1] for l in submodule_status.splitlines()} + for var in options.vars: name, _, value = var.partition('=') if not name or not value: @@ -3370,7 +3375,26 @@ def CMDsetdep(parser, args): % (name, package)) gclient_eval.SetCIPD(local_scope, name, package, value) else: - gclient_eval.SetRevision(local_scope, name, value) + # Update DEPS only when `git_dependencies` == DEPS or SYNC. + # git_dependencies is defaulted to DEPS when not set. + if 'git_dependencies' not in local_scope or local_scope[ + 'git_dependencies'] in (gclient_eval.DEPS, gclient_eval.SYNC): + gclient_eval.SetRevision(local_scope, name, value) + + # Update git submodules when `git_dependencies` == SYNC or SUBMODULES. + if 'git_dependencies' in local_scope and local_scope[ + 'git_dependencies'] in (gclient_eval.SUBMODULES, gclient_eval.SYNC): + # gclient setdep should update the revision, i.e., the gitlink only + # when the submodule entry is already present within .gitmodules. + if name not in git_modules: + raise KeyError( + 'Could not find any dependency called %s in .gitmodules.' % name) + + # Update the gitlink for the submodule. + subprocess2.call([ + 'git', 'update-index', '--add', '--cacheinfo', + f'160000,{value},{name}' + ]) with open(options.deps_file, 'wb') as f: f.write(gclient_eval.RenderDEPSFile(local_scope).encode('utf-8')) diff --git a/tests/gclient_git_smoketest.py b/tests/gclient_git_smoketest.py index a50086b0cd..c3b9c7b7b7 100755 --- a/tests/gclient_git_smoketest.py +++ b/tests/gclient_git_smoketest.py @@ -549,7 +549,8 @@ class GClientSmokeGIT(gclient_smoketest_base.GClientSmokeBase): self.assertEqual(out, output_json) def testSetDep(self): - fake_deps = os.path.join(self.root_dir, 'DEPS.fake') + self.gclient(['config', self.git_base + 'repo_1', '--name', 'src']) + fake_deps = os.path.join(self.git_base, 'repo_1', 'DEPS') with open(fake_deps, 'w') as f: f.write('\n'.join([ 'vars = { ', @@ -565,8 +566,10 @@ class GClientSmokeGIT(gclient_smoketest_base.GClientSmokeBase): ])) self.gclient([ - 'setdep', '-r', 'foo@new_foo', '-r', 'bar@new_bar', - '--var', 'foo_var=new_val', '--deps-file', fake_deps]) + 'setdep', '-r', 'foo@new_foo', '-r', 'bar@new_bar', '--var', + 'foo_var=new_val', '--deps-file', fake_deps + ], + cwd=self.git_base + 'repo_1') with open(fake_deps) as f: contents = f.read().splitlines() @@ -584,9 +587,51 @@ class GClientSmokeGIT(gclient_smoketest_base.GClientSmokeBase): '}', ], contents) - def testSetDep_BuiltinVariables(self): + def testSetDep_Submodules(self): self.gclient(['config', self.git_base + 'repo_1', '--name', 'src']) - fake_deps = os.path.join(self.root_dir, 'DEPS.fake') + fake_deps = os.path.join(self.git_base, 'repo_1', 'DEPS') + gitmodules = os.path.join(self.git_base, 'repo_1', '.gitmodules') + with open(fake_deps, 'w') as f: + f.write('\n'.join([ + 'git_dependencies = "SUBMODULES"', + 'vars = { ', + ' "foo_var": "foo_val",', + ' "foo_rev": "foo_rev",', + '}', + ])) + + with open(gitmodules, 'w') as f: + f.write('\n'.join( + ['[submodule "foo"]', ' url = https://foo', ' path = foo'])) + + subprocess2.call([ + 'git', 'update-index', '--add', '--cacheinfo', + '160000,aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa,foo' + ], + cwd=self.git_base + 'repo_1') + + self.gclient([ + 'setdep', '-r', 'foo@new_foo', '--var', 'foo_var=new_val', + '--deps-file', fake_deps + ], + cwd=self.git_base + 'repo_1') + + with open(fake_deps) as f: + contents = f.read().splitlines() + + self.assertEqual([ + 'git_dependencies = "SUBMODULES"', + 'vars = { ', + ' "foo_var": "new_val",', + ' "foo_rev": "foo_rev",', + '}', + ], contents) + + def testSetDep_BuiltinVariables(self): + self.gclient(['config', self.git_base + 'repo_1', '--name', 'src'], + cwd=self.git_base) + + fake_deps = os.path.join(self.root_dir, 'DEPS') with open(fake_deps, 'w') as f: f.write('\n'.join([ 'vars = { ', @@ -608,8 +653,10 @@ class GClientSmokeGIT(gclient_smoketest_base.GClientSmokeBase): ])) self.gclient([ - 'setdep', '-r', 'foo@new_foo', '-r', 'bar@new_bar', - '--var', 'foo_var=new_val', '--deps-file', fake_deps]) + 'setdep', '-r', 'foo@new_foo', '-r', 'bar@new_bar', '--var', + 'foo_var=new_val', '--deps-file', fake_deps + ], + cwd=self.git_base + 'repo_1') with open(fake_deps) as f: contents = f.read().splitlines()