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 |