Chromium Code Reviews| 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 |
| 11 from multiprocessing.pool import ThreadPool | 11 from multiprocessing.pool import ThreadPool |
| 12 import base64 | 12 import base64 |
| 13 import collections | |
| 13 import glob | 14 import glob |
| 14 import httplib | 15 import httplib |
| 15 import json | 16 import json |
| 16 import logging | 17 import logging |
| 17 import optparse | 18 import optparse |
| 18 import os | 19 import os |
| 19 import Queue | 20 import Queue |
| 20 import re | 21 import re |
| 21 import stat | 22 import stat |
| 22 import sys | 23 import sys |
| (...skipping 1475 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1498 else len(branches_to_fetch)) | 1499 else len(branches_to_fetch)) |
| 1499 for x in pool.imap_unordered(fetch, branches_to_fetch): | 1500 for x in pool.imap_unordered(fetch, branches_to_fetch): |
| 1500 yield x | 1501 yield x |
| 1501 else: | 1502 else: |
| 1502 # Do not use GetApprovingReviewers(), since it requires an HTTP request. | 1503 # Do not use GetApprovingReviewers(), since it requires an HTTP request. |
| 1503 for b in branches: | 1504 for b in branches: |
| 1504 c = Changelist(branchref=b, auth_config=auth_config) | 1505 c = Changelist(branchref=b, auth_config=auth_config) |
| 1505 url = c.GetIssueURL() | 1506 url = c.GetIssueURL() |
| 1506 yield (b, url, Fore.BLUE if url else Fore.WHITE) | 1507 yield (b, url, Fore.BLUE if url else Fore.WHITE) |
| 1507 | 1508 |
| 1509 | |
| 1510 def CMDupload_branch_deps(parser, args): | |
| 1511 """Uploads CLs of local branches that are dependents of the current branch. | |
| 1512 | |
| 1513 If the local branch dependency tree looks like: | |
| 1514 test1 -> test2.1 -> test3.1 | |
| 1515 -> test3.2 | |
| 1516 -> test2.2 -> test3.3 | |
| 1517 | |
| 1518 and you run this command from test1 then "git cl upload" is run on the | |
| 1519 dependent branches in this order: | |
| 1520 test2.1, test3.1, test3.2, test2.2, test3.3 | |
| 1521 | |
| 1522 Note: This command does not rebase your local dependent branches. Use it when | |
| 1523 you make a change to the parent branch that will not conflict with its | |
| 1524 dependent branches, and you would like their dependencies updated in | |
| 1525 Rietveld. | |
| 1526 """ | |
| 1527 auth.add_auth_options(parser) | |
| 1528 (options, args) = parser.parse_args(args) | |
| 1529 auth_config = auth.extract_auth_config_from_options(options) | |
| 1530 | |
| 1531 if git_common.is_dirty_git_tree('upload-branch-deps'): | |
| 1532 return 1 | |
| 1533 | |
| 1534 cl = Changelist(auth_config=auth_config) | |
| 1535 root_branch = cl.GetBranch() | |
| 1536 if root_branch is None: | |
| 1537 DieWithError('Can\'t find dependent branches from detached HEAD state. ' | |
| 1538 'Get on a branch!') | |
| 1539 if not cl.GetIssue() or not cl.GetPatchset(): | |
| 1540 DieWithError('Current branch does not have an uploaded CL. We cannot set ' | |
| 1541 'patchset dependencies without an uploaded CL.') | |
| 1542 | |
| 1543 branches = RunGit(['for-each-ref', | |
| 1544 '--format=%(refname:short) %(upstream:short)', | |
| 1545 'refs/heads']) | |
| 1546 if not branches: | |
| 1547 print('No local branches found.') | |
| 1548 return 0 | |
| 1549 | |
| 1550 # Create a dictionary of all local branches to the branches that are dependent | |
|
agable
2015/06/17 18:13:34
Seems like you should be able to reuse code from g
rmistry
2015/06/18 17:52:40
My comment for this is similar to my earlier comme
| |
| 1551 # on it. | |
| 1552 tracked_to_dependents = collections.defaultdict(list) | |
| 1553 for b in branches.splitlines(): | |
| 1554 tokens = b.split() | |
| 1555 if len(tokens) == 2: | |
| 1556 branch_name, tracked = tokens | |
| 1557 tracked_to_dependents[tracked].append(branch_name) | |
| 1558 | |
| 1559 print | |
| 1560 print 'The dependent local branches of %s are:' % root_branch | |
| 1561 dependents = [] | |
| 1562 def traverse_dependents_preorder(branch, padding=''): | |
| 1563 dependents_to_process = tracked_to_dependents.get(branch, []) | |
| 1564 padding += ' ' | |
| 1565 for dependent in dependents_to_process: | |
| 1566 print '%s%s' % (padding, dependent) | |
| 1567 dependents.append(dependent) | |
| 1568 traverse_dependents_preorder(dependent, padding) | |
| 1569 traverse_dependents_preorder(root_branch) | |
| 1570 print | |
| 1571 | |
| 1572 print ('This command will checkout all dependent branches and run ' | |
| 1573 '"git cl upload".') | |
| 1574 ask_for_data('[Press enter to continue or ctrl-C to quit]') | |
| 1575 | |
| 1576 if not dependents: | |
|
agable
2015/06/17 18:13:34
Do this before requiring user input above.
rmistry
2015/06/18 17:52:39
Done.
| |
| 1577 print 'There are no dependent local branches for %s' % root_branch | |
| 1578 return 0 | |
| 1579 | |
| 1580 # Add a default patchset title to all upload calls. | |
| 1581 args.extend(['-t', 'Updated patchset dependency with upload-branch-deps']) | |
| 1582 # Go through all dependents, checkout the branch and upload. | |
| 1583 try: | |
| 1584 for dependent_branch in dependents: | |
| 1585 print | |
| 1586 print '--------------------------------------' | |
| 1587 print 'Running "git cl upload" from %s:' % dependent_branch | |
| 1588 RunGit(['checkout', '-q', dependent_branch]) | |
| 1589 print | |
| 1590 if CMDupload(OptionParser(), args) != 0: | |
| 1591 print 'Upload failed for %s!' % dependent_branch | |
| 1592 return 1 | |
| 1593 print | |
| 1594 finally: | |
| 1595 # Swap back to the original root branch. | |
| 1596 RunGit(['checkout', '-q', root_branch]) | |
| 1597 | |
| 1598 print | |
| 1599 print 'All dependent branches %s have been updated!' % dependents | |
| 1600 print | |
| 1601 | |
| 1602 return 0 | |
| 1603 | |
| 1604 | |
| 1508 def CMDstatus(parser, args): | 1605 def CMDstatus(parser, args): |
| 1509 """Show status of changelists. | 1606 """Show status of changelists. |
| 1510 | 1607 |
| 1511 Colors are used to tell the state of the CL unless --fast is used: | 1608 Colors are used to tell the state of the CL unless --fast is used: |
| 1512 - Red not sent for review or broken | 1609 - Red not sent for review or broken |
| 1513 - Blue waiting for review | 1610 - Blue waiting for review |
| 1514 - Yellow waiting for you to reply to review | 1611 - Yellow waiting for you to reply to review |
| 1515 - Green LGTM'ed | 1612 - Green LGTM'ed |
| 1516 - Magenta in the commit queue | 1613 - Magenta in the commit queue |
| 1517 - Cyan was committed, branch can be deleted | 1614 - Cyan was committed, branch can be deleted |
| (...skipping 1847 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3365 if __name__ == '__main__': | 3462 if __name__ == '__main__': |
| 3366 # These affect sys.stdout so do it outside of main() to simplify mocks in | 3463 # These affect sys.stdout so do it outside of main() to simplify mocks in |
| 3367 # unit testing. | 3464 # unit testing. |
| 3368 fix_encoding.fix_encoding() | 3465 fix_encoding.fix_encoding() |
| 3369 colorama.init() | 3466 colorama.init() |
| 3370 try: | 3467 try: |
| 3371 sys.exit(main(sys.argv[1:])) | 3468 sys.exit(main(sys.argv[1:])) |
| 3372 except KeyboardInterrupt: | 3469 except KeyboardInterrupt: |
| 3373 sys.stderr.write('interrupted\n') | 3470 sys.stderr.write('interrupted\n') |
| 3374 sys.exit(1) | 3471 sys.exit(1) |
| OLD | NEW |