Commit b631a88c authored by Josip Sokcevic's avatar Josip Sokcevic Committed by LUCI CQ

Run git fetch with --prune on failed git cl upload

git fetch --prune removes all references that no longer exist on remote
server. This allows git cl to upload changes to correct destination
branch.

R=ehmaldonado@chromium.org

Bug: 1149640
Change-Id: I66bf8d2209242b08991c2dae0d3a7fbc892cef87
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/tools/depot_tools/+/2606613Reviewed-by: 's avatarEdward Lesmes <ehmaldonado@chromium.org>
Commit-Queue: Josip Sokcevic <sokcevic@google.com>
parent 3a03505a
......@@ -2204,32 +2204,38 @@ class Changelist(object):
change_desc):
"""Upload the current branch to Gerrit, retry if new remote HEAD is
found. options and change_desc may be mutated."""
remote, remote_branch = self.GetRemoteBranch()
branch = GetTargetRef(remote, remote_branch, options.target_branch)
try:
return self._CMDUploadChange(options, git_diff_args, custom_cl_base,
change_desc)
change_desc, branch)
except GitPushError as e:
remote, remote_branch = self.GetRemoteBranch()
should_retry = remote_branch == DEFAULT_OLD_BRANCH and \
gerrit_util.GetProjectHead(
self._gerrit_host, self.GetGerritProject()) == 'refs/heads/main'
if not should_retry:
# Repository might be in the middle of transition to main branch as
# default, and uploads to old default might be blocked.
if remote_branch not in [DEFAULT_OLD_BRANCH, DEFAULT_NEW_BRANCH]:
DieWithError(str(e), change_desc)
project_head = gerrit_util.GetProjectHead(self._gerrit_host,
self.GetGerritProject())
if project_head == branch:
DieWithError(str(e), change_desc)
branch = project_head
print("WARNING: Detected HEAD change in upstream, fetching remote state")
RunGit(['fetch', remote])
print("WARNING: Fetching remote state and retrying upload to default "
"branch...")
RunGit(['fetch', '--prune', remote])
options.edit_description = False
options.force = True
try:
self._CMDUploadChange(options, git_diff_args, custom_cl_base, change_desc)
self._CMDUploadChange(options, git_diff_args, custom_cl_base,
change_desc, branch)
except GitPushError as e:
DieWithError(str(e), change_desc)
def _CMDUploadChange(self, options, git_diff_args, custom_cl_base,
change_desc):
change_desc, branch):
"""Upload the current branch to Gerrit."""
remote, remote_branch = self.GetRemoteBranch()
branch = GetTargetRef(remote, remote_branch, options.target_branch)
if options.squash:
self._GerritCommitMsgHookCheck(offer_removal=not options.force)
if self.GetIssue():
......
......@@ -238,6 +238,7 @@ class TestGitClBasic(unittest.TestCase):
cl = git_cl.Changelist()
options = optparse.Values()
options.target_branch = 'refs/heads/bar'
with self.assertRaises(SystemExitMock):
cl.CMDUploadChange(options, [], 'foo', git_cl.ChangeDescription('bar'))
......@@ -256,10 +257,11 @@ class TestGitClBasic(unittest.TestCase):
mock.patch('git_cl.Changelist.GetGerritProject',
return_value='foo').start()
mock.patch('git_cl.gerrit_util.GetProjectHead',
return_value='refs/heads/old_default').start()
return_value='refs/heads/master').start()
cl = git_cl.Changelist()
options = optparse.Values()
options.target_branch = 'refs/heads/master'
with self.assertRaises(SystemExitMock):
cl.CMDUploadChange(options, [], 'foo', git_cl.ChangeDescription('bar'))
......@@ -283,6 +285,33 @@ class TestGitClBasic(unittest.TestCase):
cl = git_cl.Changelist()
options = optparse.Values()
options.target_branch = 'refs/heads/master'
cl.CMDUploadChange(options, [], 'foo', git_cl.ChangeDescription('bar'))
# ensure upload is called twice
self.assertEqual(len(m.mock_calls), 2)
# option overrides on retry
self.assertEqual(options.force, True)
self.assertEqual(options.edit_description, False)
def test_upload_to_old_default_retry_on_rollback(self):
"""Test when default branch migration had to be rolled back to old name"""
m = mock.patch('git_cl.Changelist._CMDUploadChange',
side_effect=[git_cl.GitPushError(), None]).start()
mock.patch('git_cl.Changelist.GetRemoteBranch',
return_value=('foo', git_cl.DEFAULT_NEW_BRANCH)).start()
mock.patch('git_cl.Changelist.GetGerritProject',
return_value='foo').start()
mock.patch('git_cl.gerrit_util.GetProjectHead',
return_value='refs/heads/master').start()
# GetTargetRef returns new default branch since it has stale remote
# information.
mock.patch('git_cl.GetTargetRef',
return_value='refs/heads/main').start()
mock.patch('git_cl.RunGit').start()
cl = git_cl.Changelist()
options = optparse.Values()
options.target_branch = 'refs/heads/master'
cl.CMDUploadChange(options, [], 'foo', git_cl.ChangeDescription('bar'))
# ensure upload is called twice
self.assertEqual(len(m.mock_calls), 2)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment