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 136 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
147 return not code | 147 return not code |
148 | 148 |
149 | 149 |
150 def time_sleep(seconds): | 150 def time_sleep(seconds): |
151 # Use this so that it can be mocked in tests without interfering with python | 151 # Use this so that it can be mocked in tests without interfering with python |
152 # system machinery. | 152 # system machinery. |
153 import time # Local import to discourage others from importing time globally. | 153 import time # Local import to discourage others from importing time globally. |
154 return time.sleep(seconds) | 154 return time.sleep(seconds) |
155 | 155 |
156 | 156 |
157 def time_time(): | |
158 # Use this so that it can be mocked in tests without interfering with python | |
159 # system machinery. | |
160 import time # Local import to discourage others from importing time globally. | |
161 return time.time() | |
162 | |
157 def ask_for_data(prompt): | 163 def ask_for_data(prompt): |
158 try: | 164 try: |
159 return raw_input(prompt) | 165 return raw_input(prompt) |
160 except KeyboardInterrupt: | 166 except KeyboardInterrupt: |
161 # Hide the exception. | 167 # Hide the exception. |
162 sys.exit(1) | 168 sys.exit(1) |
163 | 169 |
164 | 170 |
165 def _git_branch_config_key(branch, key): | 171 def _git_branch_config_key(branch, key): |
166 """Helper method to return Git config key for a branch.""" | 172 """Helper method to return Git config key for a branch.""" |
(...skipping 284 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
451 content = _buildbucket_retry('fetching try jobs', http, url, 'GET') | 457 content = _buildbucket_retry('fetching try jobs', http, url, 'GET') |
452 for build in content.get('builds', []): | 458 for build in content.get('builds', []): |
453 builds[build['id']] = build | 459 builds[build['id']] = build |
454 if 'next_cursor' in content: | 460 if 'next_cursor' in content: |
455 params['start_cursor'] = content['next_cursor'] | 461 params['start_cursor'] = content['next_cursor'] |
456 else: | 462 else: |
457 break | 463 break |
458 return builds | 464 return builds |
459 | 465 |
460 | 466 |
467 def _count_unfinished_tryjobs(jobs): | |
468 """Returns number of unfinished jobs from fetch_try_jobs result.""" | |
469 return sum(b['status'] != 'COMPLETED' for b in jobs.itervalues()) | |
Sergiy Byelozyorov
2016/10/19 15:41:13
perhaps
len(b for b in jobs.itervalues() if b['s
| |
470 | |
471 | |
461 def print_try_jobs(options, builds): | 472 def print_try_jobs(options, builds): |
462 """Prints nicely result of fetch_try_jobs.""" | 473 """Prints nicely result of fetch_try_jobs.""" |
463 if not builds: | 474 if not builds: |
464 print('No try jobs scheduled') | 475 print('No try jobs scheduled') |
465 return | 476 return |
466 | 477 |
467 # Make a copy, because we'll be modifying builds dictionary. | 478 # Make a copy, because we'll be modifying builds dictionary. |
468 builds = builds.copy() | 479 builds = builds.copy() |
469 builder_names_cache = {} | 480 builder_names_cache = {} |
470 | 481 |
(...skipping 4424 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
4895 group.add_option( | 4906 group.add_option( |
4896 '--print-master', action='store_true', help='print master name as well.') | 4907 '--print-master', action='store_true', help='print master name as well.') |
4897 group.add_option( | 4908 group.add_option( |
4898 '--color', action='store_true', default=setup_color.IS_TTY, | 4909 '--color', action='store_true', default=setup_color.IS_TTY, |
4899 help='force color output, useful when piping output.') | 4910 help='force color output, useful when piping output.') |
4900 group.add_option( | 4911 group.add_option( |
4901 '--buildbucket-host', default='cr-buildbucket.appspot.com', | 4912 '--buildbucket-host', default='cr-buildbucket.appspot.com', |
4902 help='Host of buildbucket. The default host is %default.') | 4913 help='Host of buildbucket. The default host is %default.') |
4903 group.add_option( | 4914 group.add_option( |
4904 '--json', help='Path of JSON output file to write try job results to.') | 4915 '--json', help='Path of JSON output file to write try job results to.') |
4916 group.add_option( | |
4917 '-w', '--wait-till-finished', action='store_true', default=False, | |
4918 help='Keep checking buildbucket until either all jobs finish. ' | |
Michael Achenbach
2016/10/20 09:40:35
nit: remove "either"?
| |
4919 'If after 1 hour jobs are still running, aborts and returns error ' | |
4920 'code 3.') | |
4905 parser.add_option_group(group) | 4921 parser.add_option_group(group) |
4906 auth.add_auth_options(parser) | 4922 auth.add_auth_options(parser) |
4907 options, args = parser.parse_args(args) | 4923 options, args = parser.parse_args(args) |
4908 if args: | 4924 if args: |
4909 parser.error('Unrecognized args: %s' % ' '.join(args)) | 4925 parser.error('Unrecognized args: %s' % ' '.join(args)) |
4910 | 4926 |
4911 auth_config = auth.extract_auth_config_from_options(options) | 4927 auth_config = auth.extract_auth_config_from_options(options) |
4912 cl = Changelist(auth_config=auth_config) | 4928 cl = Changelist(auth_config=auth_config) |
4913 if not cl.GetIssue(): | 4929 if not cl.GetIssue(): |
4914 parser.error('Need to upload first') | 4930 parser.error('Need to upload first') |
4915 | 4931 |
4916 patchset = options.patchset | 4932 patchset = options.patchset |
4917 if not patchset: | 4933 if not patchset: |
4918 patchset = cl.GetMostRecentPatchset() | 4934 patchset = cl.GetMostRecentPatchset() |
4919 if not patchset: | 4935 if not patchset: |
4920 parser.error('Codereview doesn\'t know about issue %s. ' | 4936 parser.error('Codereview doesn\'t know about issue %s. ' |
4921 'No access to issue or wrong issue number?\n' | 4937 'No access to issue or wrong issue number?\n' |
4922 'Either upload first, or pass --patchset explicitely' % | 4938 'Either upload first, or pass --patchset explicitely' % |
4923 cl.GetIssue()) | 4939 cl.GetIssue()) |
4924 | 4940 |
4925 if patchset != cl.GetPatchset(): | 4941 if patchset != cl.GetPatchset(): |
4926 print('Warning: Codereview server has newer patchsets (%s) than most ' | 4942 print('Warning: Codereview server has newer patchsets (%s) than most ' |
4927 'recent upload from local checkout (%s). Did a previous upload ' | 4943 'recent upload from local checkout (%s). Did a previous upload ' |
4928 'fail?\n' | 4944 'fail?\n' |
4929 'By default, git cl try-results uses the latest patchset from ' | 4945 'By default, git cl try-results uses the latest patchset from ' |
4930 'codereview, continuing to use patchset %s.\n' % | 4946 'codereview, continuing to use patchset %s.\n' % |
4931 (patchset, cl.GetPatchset(), patchset)) | 4947 (patchset, cl.GetPatchset(), patchset)) |
4932 try: | 4948 |
4933 jobs = fetch_try_jobs(auth_config, cl, options.buildbucket_host, patchset) | 4949 start_time = time_time() |
4934 except BuildbucketResponseException as ex: | 4950 while True: |
4935 print('Buildbucket error: %s' % ex) | 4951 try: |
4936 return 1 | 4952 jobs = fetch_try_jobs(auth_config, cl, options.buildbucket_host, patchset) |
4937 if options.json: | 4953 except BuildbucketResponseException as ex: |
4938 write_try_results_json(options.json, jobs) | 4954 print('Buildbucket error: %s' % ex) |
4939 else: | 4955 return 1 |
4940 print_try_jobs(options, jobs) | 4956 if options.json: |
4957 write_try_results_json(options.json, jobs) | |
Michael Achenbach
2016/10/20 09:40:35
Does this need to write the json in the loop? How
| |
4958 else: | |
4959 print_try_jobs(options, jobs) | |
4960 if not options.wait_till_finished: | |
4961 return 0 | |
Sergiy Byelozyorov
2016/10/19 15:41:13
Please "break", so that if someone chooses to add
| |
4962 | |
4963 # Only if --wait-till-finished is specified. | |
4964 unfinished = _count_unfinished_tryjobs(jobs) | |
4965 if not unfinished: | |
4966 return 0 | |
Sergiy Byelozyorov
2016/10/19 15:41:13
ditto
| |
4967 passed = time_time() - start_time | |
4968 print('After %.0f seconds waiting, %d jobs still running\n\n' % | |
Sergiy Byelozyorov
2016/10/19 15:41:13
Juse use %d instead of %.0f. It will round it to t
| |
4969 (passed, unfinished)) | |
4970 if passed > 3600: | |
Michael Achenbach
2016/10/20 09:40:35
Do you need a limit at all? Is this tool supposed
Sergiy Byelozyorov
2016/10/20 11:44:43
IMHO, this is useful to prevent users forgetting t
| |
4971 print('Ran for too long, aborting now.') | |
4972 return 3 | |
4973 time_sleep(10) # Limit unnecessary load on buildbucket. | |
Sergiy Byelozyorov
2016/10/19 15:41:13
If the option becomes widely popular, we may have
| |
4941 return 0 | 4974 return 0 |
4942 | 4975 |
4943 | 4976 |
4944 @subcommand.usage('[new upstream branch]') | 4977 @subcommand.usage('[new upstream branch]') |
4945 def CMDupstream(parser, args): | 4978 def CMDupstream(parser, args): |
4946 """Prints or sets the name of the upstream branch, if any.""" | 4979 """Prints or sets the name of the upstream branch, if any.""" |
4947 _, args = parser.parse_args(args) | 4980 _, args = parser.parse_args(args) |
4948 if len(args) > 1: | 4981 if len(args) > 1: |
4949 parser.error('Unrecognized args: %s' % ' '.join(args)) | 4982 parser.error('Unrecognized args: %s' % ' '.join(args)) |
4950 | 4983 |
(...skipping 428 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
5379 if __name__ == '__main__': | 5412 if __name__ == '__main__': |
5380 # These affect sys.stdout so do it outside of main() to simplify mocks in | 5413 # These affect sys.stdout so do it outside of main() to simplify mocks in |
5381 # unit testing. | 5414 # unit testing. |
5382 fix_encoding.fix_encoding() | 5415 fix_encoding.fix_encoding() |
5383 setup_color.init() | 5416 setup_color.init() |
5384 try: | 5417 try: |
5385 sys.exit(main(sys.argv[1:])) | 5418 sys.exit(main(sys.argv[1:])) |
5386 except KeyboardInterrupt: | 5419 except KeyboardInterrupt: |
5387 sys.stderr.write('interrupted\n') | 5420 sys.stderr.write('interrupted\n') |
5388 sys.exit(1) | 5421 sys.exit(1) |
OLD | NEW |