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.""" | 8 """A git-command for integrating reviews on Rietveld.""" |
9 | 9 |
10 from distutils.version import LooseVersion | 10 from distutils.version import LooseVersion |
(...skipping 821 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
832 return presubmit_support.GitChange( | 832 return presubmit_support.GitChange( |
833 name, | 833 name, |
834 description, | 834 description, |
835 absroot, | 835 absroot, |
836 files, | 836 files, |
837 issue, | 837 issue, |
838 patchset, | 838 patchset, |
839 author, | 839 author, |
840 upstream=upstream_branch) | 840 upstream=upstream_branch) |
841 | 841 |
| 842 def GetStatus(self): |
| 843 """Apply a rough heuristic to give a simple summary of an issue's review |
| 844 or CQ status, assuming adherence to a common workflow. |
| 845 |
| 846 Returns None if no issue for this branch, or one of the following keywords: |
| 847 * 'error' - error from review tool (including deleted issues) |
| 848 * 'unsent' - not sent for review |
| 849 * 'waiting' - waiting for review |
| 850 * 'reply' - waiting for owner to reply to review |
| 851 * 'lgtm' - LGTM from at least one approved reviewer |
| 852 * 'commit' - in the commit queue |
| 853 * 'closed' - closed |
| 854 """ |
| 855 if not self.GetIssue(): |
| 856 return None |
| 857 |
| 858 try: |
| 859 props = self.GetIssueProperties() |
| 860 except urllib2.HTTPError: |
| 861 return 'error' |
| 862 |
| 863 if props.get('closed'): |
| 864 # Issue is closed. |
| 865 return 'closed' |
| 866 if props.get('commit'): |
| 867 # Issue is in the commit queue. |
| 868 return 'commit' |
| 869 |
| 870 try: |
| 871 reviewers = self.GetApprovingReviewers() |
| 872 except urllib2.HTTPError: |
| 873 return 'error' |
| 874 |
| 875 if reviewers: |
| 876 # Was LGTM'ed. |
| 877 return 'lgtm' |
| 878 |
| 879 messages = props.get('messages') or [] |
| 880 |
| 881 if not messages: |
| 882 # No message was sent. |
| 883 return 'unsent' |
| 884 if messages[-1]['sender'] != props.get('owner_email'): |
| 885 # Non-LGTM reply from non-owner |
| 886 return 'reply' |
| 887 return 'waiting' |
| 888 |
842 def RunHook(self, committing, may_prompt, verbose, change): | 889 def RunHook(self, committing, may_prompt, verbose, change): |
843 """Calls sys.exit() if the hook fails; returns a HookResults otherwise.""" | 890 """Calls sys.exit() if the hook fails; returns a HookResults otherwise.""" |
844 | 891 |
845 try: | 892 try: |
846 return presubmit_support.DoPresubmitChecks(change, committing, | 893 return presubmit_support.DoPresubmitChecks(change, committing, |
847 verbose=verbose, output_stream=sys.stdout, input_stream=sys.stdin, | 894 verbose=verbose, output_stream=sys.stdout, input_stream=sys.stdin, |
848 default_presubmit=None, may_prompt=may_prompt, | 895 default_presubmit=None, may_prompt=may_prompt, |
849 rietveld_obj=self.RpcServer()) | 896 rietveld_obj=self.RpcServer()) |
850 except presubmit_support.PresubmitFailure, e: | 897 except presubmit_support.PresubmitFailure, e: |
851 DieWithError( | 898 DieWithError( |
(...skipping 359 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1211 if not args: | 1258 if not args: |
1212 print("Current base-url:") | 1259 print("Current base-url:") |
1213 return RunGit(['config', 'branch.%s.base-url' % branch], | 1260 return RunGit(['config', 'branch.%s.base-url' % branch], |
1214 error_ok=False).strip() | 1261 error_ok=False).strip() |
1215 else: | 1262 else: |
1216 print("Setting base-url to %s" % args[0]) | 1263 print("Setting base-url to %s" % args[0]) |
1217 return RunGit(['config', 'branch.%s.base-url' % branch, args[0]], | 1264 return RunGit(['config', 'branch.%s.base-url' % branch, args[0]], |
1218 error_ok=False).strip() | 1265 error_ok=False).strip() |
1219 | 1266 |
1220 | 1267 |
| 1268 def color_for_status(status): |
| 1269 """Maps a Changelist status to color, for CMDstatus and other tools.""" |
| 1270 return { |
| 1271 'unsent': Fore.RED, |
| 1272 'waiting': Fore.BLUE, |
| 1273 'reply': Fore.YELLOW, |
| 1274 'lgtm': Fore.GREEN, |
| 1275 'commit': Fore.MAGENTA, |
| 1276 'closed': Fore.CYAN, |
| 1277 'error': Fore.WHITE, |
| 1278 }.get(status, Fore.WHITE) |
| 1279 |
| 1280 |
1221 def CMDstatus(parser, args): | 1281 def CMDstatus(parser, args): |
1222 """Show status of changelists. | 1282 """Show status of changelists. |
1223 | 1283 |
1224 Colors are used to tell the state of the CL unless --fast is used: | 1284 Colors are used to tell the state of the CL unless --fast is used: |
1225 - Red not sent for review or broken | 1285 - Red not sent for review or broken |
1226 - Blue waiting for review | 1286 - Blue waiting for review |
1227 - Yellow waiting for you to reply to review | 1287 - Yellow waiting for you to reply to review |
1228 - Green LGTM'ed | 1288 - Green LGTM'ed |
1229 - Magenta in the commit queue | 1289 - Magenta in the commit queue |
1230 - Cyan was committed, branch can be deleted | 1290 - Cyan was committed, branch can be deleted |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1270 output = Queue.Queue() | 1330 output = Queue.Queue() |
1271 | 1331 |
1272 # Silence upload.py otherwise it becomes unweldly. | 1332 # Silence upload.py otherwise it becomes unweldly. |
1273 upload.verbosity = 0 | 1333 upload.verbosity = 0 |
1274 | 1334 |
1275 if not options.fast: | 1335 if not options.fast: |
1276 def fetch(b): | 1336 def fetch(b): |
1277 """Fetches information for an issue and returns (branch, issue, color).""" | 1337 """Fetches information for an issue and returns (branch, issue, color).""" |
1278 c = Changelist(branchref=b) | 1338 c = Changelist(branchref=b) |
1279 i = c.GetIssueURL() | 1339 i = c.GetIssueURL() |
1280 props = {} | 1340 status = c.GetStatus() |
1281 r = None | 1341 color = color_for_status(status) |
1282 if i: | |
1283 try: | |
1284 props = c.GetIssueProperties() | |
1285 r = c.GetApprovingReviewers() if i else None | |
1286 except urllib2.HTTPError: | |
1287 # The issue probably doesn't exist anymore. | |
1288 i += ' (broken)' | |
1289 | 1342 |
1290 msgs = props.get('messages') or [] | 1343 if i and (not status or status == 'error'): |
| 1344 # The issue probably doesn't exist anymore. |
| 1345 i += ' (broken)' |
1291 | 1346 |
1292 if not i: | |
1293 color = Fore.WHITE | |
1294 elif props.get('closed'): | |
1295 # Issue is closed. | |
1296 color = Fore.CYAN | |
1297 elif props.get('commit'): | |
1298 # Issue is in the commit queue. | |
1299 color = Fore.MAGENTA | |
1300 elif r: | |
1301 # Was LGTM'ed. | |
1302 color = Fore.GREEN | |
1303 elif not msgs: | |
1304 # No message was sent. | |
1305 color = Fore.RED | |
1306 elif msgs[-1]['sender'] != props.get('owner_email'): | |
1307 color = Fore.YELLOW | |
1308 else: | |
1309 color = Fore.BLUE | |
1310 output.put((b, i, color)) | 1347 output.put((b, i, color)) |
1311 | 1348 |
1312 # Process one branch synchronously to work through authentication, then | 1349 # Process one branch synchronously to work through authentication, then |
1313 # spawn threads to process all the other branches in parallel. | 1350 # spawn threads to process all the other branches in parallel. |
1314 if branches: | 1351 if branches: |
1315 fetch(branches[0]) | 1352 fetch(branches[0]) |
1316 threads = [ | 1353 threads = [ |
1317 threading.Thread(target=fetch, args=(b,)) for b in branches[1:]] | 1354 threading.Thread(target=fetch, args=(b,)) for b in branches[1:]] |
1318 for t in threads: | 1355 for t in threads: |
1319 t.daemon = True | 1356 t.daemon = True |
(...skipping 1517 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2837 ('AppEngine is misbehaving and returned HTTP %d, again. Keep faith ' | 2874 ('AppEngine is misbehaving and returned HTTP %d, again. Keep faith ' |
2838 'and retry or visit go/isgaeup.\n%s') % (e.code, str(e))) | 2875 'and retry or visit go/isgaeup.\n%s') % (e.code, str(e))) |
2839 | 2876 |
2840 | 2877 |
2841 if __name__ == '__main__': | 2878 if __name__ == '__main__': |
2842 # These affect sys.stdout so do it outside of main() to simplify mocks in | 2879 # These affect sys.stdout so do it outside of main() to simplify mocks in |
2843 # unit testing. | 2880 # unit testing. |
2844 fix_encoding.fix_encoding() | 2881 fix_encoding.fix_encoding() |
2845 colorama.init() | 2882 colorama.init() |
2846 sys.exit(main(sys.argv[1:])) | 2883 sys.exit(main(sys.argv[1:])) |
OLD | NEW |