[stacked-changes] Prepare squashed commit

Bug: b/265929888
Change-Id: Ia492666a5707996d94a4b6f7668ceaeb0eda8c39
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/tools/depot_tools/+/4182841
Reviewed-by: Josip Sokcevic <sokcevic@chromium.org>
Commit-Queue: Joanna Wang <jojwang@chromium.org>
Reviewed-by: Gavin Mak <gavinmak@google.com>
diff --git a/git_cl.py b/git_cl.py
index 6ea8498..c070e59 100755
--- a/git_cl.py
+++ b/git_cl.py
@@ -1576,6 +1576,38 @@
       return title
     return user_title or title
 
+  def PrepareSquashedCommit(self, options, parent=None, end_commit=None):
+    # type: (optparse.Values, Optional[str], Optional[str]) -> _NewUpload()
+    """Create a squashed commit to upload."""
+    if parent is None:
+      origin, upstream_branch_ref = self.FetchUpstreamTuple(self.GetBranch())
+      upstream_branch = scm.GIT.ShortBranchName(upstream_branch_ref)
+      if origin == '.':
+        # upstream is another local branch.
+        # Assume we want to upload from upstream's last upload.
+        parent = scm.GIT.GetBranchConfig(settings.GetRoot(), upstream_branch,
+                                         GERRIT_SQUASH_HASH_CONFIG_KEY)
+        assert parent, ('upstream branch %s not configured correctly. '
+                        'Could not fetch latest gerrit upload from git '
+                        'config.')
+      else:
+        # upstream is the root of the tree.
+        parent = self.GetCommonAncestorWithUpstream()
+
+    if end_commit is None:
+      end_commit = RunGit(['rev-parse', self.branchref]).strip()
+
+    reviewers, ccs, change_desc = self._PrepareChange(options, parent,
+                                                      end_commit)
+    latest_tree = RunGit(['rev-parse', end_commit + ':']).strip()
+    with gclient_utils.temporary_file() as desc_tempfile:
+      gclient_utils.FileWrite(desc_tempfile, change_desc.description)
+      commit_to_push = RunGit(
+          ['commit-tree', latest_tree, '-p', parent, '-F',
+           desc_tempfile]).strip()
+
+    return _NewUpload(reviewers, ccs, commit_to_push, end_commit, change_desc)
+
   def PrepareCherryPickSquashedCommit(self, options):
     # type: (optparse.Values) -> _NewUpload()
     """Create a commit cherry-picked on parent to push."""