Quellcode durchsuchen

Connect new stacked changes implementation.

Bug: b/265929888
Change-Id: I89f669d9d0a11f09a89c378222e6780ac9fcec34
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/tools/depot_tools/+/4189199
Reviewed-by: Josip Sokcevic <sokcevic@chromium.org>
Commit-Queue: Joanna Wang <jojwang@chromium.org>
Joanna Wang vor 2 Jahren
Ursprung
Commit
c710e2d56a
2 geänderte Dateien mit 219 neuen und 2 gelöschten Zeilen
  1. 66 2
      git_cl.py
  2. 153 0
      tests/git_cl_test.py

+ 66 - 2
git_cl.py

@@ -4825,9 +4825,73 @@ def CMDupload(parser, args):
 def UploadAllSquashed(options, orig_args):
   # type: (optparse.Values, Sequence[str]) -> Tuple[Sequence[Changelist], bool]
   """Uploads the current and upstream branches (if necessary)."""
-  _cls, _cherry_pick_current = _UploadAllPrecheck(options, orig_args)
+  cls, cherry_pick_current = _UploadAllPrecheck(options, orig_args)
+
+  # Create commits.
+  uploads_by_cl = []  #type: Sequence[Tuple[Changelist, _NewUpload]]
+  if cherry_pick_current:
+    parent = cls[1]._GitGetBranchConfigValue(GERRIT_SQUASH_HASH_CONFIG_KEY)
+    new_upload = cls[0].PrepareCherryPickSquashedCommit(options, parent)
+    uploads_by_cl.append((cls[0], new_upload))
+  else:
+    parent = None
+    ordered_cls = list(reversed(cls))
+
+    for i, cl in enumerate(ordered_cls):
+      # If we're in the middle of the stack, set end_commit to downstream's
+      # direct ancestor.
+      if i + 1 < len(ordered_cls):
+        child_base_commit = ordered_cls[i + 1].GetCommonAncestorWithUpstream()
+      else:
+        child_base_commit = None
+      new_upload = cl.PrepareSquashedCommit(options,
+                                            parent=parent,
+                                            end_commit=child_base_commit)
+      uploads_by_cl.append((cl, new_upload))
+
+      parent = new_upload.commit_to_push
+
+  # Create refspec options
+  cl, new_upload = uploads_by_cl[-1]
+  refspec_opts = cl._GetRefSpecOptions(
+      options,
+      new_upload.change_desc,
+      multi_change_upload=len(uploads_by_cl) > 1)
+  refspec_suffix = ''
+  if refspec_opts:
+    refspec_suffix = '%' + ','.join(refspec_opts)
+    assert ' ' not in refspec_suffix, ('spaces not allowed in refspec: "%s"' %
+                                       refspec_suffix)
+
+  remote, remote_branch = cl.GetRemoteBranch()
+  branch = GetTargetRef(remote, remote_branch, options.target_branch)
+  refspec = '%s:refs/for/%s%s' % (new_upload.commit_to_push, branch,
+                                  refspec_suffix)
+
+  # Git push
+  git_push_metadata = {
+      'gerrit_host':
+      cl.GetGerritHost(),
+      'title':
+      options.title or '<untitled>',
+      'change_id':
+      git_footers.get_footer_change_id(new_upload.change_desc.description),
+      'description':
+      new_upload.change_desc.description,
+  }
+  push_stdout = cl._RunGitPushWithTraces(refspec, refspec_opts,
+                                         git_push_metadata)
 
-  # TODO(b/265929888): parse cls and create commits.
+  # Post push updates
+  regex = re.compile(r'remote:\s+https?://[\w\-\.\+\/#]*/(\d+)\s.*')
+  change_numbers = [
+      m.group(1) for m in map(regex.match, push_stdout.splitlines()) if m
+  ]
+
+  for i, (cl, new_upload) in enumerate(uploads_by_cl):
+    cl.PostUploadUpdates(options, new_upload, change_numbers[i])
+
+  return 0
 
 
 def _UploadAllPrecheck(options, orig_args):

+ 153 - 0
tests/git_cl_test.py

@@ -1514,6 +1514,159 @@ class TestGitCl(unittest.TestCase):
         external_parent='newparent',
     )
 
+  @mock.patch('git_cl.Changelist.GetGerritHost',
+              return_value='chromium-review.googlesource.com')
+  @mock.patch('git_cl.Changelist.GetRemoteBranch',
+              return_value=('origin', 'refs/remotes/origin/main'))
+  @mock.patch('git_cl.Changelist.PostUploadUpdates')
+  @mock.patch('git_cl.Changelist._RunGitPushWithTraces')
+  @mock.patch('git_cl._UploadAllPrecheck')
+  @mock.patch('git_cl.Changelist.PrepareCherryPickSquashedCommit')
+  def test_upload_all_squashed_cherry_pick(self, mockCherryPickCommit,
+                                           mockUploadAllPrecheck,
+                                           mockRunGitPush,
+                                           mockPostUploadUpdates, *_mocks):
+    # Set up
+    cls = [
+        git_cl.Changelist(branchref='refs/heads/current-branch', issue='12345'),
+        git_cl.Changelist(branchref='refs/heads/upstream-branch')
+    ]
+    mockUploadAllPrecheck.return_value = (cls, True)
+
+    upstream_gerrit_commit = 'upstream-commit'
+    self.mockGit.config[
+        'branch.upstream-branch.gerritsquashhash'] = upstream_gerrit_commit
+
+    reviewers = []
+    ccs = []
+    commit_to_push = 'commit-to-push'
+    new_last_upload = 'new-last-upload'
+    change_desc = git_cl.ChangeDescription('stonks/nChange-Id:ec15e81197380')
+    new_upload = git_cl._NewUpload(reviewers, ccs, commit_to_push,
+                                   new_last_upload, upstream_gerrit_commit,
+                                   change_desc)
+    mockCherryPickCommit.return_value = new_upload
+
+    options = optparse.Values()
+    options.send_mail = options.private = False
+    options.squash = True
+    options.title = None
+    options.message = 'honk stonk'
+    options.topic = 'circus'
+    options.enable_auto_submit = False
+    options.set_bot_commit = False
+    options.cq_dry_run = False
+    options.use_commit_queue = options.cq_quick_run = False
+    options.hashtags = ['cow']
+    options.target_branch = None
+    orig_args = []
+
+    mockRunGitPush.return_value = (
+        'remote:   https://chromium-review.'
+        'googlesource.com/c/chromium/circus/clown/+/1234 stonks')
+
+    # Call
+    git_cl.UploadAllSquashed(options, orig_args)
+
+    # Asserts
+    mockCherryPickCommit.assert_called_once_with(options,
+                                                 upstream_gerrit_commit)
+    expected_refspec = ('commit-to-push:refs/for/refs/heads/main%notify=NONE,'
+                        'm=honk_stonk,topic=circus,hashtag=cow')
+    expected_refspec_opts = [
+        'notify=NONE', 'm=honk_stonk', 'topic=circus', 'hashtag=cow'
+    ]
+    mockRunGitPush.assert_called_once_with(expected_refspec,
+                                           expected_refspec_opts, mock.ANY)
+    mockPostUploadUpdates.assert_called_once_with(options, new_upload, '1234')
+
+  @mock.patch('git_cl.Changelist.GetGerritHost',
+              return_value='chromium-review.googlesource.com')
+  @mock.patch('git_cl.Changelist.GetRemoteBranch',
+              return_value=('origin', 'refs/remotes/origin/main'))
+  @mock.patch('git_cl.Changelist.GetCommonAncestorWithUpstream',
+              return_value='current-upstream-ancestor')
+  @mock.patch('git_cl.Changelist.PostUploadUpdates')
+  @mock.patch('git_cl.Changelist._RunGitPushWithTraces')
+  @mock.patch('git_cl._UploadAllPrecheck')
+  @mock.patch('git_cl.Changelist.PrepareSquashedCommit')
+  def test_upload_all_squashed(self, mockSquashedCommit, mockUploadAllPrecheck,
+                               mockRunGitPush, mockPostUploadUpdates, *_mocks):
+    # Set up
+    cls = [
+        git_cl.Changelist(branchref='refs/heads/current-branch', issue='12345'),
+        git_cl.Changelist(branchref='refs/heads/upstream-branch')
+    ]
+    mockUploadAllPrecheck.return_value = (cls, False)
+
+    reviewers = []
+    ccs = []
+
+    current_commit_to_push = 'commit-to-push'
+    current_new_last_upload = 'new-last-upload'
+    change_desc = git_cl.ChangeDescription('stonks/nChange-Id:ec15e81197380')
+    new_upload_current = git_cl._NewUpload(reviewers, ccs,
+                                           current_commit_to_push,
+                                           current_new_last_upload,
+                                           'current-upstream-ancestor',
+                                           change_desc)
+
+    upstream_desc = git_cl.ChangeDescription('kwak')
+    upstream_parent = 'origin-commit'
+    upstream_new_last_upload = 'upstrea-last-upload'
+    upstream_commit_to_push = 'upstream_push_commit'
+    new_upload_upstream = git_cl._NewUpload(reviewers, ccs,
+                                            upstream_commit_to_push,
+                                            upstream_new_last_upload,
+                                            upstream_parent, upstream_desc)
+    mockSquashedCommit.side_effect = [new_upload_upstream, new_upload_current]
+
+    options = optparse.Values()
+    options.send_mail = options.private = False
+    options.squash = True
+    options.title = None
+    options.message = 'honk stonk'
+    options.topic = 'circus'
+    options.enable_auto_submit = False
+    options.set_bot_commit = False
+    options.cq_dry_run = False
+    options.use_commit_queue = options.cq_quick_run = False
+    options.hashtags = ['cow']
+    options.target_branch = None
+    orig_args = []
+
+    mockRunGitPush.return_value = (
+        'remote:   https://chromium-review.'
+        'googlesource.com/c/chromium/circus/clown/+/1233 kwak'
+        '\n'
+        'remote:   https://chromium-review.'
+        'googlesource.com/c/chromium/circus/clown/+/1234 stonks')
+
+    # Call
+    git_cl.UploadAllSquashed(options, orig_args)
+
+    # Asserts
+    self.assertEqual(mockSquashedCommit.mock_calls, [
+        mock.call(options, parent=None, end_commit='current-upstream-ancestor'),
+        mock.call(options, parent=upstream_commit_to_push, end_commit=None)
+    ])
+
+    expected_refspec = ('commit-to-push:refs/for/refs/heads/main%notify=NONE,'
+                        'm=honk_stonk,topic=circus,hashtag=cow')
+    expected_refspec_opts = [
+        'notify=NONE', 'm=honk_stonk', 'topic=circus', 'hashtag=cow'
+    ]
+    expected_refspec = ('commit-to-push:refs/for/refs/heads/main%notify=NONE,'
+                        'topic=circus,hashtag=cow')
+    expected_refspec_opts = ['notify=NONE', 'topic=circus', 'hashtag=cow']
+    mockRunGitPush.assert_called_once_with(expected_refspec,
+                                           expected_refspec_opts, mock.ANY)
+
+    self.assertEqual(mockPostUploadUpdates.mock_calls, [
+        mock.call(options, new_upload_upstream, '1233'),
+        mock.call(options, new_upload_current, '1234')
+    ])
+
   @mock.patch(
       'git_cl.Changelist._GerritCommitMsgHookCheck', lambda offer_removal: None)
   @mock.patch('git_cl.Changelist.FetchUpstreamTuple')