Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 #!/usr/bin/env python | 1 #!/usr/bin/env python |
| 2 # Copyright (c) 2012 The Chromium Authors. All rights reserved. | 2 # Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 3 # Use of this source code is governed by a BSD-style license that can be | 3 # Use of this source code is governed by a BSD-style license that can be |
| 4 # found in the LICENSE file. | 4 # found in the LICENSE file. |
| 5 | 5 |
| 6 # Copyright (C) 2008 Evan Martin <martine@danga.com> | 6 # Copyright (C) 2008 Evan Martin <martine@danga.com> |
| 7 | 7 |
| 8 """A git-command for integrating reviews on Rietveld and Gerrit.""" | 8 """A git-command for integrating reviews on Rietveld and Gerrit.""" |
| 9 | 9 |
| 10 from __future__ import print_function | 10 from __future__ import print_function |
| (...skipping 959 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 970 parsed_url = urlparse.urlparse(url) | 970 parsed_url = urlparse.urlparse(url) |
| 971 except ValueError: | 971 except ValueError: |
| 972 return fail_result | 972 return fail_result |
| 973 for cls in _CODEREVIEW_IMPLEMENTATIONS.itervalues(): | 973 for cls in _CODEREVIEW_IMPLEMENTATIONS.itervalues(): |
| 974 tmp = cls.ParseIssueURL(parsed_url) | 974 tmp = cls.ParseIssueURL(parsed_url) |
| 975 if tmp is not None: | 975 if tmp is not None: |
| 976 return tmp | 976 return tmp |
| 977 return fail_result | 977 return fail_result |
| 978 | 978 |
| 979 | 979 |
| 980 class GerritIssueNotExists(Exception): | |
|
Sergiy Byelozyorov
2016/10/10 11:41:11
IMHO it should be either GerritIssueExistsNot or G
tandrii(chromium)
2016/10/10 15:10:14
I appreciate your review, but I think NotExists is
| |
| 981 def __init__(self, issue, url): | |
| 982 self.issue = issue | |
| 983 self.url = url | |
| 984 super(GerritIssueNotExists, self).__init__() | |
| 985 | |
| 986 def __str__(self): | |
| 987 return 'issue %s at %s does not exist or you have no access to it' % ( | |
| 988 self.issue, self.url) | |
| 989 | |
| 990 | |
| 980 class Changelist(object): | 991 class Changelist(object): |
| 981 """Changelist works with one changelist in local branch. | 992 """Changelist works with one changelist in local branch. |
| 982 | 993 |
| 983 Supports two codereview backends: Rietveld or Gerrit, selected at object | 994 Supports two codereview backends: Rietveld or Gerrit, selected at object |
| 984 creation. | 995 creation. |
| 985 | 996 |
| 986 Notes: | 997 Notes: |
| 987 * Not safe for concurrent multi-{thread,process} use. | 998 * Not safe for concurrent multi-{thread,process} use. |
| 988 * Caches values from current branch. Therefore, re-use after branch change | 999 * Caches values from current branch. Therefore, re-use after branch change |
| 989 with great care. | 1000 with great care. |
| (...skipping 1261 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2251 | 2262 |
| 2252 def GetStatus(self): | 2263 def GetStatus(self): |
| 2253 """Apply a rough heuristic to give a simple summary of an issue's review | 2264 """Apply a rough heuristic to give a simple summary of an issue's review |
| 2254 or CQ status, assuming adherence to a common workflow. | 2265 or CQ status, assuming adherence to a common workflow. |
| 2255 | 2266 |
| 2256 Returns None if no issue for this branch, or one of the following keywords: | 2267 Returns None if no issue for this branch, or one of the following keywords: |
| 2257 * 'error' - error from review tool (including deleted issues) | 2268 * 'error' - error from review tool (including deleted issues) |
| 2258 * 'unsent' - no reviewers added | 2269 * 'unsent' - no reviewers added |
| 2259 * 'waiting' - waiting for review | 2270 * 'waiting' - waiting for review |
| 2260 * 'reply' - waiting for owner to reply to review | 2271 * 'reply' - waiting for owner to reply to review |
| 2261 * 'not lgtm' - Code-Review -2 from at least one approved reviewer | 2272 * 'not lgtm' - Code-Review disaproval from at least one valid reviewer |
| 2262 * 'lgtm' - Code-Review +2 from at least one approved reviewer | 2273 * 'lgtm' - Code-Review approval from at least one valid reviewer |
| 2263 * 'commit' - in the commit queue | 2274 * 'commit' - in the commit queue |
| 2264 * 'closed' - abandoned | 2275 * 'closed' - abandoned |
| 2265 """ | 2276 """ |
| 2266 if not self.GetIssue(): | 2277 if not self.GetIssue(): |
| 2267 return None | 2278 return None |
| 2268 | 2279 |
| 2269 try: | 2280 try: |
| 2270 data = self._GetChangeDetail(['DETAILED_LABELS', 'CURRENT_REVISION']) | 2281 data = self._GetChangeDetail(['DETAILED_LABELS', 'CURRENT_REVISION']) |
| 2271 except httplib.HTTPException: | 2282 except (httplib.HTTPException, GerritIssueNotExists): |
| 2272 return 'error' | 2283 return 'error' |
| 2273 | 2284 |
| 2274 if data['status'] in ('ABANDONED', 'MERGED'): | 2285 if data['status'] in ('ABANDONED', 'MERGED'): |
| 2275 return 'closed' | 2286 return 'closed' |
| 2276 | 2287 |
| 2277 cq_label = data['labels'].get('Commit-Queue', {}) | 2288 cq_label = data['labels'].get('Commit-Queue', {}) |
| 2278 if cq_label: | 2289 if cq_label: |
| 2279 # Vote value is a stringified integer, which we expect from 0 to 2. | 2290 # Vote value is a stringified integer, which we expect from 0 to 2. |
| 2280 vote_value = cq_label.get('value', '0') | 2291 vote_value = cq_label.get('value', '0') |
| 2281 vote_text = cq_label.get('values', {}).get(vote_value, '') | 2292 vote_text = cq_label.get('values', {}).get(vote_value, '') |
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2336 """ | 2347 """ |
| 2337 raise NotImplementedError() | 2348 raise NotImplementedError() |
| 2338 | 2349 |
| 2339 def SubmitIssue(self, wait_for_merge=True): | 2350 def SubmitIssue(self, wait_for_merge=True): |
| 2340 gerrit_util.SubmitChange(self._GetGerritHost(), self.GetIssue(), | 2351 gerrit_util.SubmitChange(self._GetGerritHost(), self.GetIssue(), |
| 2341 wait_for_merge=wait_for_merge) | 2352 wait_for_merge=wait_for_merge) |
| 2342 | 2353 |
| 2343 def _GetChangeDetail(self, options=None, issue=None): | 2354 def _GetChangeDetail(self, options=None, issue=None): |
| 2344 options = options or [] | 2355 options = options or [] |
| 2345 issue = issue or self.GetIssue() | 2356 issue = issue or self.GetIssue() |
| 2346 assert issue, 'issue required to query Gerrit' | 2357 assert issue, 'issue is required to query Gerrit' |
| 2347 return gerrit_util.GetChangeDetail(self._GetGerritHost(), str(issue), | 2358 data = gerrit_util.GetChangeDetail(self._GetGerritHost(), str(issue), |
| 2348 options) | 2359 options) |
| 2360 if not data: | |
| 2361 raise GerritIssueNotExists(issue, self.GetCodereviewServer()) | |
| 2362 return data | |
| 2349 | 2363 |
| 2350 def CMDLand(self, force, bypass_hooks, verbose): | 2364 def CMDLand(self, force, bypass_hooks, verbose): |
| 2351 if git_common.is_dirty_git_tree('land'): | 2365 if git_common.is_dirty_git_tree('land'): |
| 2352 return 1 | 2366 return 1 |
| 2353 detail = self._GetChangeDetail(['CURRENT_REVISION', 'LABELS']) | 2367 detail = self._GetChangeDetail(['CURRENT_REVISION', 'LABELS']) |
| 2354 if u'Commit-Queue' in detail.get('labels', {}): | 2368 if u'Commit-Queue' in detail.get('labels', {}): |
| 2355 if not force: | 2369 if not force: |
| 2356 ask_for_data('\nIt seems this repository has a Commit Queue, ' | 2370 ask_for_data('\nIt seems this repository has a Commit Queue, ' |
| 2357 'which can test and land changes for you. ' | 2371 'which can test and land changes for you. ' |
| 2358 'Are you sure you wish to bypass it?\n' | 2372 'Are you sure you wish to bypass it?\n' |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2393 assert not nocommit | 2407 assert not nocommit |
| 2394 assert not directory | 2408 assert not directory |
| 2395 assert parsed_issue_arg.valid | 2409 assert parsed_issue_arg.valid |
| 2396 | 2410 |
| 2397 self._changelist.issue = parsed_issue_arg.issue | 2411 self._changelist.issue = parsed_issue_arg.issue |
| 2398 | 2412 |
| 2399 if parsed_issue_arg.hostname: | 2413 if parsed_issue_arg.hostname: |
| 2400 self._gerrit_host = parsed_issue_arg.hostname | 2414 self._gerrit_host = parsed_issue_arg.hostname |
| 2401 self._gerrit_server = 'https://%s' % self._gerrit_host | 2415 self._gerrit_server = 'https://%s' % self._gerrit_host |
| 2402 | 2416 |
| 2403 detail = self._GetChangeDetail(['ALL_REVISIONS']) | 2417 try: |
| 2418 detail = self._GetChangeDetail(['ALL_REVISIONS']) | |
| 2419 except GerritIssueNotExists as e: | |
| 2420 DieWithError(str(e)) | |
| 2404 | 2421 |
| 2405 if not parsed_issue_arg.patchset: | 2422 if not parsed_issue_arg.patchset: |
| 2406 # Use current revision by default. | 2423 # Use current revision by default. |
| 2407 revision_info = detail['revisions'][detail['current_revision']] | 2424 revision_info = detail['revisions'][detail['current_revision']] |
| 2408 patchset = int(revision_info['_number']) | 2425 patchset = int(revision_info['_number']) |
| 2409 else: | 2426 else: |
| 2410 patchset = parsed_issue_arg.patchset | 2427 patchset = parsed_issue_arg.patchset |
| 2411 for revision_info in detail['revisions'].itervalues(): | 2428 for revision_info in detail['revisions'].itervalues(): |
| 2412 if int(revision_info['_number']) == parsed_issue_arg.patchset: | 2429 if int(revision_info['_number']) == parsed_issue_arg.patchset: |
| 2413 break | 2430 break |
| (...skipping 2903 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 5317 if __name__ == '__main__': | 5334 if __name__ == '__main__': |
| 5318 # These affect sys.stdout so do it outside of main() to simplify mocks in | 5335 # These affect sys.stdout so do it outside of main() to simplify mocks in |
| 5319 # unit testing. | 5336 # unit testing. |
| 5320 fix_encoding.fix_encoding() | 5337 fix_encoding.fix_encoding() |
| 5321 setup_color.init() | 5338 setup_color.init() |
| 5322 try: | 5339 try: |
| 5323 sys.exit(main(sys.argv[1:])) | 5340 sys.exit(main(sys.argv[1:])) |
| 5324 except KeyboardInterrupt: | 5341 except KeyboardInterrupt: |
| 5325 sys.stderr.write('interrupted\n') | 5342 sys.stderr.write('interrupted\n') |
| 5326 sys.exit(1) | 5343 sys.exit(1) |
| OLD | NEW |