mirror of
https://chromium.googlesource.com/chromium/tools/depot_tools.git
synced 2026-01-11 02:31:29 +00:00
[stacked_changes] Create cherry-picked commit.
Bug:b/265929888 Change-Id: I4277474c1f09e4ac6ea6ebb5d9d340f22365f542 Reviewed-on: https://chromium-review.googlesource.com/c/chromium/tools/depot_tools/+/4178924 Reviewed-by: Gavin Mak <gavinmak@google.com> Reviewed-by: Josip Sokcevic <sokcevic@chromium.org> Commit-Queue: Joanna Wang <jojwang@chromium.org>
This commit is contained in:
41
git_cl.py
41
git_cl.py
@@ -999,6 +999,12 @@ _CommentSummary = collections.namedtuple(
|
||||
'approval', 'disapproval'])
|
||||
|
||||
|
||||
_NewUpload = collections.namedtuple('NewUpload', [
|
||||
'reviewers', 'ccs', 'commit_to_push', 'new_last_uploaded_commit',
|
||||
'change_desc'
|
||||
])
|
||||
|
||||
|
||||
class Changelist(object):
|
||||
"""Changelist works with one changelist in local branch.
|
||||
|
||||
@@ -1569,6 +1575,41 @@ class Changelist(object):
|
||||
return title
|
||||
return user_title or title
|
||||
|
||||
def PrepareCherryPickSquashedCommit(self, options):
|
||||
# type: (optparse.Values) -> _NewUpload()
|
||||
"""Create a commit cherry-picked on parent to push."""
|
||||
|
||||
parent = self.GetCommonAncestorWithUpstream()
|
||||
reviewers, ccs, change_desc = self._PrepareChange(options, parent,
|
||||
self.branchref)
|
||||
|
||||
new_upload_hash = RunGit(['rev-parse', self.branchref]).strip()
|
||||
latest_tree = RunGit(['rev-parse', self.branchref + ':']).strip()
|
||||
with gclient_utils.temporary_file() as desc_tempfile:
|
||||
gclient_utils.FileWrite(desc_tempfile, change_desc.description)
|
||||
commit_to_cp = RunGit(
|
||||
['commit-tree', latest_tree, '-p', parent, '-F',
|
||||
desc_tempfile]).strip()
|
||||
|
||||
_, upstream_branch_ref = self.FetchUpstreamTuple(self.GetBranch())
|
||||
|
||||
upstream_branch = scm.GIT.ShortBranchName(upstream_branch_ref)
|
||||
upstream_squashed_upload = scm.GIT.GetBranchConfig(
|
||||
settings.GetRoot(), upstream_branch, GERRIT_SQUASH_HASH_CONFIG_KEY)
|
||||
|
||||
RunGit(['checkout', '-q', upstream_squashed_upload])
|
||||
ret, _out = RunGitWithCode(['cherry-pick', commit_to_cp])
|
||||
if ret:
|
||||
RunGit(['cherry-pick', '--abort'])
|
||||
RunGit(['checkout', '-q', self.branch])
|
||||
DieWithError('Could not cleanly cherry-pick')
|
||||
|
||||
commit_to_push = RunGit(['rev-parse', 'HEAD'])
|
||||
RunGit(['checkout', '-q', self.branch])
|
||||
|
||||
return _NewUpload(reviewers, ccs, commit_to_push, new_upload_hash,
|
||||
change_desc)
|
||||
|
||||
def _PrepareChange(self, options, parent, end_commit):
|
||||
# type: (optparse.Values, str, str) ->
|
||||
# Tuple[Sequence[str], Sequence[str], ChangeDescription]
|
||||
|
||||
@@ -3210,8 +3210,12 @@ class ChangelistTest(unittest.TestCase):
|
||||
mock.patch('subprocess2.Popen').start()
|
||||
mock.patch(
|
||||
'git_cl.Changelist.GetGerritProject', return_value='project').start()
|
||||
mock.patch('sys.exit', side_effect=SystemExitMock).start()
|
||||
|
||||
self.addCleanup(mock.patch.stopall)
|
||||
self.temp_count = 0
|
||||
self.mockGit = GitMocks()
|
||||
mock.patch('scm.GIT.GetConfig', self.mockGit.GetConfig).start()
|
||||
|
||||
def testRunHook(self):
|
||||
expected_results = {
|
||||
@@ -3555,6 +3559,79 @@ class ChangelistTest(unittest.TestCase):
|
||||
for user_title in ['not empty', 'yes', 'YES']:
|
||||
self.assertEqual(cl._GetTitleForUpload(options), user_title)
|
||||
|
||||
@mock.patch('git_cl.Settings.GetRoot', return_value='')
|
||||
@mock.patch('git_cl.Changelist.FetchUpstreamTuple')
|
||||
@mock.patch('git_cl.RunGitWithCode')
|
||||
@mock.patch('git_cl.RunGit')
|
||||
@mock.patch('git_cl.Changelist._PrepareChange')
|
||||
@mock.patch('git_cl.Changelist.GetCommonAncestorWithUpstream')
|
||||
def testPrepareCherryPickSquashedCommit(self,
|
||||
mockGetCommonAncestorWithUpstream,
|
||||
mockPrepareChange, mockRunGit,
|
||||
mockRunGitWithCode,
|
||||
mockFetchUpstreamTuple, *_mocks):
|
||||
parent_hash = '1a2bparentcommit'
|
||||
mockGetCommonAncestorWithUpstream.return_value = parent_hash
|
||||
|
||||
change_desc = git_cl.ChangeDescription('BOO!')
|
||||
ccs = ['cc@review.cl']
|
||||
reviewers = ['reviewer@review.cl']
|
||||
mockPrepareChange.return_value = (reviewers, ccs, change_desc)
|
||||
|
||||
branchref = 'refs/heads/current-branch'
|
||||
cl = git_cl.Changelist(branchref=branchref)
|
||||
options = optparse.Values()
|
||||
|
||||
mockFetchUpstreamTuple.return_value = ('', 'refs/heads/upstream')
|
||||
|
||||
upstream_gerrit_hash = 'upstream-gerrit-hash'
|
||||
self.mockGit.config['branch.upstream.%s' %
|
||||
git_cl.GERRIT_SQUASH_HASH_CONFIG_KEY] = (
|
||||
upstream_gerrit_hash)
|
||||
|
||||
latest_tree_hash = 'tree-hash'
|
||||
hash_to_cp = 'squashed-hash'
|
||||
hash_to_push = 'hash-to-push'
|
||||
hash_to_save_as_last_upload = 'last-upload'
|
||||
|
||||
def mock_run_git(commands):
|
||||
if commands == ['rev-parse', branchref]:
|
||||
return hash_to_save_as_last_upload
|
||||
if commands == ['rev-parse', branchref + ':']:
|
||||
return latest_tree_hash
|
||||
if {'commit-tree', latest_tree_hash, '-p', parent_hash,
|
||||
'-F'}.issubset(set(commands)):
|
||||
return hash_to_cp
|
||||
if commands == ['rev-parse', 'HEAD']:
|
||||
return hash_to_push
|
||||
|
||||
mockRunGit.side_effect = mock_run_git
|
||||
|
||||
def mock_run_git_with_code(commands):
|
||||
if commands == ['cherry-pick', hash_to_cp]:
|
||||
return 0, ''
|
||||
|
||||
mockRunGitWithCode.side_effect = mock_run_git_with_code
|
||||
|
||||
new_upload = cl.PrepareCherryPickSquashedCommit(options)
|
||||
self.assertEqual(new_upload.reviewers, reviewers)
|
||||
self.assertEqual(new_upload.ccs, ccs)
|
||||
self.assertEqual(new_upload.commit_to_push, hash_to_push)
|
||||
self.assertEqual(new_upload.new_last_uploaded_commit,
|
||||
hash_to_save_as_last_upload)
|
||||
self.assertEqual(new_upload.change_desc, change_desc)
|
||||
|
||||
# Test failed cherry-pick
|
||||
|
||||
def mock_run_git_with_code(commands):
|
||||
if commands == ['cherry-pick', hash_to_cp]:
|
||||
return 1, ''
|
||||
|
||||
mockRunGitWithCode.side_effect = mock_run_git_with_code
|
||||
|
||||
with self.assertRaises(SystemExitMock):
|
||||
cl.PrepareCherryPickSquashedCommit(options)
|
||||
|
||||
@mock.patch('git_cl.Changelist.GetAffectedFiles', return_value=[])
|
||||
@mock.patch('git_cl.GenerateGerritChangeId', return_value='1a2b3c')
|
||||
@mock.patch('git_cl.Changelist.GetIssue', return_value=None)
|
||||
|
||||
Reference in New Issue
Block a user