Summarize number of commits being processed by `git cl upload`.
Occasionally, users can get a branch into a state where `git cl upload`
takes a long time because it is operating on an unexpectedly large diff.
One way where this can happen is when the local view of origin/main is
behind and someone force-patches in a CL based on a newer origin/main:
git cl upload will happily consider all the origin/main commits it
does not have in its local view of origin/main to simply be part of the
diff.
As this is a rather frustrating user experience, make it a bit easier to
realize when this sort of thing is happening by summarizing the number
of commits `git cl upload` is processing.
One alternative would be to stats about the diff; however, calculating
the number of commits is considerably faster than calculating the actual
diff. A quick local test shows that calculating the diff for 10k commits
takes nearly 20 seconds, while calculating the number of commits takes a
150 milliseconds.
Change-Id: I0e8706f164f6bf669f36f4792401589644be38b5
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/tools/depot_tools/+/4819796
Commit-Queue: Daniel Cheng <dcheng@chromium.org>
Reviewed-by: Gavin Mak <gavinmak@google.com>
diff --git a/git_cl.py b/git_cl.py
index d2acf19..0b879d4 100755
--- a/git_cl.py
+++ b/git_cl.py
@@ -30,6 +30,9 @@
import zlib
from third_party import colorama
+from typing import Optional
+from typing import Sequence
+from typing import Tuple
import auth
import clang_format
import fix_encoding
@@ -732,6 +735,21 @@
if not any(fnmatch.fnmatch(f, p) for p in patterns)]
+def _GetCommitCountSummary(begin_commit: str,
+ end_commit: str = "HEAD") -> Optional[str]:
+ """Generate a summary of the number of commits in (begin_commit, end_commit).
+
+ Returns a string containing the summary, or None if the range is empty.
+ """
+ count = int(
+ RunGitSilent(['rev-list', '--count', f'{begin_commit}..{end_commit}']))
+
+ if not count:
+ return None
+
+ return f'{count} commit{"s"[:count!=1]}'
+
+
def print_stats(args):
"""Prints statistics about the change to the user."""
# --no-ext-diff is broken in some versions of Git, so try to work around
@@ -1815,6 +1833,8 @@
self.EnsureAuthenticated(force=options.force)
self.EnsureCanUploadPatchset(force=options.force)
+ print(f'Processing {_GetCommitCountSummary(*git_diff_args)}...')
+
# Apply watchlists on upload.
watchlist = watchlists.Watchlists(settings.GetRoot())
files = self.GetAffectedFiles(base_branch)
@@ -4843,13 +4863,13 @@
return ret
-def UploadAllSquashed(options, orig_args):
- # type: (optparse.Values, Sequence[str]) -> Tuple[Sequence[Changelist], bool]
+def UploadAllSquashed(options: optparse.Values,
+ orig_args: Sequence[str]) -> int:
"""Uploads the current and upstream branches (if necessary)."""
cls, cherry_pick_current = _UploadAllPrecheck(options, orig_args)
# Create commits.
- uploads_by_cl = [] #type: Sequence[Tuple[Changelist, _NewUpload]]
+ uploads_by_cl: list[Tuple[Changelist, _NewUpload]] = []
if cherry_pick_current:
parent = cls[1]._GitGetBranchConfigValue(GERRIT_SQUASH_HASH_CONFIG_KEY)
new_upload = cls[0].PrepareCherryPickSquashedCommit(options, parent)
@@ -4986,13 +5006,14 @@
base_commit = cl.GetCommonAncestorWithUpstream()
end_commit = RunGit(['rev-parse', cl.GetBranchRef()]).strip()
- diff = RunGitSilent(['diff', '%s..%s' % (base_commit, end_commit)])
- if diff:
+ commit_summary = _GetCommitCountSummary(base_commit, end_commit)
+ if commit_summary:
cls.append(cl)
if (not first_pass and
cl._GitGetBranchConfigValue(GERRIT_SQUASH_HASH_CONFIG_KEY) is None):
# We are mid-stack and the user must upload their upstream branches.
must_upload_upstream = True
+ print(f'Found change with {commit_summary}...')
elif first_pass: # The current branch has nothing to commit. Exit.
DieWithError('Branch %s has nothing to commit' % cl.GetBranch())
# Else: A mid-stack branch has nothing to commit. We do not add it to cls.