Chromium Code Reviews| Index: git_cl.py |
| diff --git a/git_cl.py b/git_cl.py |
| index eaaed167aff5f4121c58a9aaf0814339ac337371..8a8c8baf896f3e3da077fb0f6d081f2cb8710517 100755 |
| --- a/git_cl.py |
| +++ b/git_cl.py |
| @@ -2929,11 +2929,12 @@ def fetch_cl_status(branch, auth_config=None): |
| # The issue probably doesn't exist anymore. |
| url += ' (broken)' |
| - return (branch, url, status) |
| + return (branch, cl.GetIssue(), url, status) |
| def get_cl_statuses( |
| branches, fine_grained, max_processes=None, auth_config=None): |
| - """Returns a blocking iterable of (branch, issue, status) for given branches. |
| + """Returns a blocking iterable of (branch, issue ID, issue URL, status) 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. |
| @@ -2961,6 +2962,10 @@ def get_cl_statuses( |
| yield fetch(branches[0]) |
| branches_to_fetch = branches[1:] |
| + if len(branches_to_fetch) == 0: |
| + # Exit early if there was only one branch to fetch. |
| + return |
|
tandrii(chromium)
2016/05/20 20:56:19
are you sure this works? I thought return can't be
Kevin M
2016/05/20 22:18:14
"return" from a generator raises a StopIteration.
|
| + |
| pool = ThreadPool( |
| min(max_processes, len(branches_to_fetch)) |
| if max_processes is not None |
| @@ -2980,14 +2985,14 @@ def get_cl_statuses( |
| # Add any branches that failed to fetch. |
| for b in set(branches_to_fetch) - fetched_branches: |
| cl = Changelist(branchref=b, auth_config=auth_config) |
| - yield (b, cl.GetIssueURL() if b else None, 'error') |
| + yield (b, cl.GetIssue(), cl.GetIssueURL() if b else None, 'error') |
| else: |
| # Do not use GetApprovingReviewers(), since it requires an HTTP request. |
| for b in branches: |
| cl = Changelist(branchref=b, auth_config=auth_config) |
| url = cl.GetIssueURL() if b else None |
| - yield (b, url, 'waiting' if url else 'error') |
| + yield (b, cl.GetIssue(), url, 'waiting' if url else 'error') |
| def upload_branch_deps(cl, args): |
| @@ -3089,6 +3094,64 @@ def upload_branch_deps(cl, args): |
| return 0 |
| +def CMDcleanup(parser, args): |
| + """Archives closed branches from the Git using tags and removes them from |
| + the Git branch list.""" |
| + parser.add_option( |
| + '-j', '--maxjobs', action='store', type=int, |
| + help='The maximum number of jobs to use when retrieving review status') |
| + |
| + parser.add_option( |
| + '-y', action='store_true', dest='no_prompt', default=False, |
|
tandrii(chromium)
2016/05/20 20:56:19
-f, --force to be inline with other cmds.
Kevin M
2016/05/20 22:18:14
Done.
|
| + help='Bypasses the confirmation prompt.') |
| + |
| + auth.add_auth_options(parser) |
| + options, args = parser.parse_args(args) |
| + if args: |
| + parser.error('Unsupported args: %s' % args) |
| + auth_config = auth.extract_auth_config_from_options(options) |
| + |
| + branches = RunGit(['for-each-ref', '--format=%(refname)', 'refs/heads']) |
| + if not branches: |
| + print('No local branch found.') |
|
tandrii(chromium)
2016/05/20 20:56:19
nit: why parenthesis here and not below?
Kevin M
2016/05/20 22:18:14
C++ habits, I guess. Done.
|
| + return 0 |
| + |
| + print 'Finding all branches associated with closed issues...' |
| + changes = ( |
| + Changelist(branchref=b, auth_config=auth_config) |
| + for b in branches.splitlines()) |
| + branches = [c.GetBranch() for c in changes] |
|
martiniss
2016/05/20 03:11:55
Any reason to not combine this and the previous li
Kevin M
2016/05/20 16:54:41
No reason other than avoiding nested list comprehe
|
| + alignment = max(5, max(len(b) for b in branches)) |
| + branch_statuses = get_cl_statuses(branches, |
| + fine_grained=True, |
| + max_processes=options.maxjobs, |
| + auth_config=auth_config) |
| + proposal = [(branch, 'submitted-%s-%s' % (branch, issue_id)) |
| + for branch, issue_id, _, status in branch_statuses |
| + if status == 'closed'] |
| + |
| + if len(proposal) == 0: |
| + print 'No closed branches found.' |
| + return 0 |
| + |
| + print '\nBranches with closed issues that will be tagged and deleted:' |
| + print "%*s | %s" % (alignment, "Branch name", "Archival tag name") |
| + for next_item in proposal: |
| + print '%*s %s' % (alignment, next_item[0], next_item[1]) |
| + |
| + prompt = None |
| + if not options.no_prompt: |
| + prompt = raw_input('\nProceed with deletion (Y/N)? ') |
| + if prompt == 'Y' or prompt == 'y' or options.no_prompt: |
| + for next_item in proposal: |
| + branch, tagname = next_item |
| + RunGit(['tag', tagname, branch]) |
|
martiniss
2016/05/20 03:11:55
What is the purpose of tagging the branch? Bookkee
Kevin M
2016/05/20 16:54:41
The tags allow you to access your local Git commit
|
| + RunGit(['branch', '-D', branch]) |
| + print '\nJob\'s done!' |
| + else: |
| + print 'Aborted.' |
| + |
| + return 0 |
| def CMDstatus(parser, args): |
| """Show status of changelists. |
| @@ -3156,7 +3219,7 @@ def CMDstatus(parser, args): |
| alignment = max(5, max(len(ShortBranchName(b)) for b in branches)) |
| for branch in sorted(branches): |
| while branch not in branch_statuses: |
| - b, i, status = output.next() |
| + b, _, i, status = output.next() |
| branch_statuses[b] = (i, status) |
| issue_url, status = branch_statuses.pop(branch) |
| color = color_for_status(status) |