OLD | NEW |
---|---|
1 # Copyright 2016 The Chromium Authors. All rights reserved. | 1 # Copyright 2016 The Chromium Authors. All rights reserved. |
2 # Use of this source code is governed by a BSD-style license that can be | 2 # Use of this source code is governed by a BSD-style license that can be |
3 # found in the LICENSE file. | 3 # found in the LICENSE file. |
4 | 4 |
5 import collections | 5 import collections |
6 import urlparse | |
7 | |
8 from dashboard.services import gerrit_service | |
6 | 9 |
7 | 10 |
8 class Patch(collections.namedtuple('Patch', ('server', 'issue', 'patchset'))): | 11 def FromDict(data): |
9 """A patch in Rietveld.""" | 12 # If we have more Patch types in the future, we can loop |
10 # TODO: Support Gerrit. | 13 # through them all and try each one's FromDict() in turn. |
11 # https://github.com/catapult-project/catapult/issues/3599 | 14 return GerritPatch.FromDict(data) |
15 | |
16 | |
17 class GerritPatch(collections.namedtuple( | |
18 'GerritPatch', ('server', 'change', 'revision'))): | |
19 """A patch in Gerrit. | |
20 | |
21 change is a change ID of the format '<project>~<branch>~<Change-Id>' and | |
22 revision is a commit ID. Both are described in the Gerrit API documentation. | |
23 https://gerrit-review.googlesource.com/Documentation/rest-api-changes.html#ids | |
24 | |
25 They must be in a canonical format so we can look up builds precisely. | |
26 """ | |
12 | 27 |
13 def __str__(self): | 28 def __str__(self): |
14 return self.id_string | 29 return self.id_string |
15 | 30 |
16 @property | 31 @property |
17 def id_string(self): | 32 def id_string(self): |
18 return '%s/%d/%d' % (self.server, self.issue, self.patchset) | 33 return '%s/%s/%s' % (self.server, self.change, self.revision) |
34 | |
35 def BuildParameters(self): | |
36 patch_info = gerrit_service.GetChange( | |
37 self.server, self.change, fields=('ALL_REVISIONS',)) | |
38 revision_info = patch_info['revisions'][self.revision] | |
39 return { | |
40 'patch_gerrit_url': self.server, | |
41 'patch_issue': patch_info['_number'], | |
42 'patch_project': patch_info['project'], | |
43 'patch_ref': revision_info['fetch']['http']['ref'], | |
44 'patch_repository_url': revision_info['fetch']['http']['url'], | |
45 'patch_set': revision_info['_number'], | |
46 'patch_storage': 'gerrit', | |
47 } | |
19 | 48 |
20 def AsDict(self): | 49 def AsDict(self): |
21 return self._asdict() | 50 return self._asdict() |
22 | 51 |
23 @classmethod | 52 @classmethod |
24 def FromDict(cls, data): | 53 def FromDict(cls, data): |
25 # TODO: Validate to ensure the patch exists on the server. | 54 """Creates a new GerritPatch from the given data. |
26 return cls(data['server'], data['issue'], data['patchset']) | 55 |
56 Args: | |
57 data: A patch URL string, or | |
58 A dict containing {server, change, revision [optional]}. | |
59 change is a {change-id} as described in the Gerrit API documentation. | |
60 revision is a commit ID hash or numeric patch number. | |
61 If revision is omitted, it is the change's current revision. | |
62 | |
63 Returns: | |
64 A GerritPatch. | |
65 | |
66 Raises: | |
67 KeyError: The patch doesn't have the given revision. | |
68 """ | |
69 if isinstance(data, basestring): | |
70 url_parts = urlparse.urlparse(data) | |
perezju
2017/09/25 09:22:21
nit: Add a small comment with an example of how su
dtu
2017/09/25 20:29:55
Done.
| |
71 server = urlparse.urlunsplit( | |
72 (url_parts.scheme, url_parts.netloc, '', '', '')) | |
73 change = url_parts.path.rsplit('/', 1)[-1] | |
74 revision = None | |
75 else: | |
76 server = data['server'] | |
77 change = data['change'] | |
78 revision = data.get('revision') | |
79 | |
80 # Look up the patch and convert everything to a canonical format. | |
81 patch_info = gerrit_service.GetChange( | |
82 server, change, fields=('ALL_REVISIONS',)) | |
83 change = patch_info['id'] | |
84 | |
85 # Revision can be a revision ID or numeric patch number. | |
86 if not revision: | |
87 revision = patch_info['current_revision'] | |
88 for revision_id, revision_info in patch_info['revisions'].iteritems(): | |
89 if revision == revision_id or revision == revision_info['_number']: | |
90 revision = revision_id | |
91 break | |
92 else: | |
93 raise KeyError('Patch revision not found: %s/%s revision %s' % | |
94 (server, change, revision)) | |
95 | |
96 return cls(server, change, revision) | |
OLD | NEW |