Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(72)

Side by Side Diff: git_cl.py

Issue 938583002: Make git-map-branches -vvv show CL status colors. (Closed) Base URL: https://chromium.googlesource.com/chromium/tools/depot_tools.git@master
Patch Set: address comments Created 5 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | git_map_branches.py » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
11 from multiprocessing.pool import ThreadPool
11 import base64 12 import base64
12 import glob 13 import glob
13 import json 14 import json
14 import logging 15 import logging
15 import optparse 16 import optparse
16 import os 17 import os
17 import Queue 18 import Queue
18 import re 19 import re
19 import stat 20 import stat
20 import sys 21 import sys
21 import tempfile 22 import tempfile
22 import textwrap 23 import textwrap
23 import threading
24 import urllib2 24 import urllib2
25 import urlparse 25 import urlparse
26 import webbrowser 26 import webbrowser
27 import zlib 27 import zlib
28 28
29 try: 29 try:
30 import readline # pylint: disable=F0401,W0611 30 import readline # pylint: disable=F0401,W0611
31 except ImportError: 31 except ImportError:
32 pass 32 pass
33 33
(...skipping 1301 matching lines...) Expand 10 before | Expand all | Expand 10 after
1335 return { 1335 return {
1336 'unsent': Fore.RED, 1336 'unsent': Fore.RED,
1337 'waiting': Fore.BLUE, 1337 'waiting': Fore.BLUE,
1338 'reply': Fore.YELLOW, 1338 'reply': Fore.YELLOW,
1339 'lgtm': Fore.GREEN, 1339 'lgtm': Fore.GREEN,
1340 'commit': Fore.MAGENTA, 1340 'commit': Fore.MAGENTA,
1341 'closed': Fore.CYAN, 1341 'closed': Fore.CYAN,
1342 'error': Fore.WHITE, 1342 'error': Fore.WHITE,
1343 }.get(status, Fore.WHITE) 1343 }.get(status, Fore.WHITE)
1344 1344
1345 def fetch_cl_status(b):
1346 """Fetches information for an issue and returns (branch, issue, color)."""
1347 c = Changelist(branchref=b)
1348 i = c.GetIssueURL()
1349 status = c.GetStatus()
1350 color = color_for_status(status)
1351
1352 if i and (not status or status == 'error'):
1353 # The issue probably doesn't exist anymore.
1354 i += ' (broken)'
1355
1356 return (b, i, color)
1357
1358 def get_cl_statuses(branches, fine_grained, max_processes=None):
1359 """Returns a blocking iterable of (branch, issue, color) for given branches.
1360
1361 If fine_grained is true, this will fetch CL statuses from the server.
1362 Otherwise, simply indicate if there's a matching url for the given branches.
1363
1364 If max_processes is specified, it is used as the maximum number of processes
1365 to spawn to fetch CL status from the server. Otherwise 1 process per branch is
1366 spawned.
1367 """
1368 # Silence upload.py otherwise it becomes unwieldly.
1369 upload.verbosity = 0
1370
1371 if fine_grained:
1372 # Process one branch synchronously to work through authentication, then
1373 # spawn processes to process all the other branches in parallel.
1374 if branches:
1375 yield fetch_cl_status(branches[0])
1376
1377 branches_to_fetch = branches[1:]
1378 pool = ThreadPool(
1379 min(max_processes, len(branches_to_fetch))
1380 if max_processes is not None
1381 else len(branches_to_fetch))
1382 for x in pool.imap_unordered(fetch_cl_status, branches_to_fetch):
1383 yield x
1384 else:
1385 # Do not use GetApprovingReviewers(), since it requires an HTTP request.
1386 for b in branches:
1387 c = Changelist(branchref=b)
1388 url = c.GetIssueURL()
1389 yield (b, url, Fore.BLUE if url else Fore.WHITE)
1345 1390
1346 def CMDstatus(parser, args): 1391 def CMDstatus(parser, args):
1347 """Show status of changelists. 1392 """Show status of changelists.
1348 1393
1349 Colors are used to tell the state of the CL unless --fast is used: 1394 Colors are used to tell the state of the CL unless --fast is used:
1350 - Red not sent for review or broken 1395 - Red not sent for review or broken
1351 - Blue waiting for review 1396 - Blue waiting for review
1352 - Yellow waiting for you to reply to review 1397 - Yellow waiting for you to reply to review
1353 - Green LGTM'ed 1398 - Green LGTM'ed
1354 - Magenta in the commit queue 1399 - Magenta in the commit queue
1355 - Cyan was committed, branch can be deleted 1400 - Cyan was committed, branch can be deleted
1356 1401
1357 Also see 'git cl comments'. 1402 Also see 'git cl comments'.
1358 """ 1403 """
1359 parser.add_option('--field', 1404 parser.add_option('--field',
1360 help='print only specific field (desc|id|patch|url)') 1405 help='print only specific field (desc|id|patch|url)')
1361 parser.add_option('-f', '--fast', action='store_true', 1406 parser.add_option('-f', '--fast', action='store_true',
1362 help='Do not retrieve review status') 1407 help='Do not retrieve review status')
1408 parser.add_option(
1409 '-j', '--maxjobs', action='store', type=int,
1410 help='The maximum number of jobs to use when retrieving review status')
1363 (options, args) = parser.parse_args(args) 1411 (options, args) = parser.parse_args(args)
1364 if args: 1412 if args:
1365 parser.error('Unsupported args: %s' % args) 1413 parser.error('Unsupported args: %s' % args)
1366 1414
1367 if options.field: 1415 if options.field:
1368 cl = Changelist() 1416 cl = Changelist()
1369 if options.field.startswith('desc'): 1417 if options.field.startswith('desc'):
1370 print cl.GetDescription() 1418 print cl.GetDescription()
1371 elif options.field == 'id': 1419 elif options.field == 'id':
1372 issueid = cl.GetIssue() 1420 issueid = cl.GetIssue()
(...skipping 11 matching lines...) Expand all
1384 1432
1385 branches = RunGit(['for-each-ref', '--format=%(refname)', 'refs/heads']) 1433 branches = RunGit(['for-each-ref', '--format=%(refname)', 'refs/heads'])
1386 if not branches: 1434 if not branches:
1387 print('No local branch found.') 1435 print('No local branch found.')
1388 return 0 1436 return 0
1389 1437
1390 changes = (Changelist(branchref=b) for b in branches.splitlines()) 1438 changes = (Changelist(branchref=b) for b in branches.splitlines())
1391 branches = [c.GetBranch() for c in changes] 1439 branches = [c.GetBranch() for c in changes]
1392 alignment = max(5, max(len(b) for b in branches)) 1440 alignment = max(5, max(len(b) for b in branches))
1393 print 'Branches associated with reviews:' 1441 print 'Branches associated with reviews:'
1394 # Adhoc thread pool to request data concurrently. 1442 output = get_cl_statuses(branches,
1395 output = Queue.Queue() 1443 fine_grained=not options.fast,
1444 max_processes=options.maxjobs)
1396 1445
1397 # Silence upload.py otherwise it becomes unweldly. 1446 branch_statuses = {}
1398 upload.verbosity = 0
1399
1400 if not options.fast:
1401 def fetch(b):
1402 """Fetches information for an issue and returns (branch, issue, color)."""
1403 c = Changelist(branchref=b)
1404 i = c.GetIssueURL()
1405 status = c.GetStatus()
1406 color = color_for_status(status)
1407
1408 if i and (not status or status == 'error'):
1409 # The issue probably doesn't exist anymore.
1410 i += ' (broken)'
1411
1412 output.put((b, i, color))
1413
1414 # Process one branch synchronously to work through authentication, then
1415 # spawn threads to process all the other branches in parallel.
1416 if branches:
1417 fetch(branches[0])
1418 threads = [
1419 threading.Thread(target=fetch, args=(b,)) for b in branches[1:]]
1420 for t in threads:
1421 t.daemon = True
1422 t.start()
1423 else:
1424 # Do not use GetApprovingReviewers(), since it requires an HTTP request.
1425 for b in branches:
1426 c = Changelist(branchref=b)
1427 url = c.GetIssueURL()
1428 output.put((b, url, Fore.BLUE if url else Fore.WHITE))
1429
1430 tmp = {}
1431 alignment = max(5, max(len(ShortBranchName(b)) for b in branches)) 1447 alignment = max(5, max(len(ShortBranchName(b)) for b in branches))
1432 for branch in sorted(branches): 1448 for branch in sorted(branches):
1433 while branch not in tmp: 1449 while branch not in branch_statuses:
1434 b, i, color = output.get() 1450 b, i, color = output.next()
1435 tmp[b] = (i, color) 1451 branch_statuses[b] = (i, color)
1436 issue, color = tmp.pop(branch) 1452 issue, color = branch_statuses.pop(branch)
1437 reset = Fore.RESET 1453 reset = Fore.RESET
1438 if not sys.stdout.isatty(): 1454 if not sys.stdout.isatty():
1439 color = '' 1455 color = ''
1440 reset = '' 1456 reset = ''
1441 print ' %*s : %s%s%s' % ( 1457 print ' %*s : %s%s%s' % (
1442 alignment, ShortBranchName(branch), color, issue, reset) 1458 alignment, ShortBranchName(branch), color, issue, reset)
1443 1459
1444 cl = Changelist() 1460 cl = Changelist()
1445 print 1461 print
1446 print 'Current branch:', 1462 print 'Current branch:',
(...skipping 1671 matching lines...) Expand 10 before | Expand all | Expand 10 after
3118 if __name__ == '__main__': 3134 if __name__ == '__main__':
3119 # These affect sys.stdout so do it outside of main() to simplify mocks in 3135 # These affect sys.stdout so do it outside of main() to simplify mocks in
3120 # unit testing. 3136 # unit testing.
3121 fix_encoding.fix_encoding() 3137 fix_encoding.fix_encoding()
3122 colorama.init() 3138 colorama.init()
3123 try: 3139 try:
3124 sys.exit(main(sys.argv[1:])) 3140 sys.exit(main(sys.argv[1:]))
3125 except KeyboardInterrupt: 3141 except KeyboardInterrupt:
3126 sys.stderr.write('interrupted\n') 3142 sys.stderr.write('interrupted\n')
3127 sys.exit(1) 3143 sys.exit(1)
OLDNEW
« no previous file with comments | « no previous file | git_map_branches.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698