Index: git_cl.py |
diff --git a/git_cl.py b/git_cl.py |
index bcd4a6252b018978cc860b3ebebf75dd6f197d54..66b180688f1e906ad1946b2b1863e2b90e8129ea 100755 |
--- a/git_cl.py |
+++ b/git_cl.py |
@@ -12,6 +12,7 @@ import base64 |
import glob |
import json |
import logging |
+import multiprocessing |
import optparse |
import os |
import Queue |
@@ -20,7 +21,6 @@ import stat |
import sys |
import tempfile |
import textwrap |
-import threading |
import urllib2 |
import urlparse |
import webbrowser |
@@ -1338,6 +1338,51 @@ def color_for_status(status): |
'error': Fore.WHITE, |
}.get(status, Fore.WHITE) |
+def fetch_cl_status(b): |
+ """Fetches information for an issue and returns (branch, issue, color).""" |
+ c = Changelist(branchref=b) |
+ i = c.GetIssueURL() |
+ status = c.GetStatus() |
+ color = color_for_status(status) |
+ |
+ if i and (not status or status == 'error'): |
+ # The issue probably doesn't exist anymore. |
+ i += ' (broken)' |
+ |
+ return (b, i, color) |
+ |
+def get_cl_statuses(branches, fine_grained, max_processes=None): |
+ """Returns a blocking iterable of (branch, issue, color) for given branches. |
+ |
+ If fine_grained is true, this will fetch CL statuses from the server. |
+ Otherwise, simply indicate if there's a matching url for the given branches. |
+ |
+ If max_processes is specified, it is used as the maximum number of processes |
+ to spawn to fetch CL status from the server. Otherwise 1 process per branch is |
+ spawned. |
+ """ |
+ # Silence upload.py otherwise it becomes unwieldly. |
+ upload.verbosity = 0 |
+ |
+ if fine_grained: |
+ # Process one branch synchronously to work through authentication, then |
+ # spawn processes to process all the other branches in parallel. |
+ if branches: |
+ yield fetch_cl_status(branches[0]) |
+ |
+ branches_to_fetch = branches[1:] |
+ pool = multiprocessing.Pool( |
+ min(max_processes, len(branches_to_fetch)) |
+ if max_processes is not None |
+ else len(branches_to_fetch)) |
+ for x in pool.imap_unordered(fetch_cl_status, branches_to_fetch): |
+ yield x |
+ else: |
+ # Do not use GetApprovingReviewers(), since it requires an HTTP request. |
+ for b in branches: |
+ c = Changelist(branchref=b) |
+ url = c.GetIssueURL() |
+ yield (b, url, Fore.BLUE if url else Fore.WHITE) |
def CMDstatus(parser, args): |
"""Show status of changelists. |
@@ -1356,6 +1401,9 @@ def CMDstatus(parser, args): |
help='print only specific field (desc|id|patch|url)') |
parser.add_option('-f', '--fast', action='store_true', |
help='Do not retrieve review status') |
+ parser.add_option( |
+ '-j', '--maxjobs', action='store', type=int, |
+ help='The maximum number of jobs to use when retrieving review status') |
(options, args) = parser.parse_args(args) |
if args: |
parser.error('Unsupported args: %s' % args) |
@@ -1387,47 +1435,15 @@ def CMDstatus(parser, args): |
branches = [c.GetBranch() for c in changes] |
alignment = max(5, max(len(b) for b in branches)) |
print 'Branches associated with reviews:' |
- # Adhoc thread pool to request data concurrently. |
- output = Queue.Queue() |
- |
- # Silence upload.py otherwise it becomes unweldly. |
- upload.verbosity = 0 |
- |
- if not options.fast: |
- def fetch(b): |
- """Fetches information for an issue and returns (branch, issue, color).""" |
- c = Changelist(branchref=b) |
- i = c.GetIssueURL() |
- status = c.GetStatus() |
- color = color_for_status(status) |
- |
- if i and (not status or status == 'error'): |
- # The issue probably doesn't exist anymore. |
- i += ' (broken)' |
- |
- output.put((b, i, color)) |
- |
- # Process one branch synchronously to work through authentication, then |
- # spawn threads to process all the other branches in parallel. |
- if branches: |
- fetch(branches[0]) |
- threads = [ |
- threading.Thread(target=fetch, args=(b,)) for b in branches[1:]] |
- for t in threads: |
- t.daemon = True |
- t.start() |
- else: |
- # Do not use GetApprovingReviewers(), since it requires an HTTP request. |
- for b in branches: |
- c = Changelist(branchref=b) |
- url = c.GetIssueURL() |
- output.put((b, url, Fore.BLUE if url else Fore.WHITE)) |
+ output = get_cl_statuses(branches, |
+ fine_grained=not options.fast, |
+ max_processes=options.maxjobs) |
tmp = {} |
iannucci
2015/03/11 20:18:46
can we rename this to e.g. branch_status or someth
calamity
2015/03/11 22:28:27
Done.
|
alignment = max(5, max(len(ShortBranchName(b)) for b in branches)) |
for branch in sorted(branches): |
while branch not in tmp: |
- b, i, color = output.get() |
+ b, i, color = output.next() |
tmp[b] = (i, color) |
issue, color = tmp.pop(branch) |
reset = Fore.RESET |