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 distutils.version import LooseVersion | 10 from distutils.version import LooseVersion |
11 from multiprocessing.pool import ThreadPool | 11 from multiprocessing.pool import ThreadPool |
12 import base64 | 12 import base64 |
13 import collections | 13 import collections |
14 import glob | 14 import glob |
15 import httplib | 15 import httplib |
16 import json | 16 import json |
17 import logging | 17 import logging |
18 import optparse | 18 import optparse |
19 import os | 19 import os |
20 import Queue | |
21 import re | 20 import re |
22 import stat | 21 import stat |
23 import sys | 22 import sys |
24 import tempfile | |
25 import textwrap | 23 import textwrap |
26 import time | 24 import time |
27 import traceback | 25 import traceback |
28 import urllib | 26 import urllib |
29 import urllib2 | 27 import urllib2 |
30 import urlparse | 28 import urlparse |
31 import uuid | 29 import uuid |
32 import webbrowser | 30 import webbrowser |
33 import zlib | 31 import zlib |
34 | 32 |
(...skipping 2854 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2889 return { | 2887 return { |
2890 'unsent': Fore.RED, | 2888 'unsent': Fore.RED, |
2891 'waiting': Fore.BLUE, | 2889 'waiting': Fore.BLUE, |
2892 'reply': Fore.YELLOW, | 2890 'reply': Fore.YELLOW, |
2893 'lgtm': Fore.GREEN, | 2891 'lgtm': Fore.GREEN, |
2894 'commit': Fore.MAGENTA, | 2892 'commit': Fore.MAGENTA, |
2895 'closed': Fore.CYAN, | 2893 'closed': Fore.CYAN, |
2896 'error': Fore.WHITE, | 2894 'error': Fore.WHITE, |
2897 }.get(status, Fore.WHITE) | 2895 }.get(status, Fore.WHITE) |
2898 | 2896 |
2899 def fetch_cl_status(branch, auth_config=None): | 2897 def fetch_cl_status(cl, auth_config=None): |
tandrii(chromium)
2016/04/15 15:38:35
auth_config isn't needed any more.
| |
2900 """Fetches information for an issue and returns (branch, issue, status).""" | 2898 """Fetches information for an issue and returns (branch, issue, status).""" |
2901 cl = Changelist(branchref=branch, auth_config=auth_config) | |
2902 url = cl.GetIssueURL() | 2899 url = cl.GetIssueURL() |
2903 status = cl.GetStatus() | 2900 status = cl.GetStatus() |
2904 | 2901 |
2905 if url and (not status or status == 'error'): | 2902 if url and (not status or status == 'error'): |
2906 # The issue probably doesn't exist anymore. | 2903 # The issue probably doesn't exist anymore. |
2907 url += ' (broken)' | 2904 url += ' (broken)' |
tandrii(chromium)
2016/04/15 15:38:35
i think with your awesome refactoring, we can go f
Clemens Hammacher
2016/04/21 12:54:46
Removing this function would conflict with this ot
| |
2908 | 2905 |
2909 return (branch, url, status) | 2906 return (cl, url, status) |
2910 | 2907 |
2911 def get_cl_statuses( | 2908 def get_cl_statuses( |
2912 branches, fine_grained, max_processes=None, auth_config=None): | 2909 changes, fine_grained, max_processes=None, auth_config=None): |
2913 """Returns a blocking iterable of (branch, issue, color) for given branches. | 2910 """Returns a blocking iterable of (branch, issue, color) for given branches. |
2914 | 2911 |
2915 If fine_grained is true, this will fetch CL statuses from the server. | 2912 If fine_grained is true, this will fetch CL statuses from the server. |
2916 Otherwise, simply indicate if there's a matching url for the given branches. | 2913 Otherwise, simply indicate if there's a matching url for the given branches. |
2917 | 2914 |
2918 If max_processes is specified, it is used as the maximum number of processes | 2915 If max_processes is specified, it is used as the maximum number of processes |
2919 to spawn to fetch CL status from the server. Otherwise 1 process per branch is | 2916 to spawn to fetch CL status from the server. Otherwise 1 process per branch is |
2920 spawned. | 2917 spawned. |
2921 """ | 2918 """ |
2922 # Silence upload.py otherwise it becomes unwieldly. | 2919 # Silence upload.py otherwise it becomes unwieldly. |
2923 upload.verbosity = 0 | 2920 upload.verbosity = 0 |
2924 | 2921 |
2925 if fine_grained: | 2922 if fine_grained: |
2926 # Process one branch synchronously to work through authentication, then | 2923 # Process one branch synchronously to work through authentication, then |
2927 # spawn processes to process all the other branches in parallel. | 2924 # spawn processes to process all the other branches in parallel. |
2928 if branches: | 2925 if changes: |
2929 fetch = lambda branch: fetch_cl_status(branch, auth_config=auth_config) | 2926 fetch = lambda cl: fetch_cl_status(cl, auth_config=auth_config) |
tandrii(chromium)
2016/04/15 15:38:35
so based on above comment, i propose to change thi
| |
2930 yield fetch(branches[0]) | 2927 yield fetch(changes[0]) |
2931 | 2928 |
2932 branches_to_fetch = branches[1:] | 2929 changes_to_fetch = changes[1:] |
2933 pool = ThreadPool( | 2930 pool = ThreadPool( |
2934 min(max_processes, len(branches_to_fetch)) | 2931 min(max_processes, len(changes_to_fetch)) |
2935 if max_processes is not None | 2932 if max_processes is not None |
2936 else len(branches_to_fetch)) | 2933 else len(changes_to_fetch)) |
2937 for x in pool.imap_unordered(fetch, branches_to_fetch): | 2934 for x in pool.imap_unordered(fetch, changes_to_fetch): |
2938 yield x | 2935 yield x |
2939 else: | 2936 else: |
2940 # Do not use GetApprovingReviewers(), since it requires an HTTP request. | 2937 # Do not use GetApprovingReviewers(), since it requires an HTTP request. |
2941 for b in branches: | 2938 for c in changes: |
2942 cl = Changelist(branchref=b, auth_config=auth_config) | 2939 cl = Changelist(branchref=c.GetBranch(), auth_config=auth_config) |
tandrii(chromium)
2016/04/15 15:38:35
I think you can just use one from changes list, an
| |
2943 url = cl.GetIssueURL() | 2940 url = cl.GetIssueURL() |
2944 yield (b, url, 'waiting' if url else 'error') | 2941 yield (c, url, 'waiting' if url else 'error') |
tandrii(chromium)
2016/04/15 15:38:35
and based on refactoring suggestion for line 2926,
| |
2945 | 2942 |
2946 | 2943 |
2947 def upload_branch_deps(cl, args): | 2944 def upload_branch_deps(cl, args): |
2948 """Uploads CLs of local branches that are dependents of the current branch. | 2945 """Uploads CLs of local branches that are dependents of the current branch. |
2949 | 2946 |
2950 If the local branch dependency tree looks like: | 2947 If the local branch dependency tree looks like: |
2951 test1 -> test2.1 -> test3.1 | 2948 test1 -> test2.1 -> test3.1 |
2952 -> test3.2 | 2949 -> test3.2 |
2953 -> test2.2 -> test3.3 | 2950 -> test2.2 -> test3.3 |
2954 | 2951 |
(...skipping 132 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3087 url = cl.GetIssueURL() | 3084 url = cl.GetIssueURL() |
3088 if url: | 3085 if url: |
3089 print url | 3086 print url |
3090 return 0 | 3087 return 0 |
3091 | 3088 |
3092 branches = RunGit(['for-each-ref', '--format=%(refname)', 'refs/heads']) | 3089 branches = RunGit(['for-each-ref', '--format=%(refname)', 'refs/heads']) |
3093 if not branches: | 3090 if not branches: |
3094 print('No local branch found.') | 3091 print('No local branch found.') |
3095 return 0 | 3092 return 0 |
3096 | 3093 |
3097 changes = ( | 3094 changes = [ |
3098 Changelist(branchref=b, auth_config=auth_config) | 3095 Changelist(branchref=b, auth_config=auth_config) |
3099 for b in branches.splitlines()) | 3096 for b in branches.splitlines()] |
3100 # TODO(tandrii): refactor to use CLs list instead of branches list. | |
3101 branches = [c.GetBranch() for c in changes] | |
3102 alignment = max(5, max(len(b) for b in branches)) | |
3103 print 'Branches associated with reviews:' | 3097 print 'Branches associated with reviews:' |
3104 output = get_cl_statuses(branches, | 3098 output = get_cl_statuses(changes, |
3105 fine_grained=not options.fast, | 3099 fine_grained=not options.fast, |
3106 max_processes=options.maxjobs, | 3100 max_processes=options.maxjobs, |
3107 auth_config=auth_config) | 3101 auth_config=auth_config) |
3108 | 3102 |
3109 branch_statuses = {} | 3103 branch_statuses = {} |
3110 alignment = max(5, max(len(ShortBranchName(b)) for b in branches)) | 3104 alignment = max(5, max(len(ShortBranchName(c.GetBranch())) for c in changes)) |
3111 for branch in sorted(branches): | 3105 for cl in sorted(changes, key = lambda c : c.GetBranch()): |
tandrii(chromium)
2016/04/15 15:38:35
nits: no space before ":" and no space around "="
| |
3106 branch = cl.GetBranch() | |
3112 while branch not in branch_statuses: | 3107 while branch not in branch_statuses: |
3113 b, i, status = output.next() | 3108 c, i, status = output.next() |
3114 branch_statuses[b] = (i, status) | 3109 branch_statuses[c.GetBranch()] = (i, status) |
3115 issue_url, status = branch_statuses.pop(branch) | 3110 issue_url, status = branch_statuses.pop(branch) |
3116 color = color_for_status(status) | 3111 color = color_for_status(status) |
3117 reset = Fore.RESET | 3112 reset = Fore.RESET |
3118 if not setup_color.IS_TTY: | 3113 if not setup_color.IS_TTY: |
3119 color = '' | 3114 color = '' |
3120 reset = '' | 3115 reset = '' |
3121 status_str = '(%s)' % status if status else '' | 3116 status_str = '(%s)' % status if status else '' |
3122 print ' %*s : %s%s %s%s' % ( | 3117 print ' %*s : %s%s %s%s' % ( |
3123 alignment, ShortBranchName(branch), color, issue_url, status_str, | 3118 alignment, ShortBranchName(branch), color, issue_url, |
3124 reset) | 3119 status_str, reset) |
3125 | 3120 |
3126 cl = Changelist(auth_config=auth_config) | 3121 cl = Changelist(auth_config=auth_config) |
3127 print | 3122 print |
3128 print 'Current branch:', | 3123 print 'Current branch:', |
3129 print cl.GetBranch() | 3124 print cl.GetBranch() |
3130 if not cl.GetIssue(): | 3125 if not cl.GetIssue(): |
3131 print 'No issue assigned.' | 3126 print 'No issue assigned.' |
3132 return 0 | 3127 return 0 |
3133 print 'Issue number: %s (%s)' % (cl.GetIssue(), cl.GetIssueURL()) | 3128 print 'Issue number: %s (%s)' % (cl.GetIssue(), cl.GetIssueURL()) |
3134 if not options.fast: | 3129 if not options.fast: |
(...skipping 1690 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
4825 if __name__ == '__main__': | 4820 if __name__ == '__main__': |
4826 # These affect sys.stdout so do it outside of main() to simplify mocks in | 4821 # These affect sys.stdout so do it outside of main() to simplify mocks in |
4827 # unit testing. | 4822 # unit testing. |
4828 fix_encoding.fix_encoding() | 4823 fix_encoding.fix_encoding() |
4829 setup_color.init() | 4824 setup_color.init() |
4830 try: | 4825 try: |
4831 sys.exit(main(sys.argv[1:])) | 4826 sys.exit(main(sys.argv[1:])) |
4832 except KeyboardInterrupt: | 4827 except KeyboardInterrupt: |
4833 sys.stderr.write('interrupted\n') | 4828 sys.stderr.write('interrupted\n') |
4834 sys.exit(1) | 4829 sys.exit(1) |
OLD | NEW |