diff --git a/gclient.py b/gclient.py index b6cea2bdd9..b5ee7ba9cd 100755 --- a/gclient.py +++ b/gclient.py @@ -934,6 +934,38 @@ class Dependency(gclient_utils.WorkItem, DependencySettings): bad_deps.append(dep) return bad_deps + def FuzzyMatchUrl(self, parsed_url, candidates): + """Attempts to find this dependency in the list of candidates. + + It looks first for the URL of this dependency (parsed_url) in the list of + candidates. If it doesn't succeed, and the URL ends in '.git', it will try + looking for the URL minus '.git'. Finally it will try to look for the name + of the dependency. + + Args: + parsed_url: str. The parsed URL for this dependency. Something like + "https://example.com/src.git@revision" + candidates: list, dict. The list of candidates in which to look for this + dependency. It can contain URLs as above, or dependency names like + "src/some/dep". + + Returns: + If this dependency is not found in the list of candidates, returns None. + Otherwise, it returns under which name did we find this dependency: + - Its parsed url: "https://example.com/src.git' + - Its parsed url minus '.git': "https://example.com/src" + - Its name: "src" + """ + if parsed_url: + origin, _ = gclient_utils.SplitUrlRevision(parsed_url) + if origin in candidates: + return origin + if origin.endswith('.git') and origin[:-len('.git')] in candidates: + return origin[:-len('.git')] + if self.name in candidates: + return self.name + return None + # Arguments number differs from overridden method # pylint: disable=arguments-differ def run(self, revision_overrides, command, args, work_queue, options, @@ -950,10 +982,8 @@ class Dependency(gclient_utils.WorkItem, DependencySettings): 'flatten', 'runhooks', 'recurse', 'validate', None) parsed_url = self.LateOverride(self.url) file_list = [] if not options.nohooks else None - revision_override = revision_overrides.pop(self.name, None) - if parsed_url: - revision_override = revision_overrides.pop( - parsed_url.split('@')[0], revision_override) + revision_override = revision_overrides.pop( + self.FuzzyMatchUrl(parsed_url, revision_overrides), None) if run_scm and parsed_url: # Create a shallow copy to mutate revision. options = copy.copy(options) @@ -966,10 +996,11 @@ class Dependency(gclient_utils.WorkItem, DependencySettings): file_list) patch_repo = parsed_url.split('@')[0] - patch_ref = patch_refs.pop(patch_repo, patch_refs.pop(self.name, None)) + patch_ref = patch_refs.pop( + self.FuzzyMatchUrl(parsed_url, patch_refs), None) if command == 'update' and patch_ref is not None: self._used_scm.apply_patch_ref(patch_repo, patch_ref, options, - file_list) + file_list) if file_list: file_list = [os.path.join(self.name, f.strip()) for f in file_list] @@ -1795,14 +1826,9 @@ it or fix the checkout. work_queue.enqueue(s) work_queue.flush({}, None, [], options=self._options, patch_refs=None) - def ShouldPrintRevision(path, rev): - if not self._options.path and not self._options.url: - return True - if self._options.path and path in self._options.path: - return True - if self._options.url and rev and rev.split('@')[0] in self._options.url: - return True - return False + def ShouldPrintRevision(dep, rev): + return (not self._options.filter + or d.FuzzyMatchUrl(rev, self._options.filter)) def GetURLAndRev(dep): """Returns the revision-qualified SCM url for a Dependency.""" @@ -1824,7 +1850,7 @@ it or fix the checkout. """Recursively grab dependencies.""" for d in dep.dependencies: rev = GetURLAndRev(d) - if ShouldPrintRevision(d.name, rev): + if ShouldPrintRevision(d, rev): entries[d.name] = rev GrabDeps(d) GrabDeps(d) @@ -1852,7 +1878,7 @@ it or fix the checkout. rev = GetURLAndRev(d) else: rev = d.parsed_url - if ShouldPrintRevision(d.name, rev): + if ShouldPrintRevision(d, rev): entries[d.name] = rev if self._options.output_json: json_output = { @@ -2896,12 +2922,9 @@ def CMDrevinfo(parser, args): help='creates a snapshot .gclient file of the current ' 'version of all repositories to reproduce the tree, ' 'implies -a') - parser.add_option('-u', '--url', action='append', - help='Display revision information only for the specified ' - 'URLs.') - parser.add_option('-p', '--path', action='append', + parser.add_option('--filter', action='append', dest='filter', help='Display revision information only for the specified ' - 'paths.') + 'dependencies (filtered by URL or path).') parser.add_option('--output-json', help='Output a json document to this path containing ' 'information about the revisions.') diff --git a/tests/gclient_smoketest.py b/tests/gclient_smoketest.py index d480aff46a..e6e6d6b95e 100755 --- a/tests/gclient_smoketest.py +++ b/tests/gclient_smoketest.py @@ -702,7 +702,7 @@ class GClientSmokeGIT(GClientSmokeBase): return self.gclient(['config', self.git_base + 'repo_1', '--name', 'src']) self.gclient(['sync', '--deps', 'mac']) - results = self.gclient(['revinfo', '--deps', 'mac', '--path', 'src']) + results = self.gclient(['revinfo', '--deps', 'mac', '--filter', 'src']) out = ('src: %(base)srepo_1\n' % { 'base': self.git_base, @@ -715,7 +715,7 @@ class GClientSmokeGIT(GClientSmokeBase): self.gclient(['config', self.git_base + 'repo_1', '--name', 'src']) self.gclient(['sync', '--deps', 'mac']) results = self.gclient(['revinfo', '--deps', 'mac', - '--url', '%srepo_2' % self.git_base]) + '--filter', '%srepo_2' % self.git_base]) out = ('src/repo2: %(base)srepo_2@%(hash2)s\n' % { 'base': self.git_base, @@ -728,8 +728,8 @@ class GClientSmokeGIT(GClientSmokeBase): return self.gclient(['config', self.git_base + 'repo_1', '--name', 'src']) self.gclient(['sync', '--deps', 'mac']) - results = self.gclient(['revinfo', '--deps', 'mac', '--path', 'src', - '--url', '%srepo_2' % self.git_base]) + results = self.gclient(['revinfo', '--deps', 'mac', '--filter', 'src', + '--filter', '%srepo_2' % self.git_base]) out = ('src: %(base)srepo_1\n' 'src/repo2: %(base)srepo_2@%(hash2)s\n' % { diff --git a/tests/gclient_test.py b/tests/gclient_test.py index 1360581a68..2628a0fa66 100755 --- a/tests/gclient_test.py +++ b/tests/gclient_test.py @@ -1228,6 +1228,68 @@ class GclientTest(trial_dir.TestCase): self.assertEquals('https://example.com/foo_package@foo_version', dep0.url) self.assertEquals('https://example.com/bar_package@bar_version', dep1.url) + def testFuzzyMatchUrlByURL(self): + write( + '.gclient', + 'solutions = [\n' + ' { "name": "foo", "url": "https://example.com/foo.git",\n' + ' "deps_file" : ".DEPS.git",\n' + ' },\n' + ']') + write( + os.path.join('foo', 'DEPS'), + 'deps = {\n' + ' "bar": "https://example.com/bar.git@bar_version",\n' + '}') + options, _ = gclient.OptionParser().parse_args([]) + obj = gclient.GClient.LoadCurrentConfig(options) + foo_sol = obj.dependencies[0] + self.assertEqual( + 'https://example.com/foo.git', + foo_sol.FuzzyMatchUrl('https://example.com/foo.git', + ['https://example.com/foo.git', 'foo'])) + + def testFuzzyMatchUrlByURLNoGit(self): + write( + '.gclient', + 'solutions = [\n' + ' { "name": "foo", "url": "https://example.com/foo.git",\n' + ' "deps_file" : ".DEPS.git",\n' + ' },\n' + ']') + write( + os.path.join('foo', 'DEPS'), + 'deps = {\n' + ' "bar": "https://example.com/bar.git@bar_version",\n' + '}') + options, _ = gclient.OptionParser().parse_args([]) + obj = gclient.GClient.LoadCurrentConfig(options) + foo_sol = obj.dependencies[0] + self.assertEqual( + 'https://example.com/foo', + foo_sol.FuzzyMatchUrl('https://example.com/foo.git', + ['https://example.com/foo', 'foo'])) + + def testFuzzyMatchUrlByName(self): + write( + '.gclient', + 'solutions = [\n' + ' { "name": "foo", "url": "https://example.com/foo",\n' + ' "deps_file" : ".DEPS.git",\n' + ' },\n' + ']') + write( + os.path.join('foo', 'DEPS'), + 'deps = {\n' + ' "bar": "https://example.com/bar.git@bar_version",\n' + '}') + options, _ = gclient.OptionParser().parse_args([]) + obj = gclient.GClient.LoadCurrentConfig(options) + foo_sol = obj.dependencies[0] + self.assertEqual( + 'foo', + foo_sol.FuzzyMatchUrl('https://example.com/foo.git', ['foo'])) + if __name__ == '__main__': sys.stdout = gclient_utils.MakeFileAutoFlush(sys.stdout)