Merge instead of rebasing upstream changes in `gclient sync` when --merge is given.

Merge ALL the things!

BUG=none

Review URL: https://codereview.chromium.org/61823002

git-svn-id: svn://svn.chromium.org/chrome/trunk/tools/depot_tools@246575 0039d316-1c4b-4281-b951-d872f2087c98
experimental/szager/collated-output
bauerb@chromium.org 11 years ago
parent 9d2165cd01
commit 30c46d64d7

@ -78,18 +78,6 @@ class GitDiffFilterer(DiffFiltererWrapper):
return re.sub("[a|b]/" + self._current_file, self._replacement_file, line)
def ask_for_data(prompt, options):
if options.jobs > 1:
raise gclient_utils.Error("Background task requires input. Rerun "
"gclient with --jobs=1 so that\n"
"interaction is possible.")
try:
return raw_input(prompt)
except KeyboardInterrupt:
# Hide the exception.
sys.exit(1)
### SCM abstraction layer
# Factory Method for SCM wrapper creation
@ -473,7 +461,8 @@ class GitWrapper(SCMWrapper):
if scm.GIT.IsGitSvn(self.checkout_path) and upstream_branch is not None:
# Our git-svn branch (upstream_branch) is our upstream
self._AttemptRebase(upstream_branch, files, options,
newbase=revision, printed_path=printed_path)
newbase=revision, printed_path=printed_path,
merge=options.merge)
printed_path = True
else:
# Can't find a merge-base since we don't know our upstream. That makes
@ -483,12 +472,13 @@ class GitWrapper(SCMWrapper):
if options.revision or deps_revision:
upstream_branch = revision
self._AttemptRebase(upstream_branch, files, options,
printed_path=printed_path)
printed_path=printed_path, merge=options.merge)
printed_path = True
elif rev_type == 'hash':
# case 2
self._AttemptRebase(upstream_branch, files, options,
newbase=revision, printed_path=printed_path)
newbase=revision, printed_path=printed_path,
merge=options.merge)
printed_path = True
elif revision.replace('heads', 'remotes/' + self.remote) != upstream_branch:
# case 4
@ -509,25 +499,30 @@ class GitWrapper(SCMWrapper):
print('Trying fast-forward merge to branch : %s' % upstream_branch)
try:
merge_args = ['merge']
if not options.merge:
if options.merge:
merge_args.append('--ff')
else:
merge_args.append('--ff-only')
merge_args.append(upstream_branch)
merge_output = scm.GIT.Capture(merge_args, cwd=self.checkout_path)
except subprocess2.CalledProcessError as e:
if re.match('fatal: Not possible to fast-forward, aborting.', e.stderr):
files = []
if not printed_path:
print('\n_____ %s%s' % (self.relpath, rev_str))
printed_path = True
while True:
try:
action = ask_for_data(
'Cannot fast-forward merge, attempt to rebase? '
'(y)es / (q)uit / (s)kip : ', options)
action = self._AskForData(
'Cannot %s, attempt to rebase? '
'(y)es / (q)uit / (s)kip : ' %
('merge' if options.merge else 'fast-forward merge'),
options)
except ValueError:
raise gclient_utils.Error('Invalid Character')
if re.match(r'yes|y', action, re.I):
self._AttemptRebase(upstream_branch, files, options,
printed_path=printed_path)
printed_path=printed_path, merge=False)
printed_path = True
break
elif re.match(r'quit|q', action, re.I):
@ -883,20 +878,40 @@ class GitWrapper(SCMWrapper):
'an existing branch or use \'git checkout %s -b <branch>\' to\n'
'create a new branch for your work.') % (revision, self.remote))
@staticmethod
def _AskForData(prompt, options):
if options.jobs > 1:
raise gclient_utils.Error("Background task requires input. Rerun "
"gclient with --jobs=1 so that\n"
"interaction is possible.")
try:
return raw_input(prompt)
except KeyboardInterrupt:
# Hide the exception.
sys.exit(1)
def _AttemptRebase(self, upstream, files, options, newbase=None,
branch=None, printed_path=False):
branch=None, printed_path=False, merge=False):
"""Attempt to rebase onto either upstream or, if specified, newbase."""
if files is not None:
files.extend(self._Capture(['diff', upstream, '--name-only']).split())
revision = upstream
if newbase:
revision = newbase
action = 'merge' if merge else 'rebase'
if not printed_path:
print('\n_____ %s : Attempting rebase onto %s...' % (
self.relpath, revision))
print('\n_____ %s : Attempting %s onto %s...' % (
self.relpath, action, revision))
printed_path = True
else:
print('Attempting rebase onto %s...' % revision)
print('Attempting %s onto %s...' % (action, revision))
if merge:
merge_output = self._Capture(['merge', revision])
if options.verbose:
print(merge_output)
return
# Build the rebase command here using the args
# git rebase [options] [--onto <newbase>] <upstream> [<branch>]
@ -916,7 +931,7 @@ class GitWrapper(SCMWrapper):
re.match(r'cannot rebase: your index contains uncommitted changes',
e.stderr)):
while True:
rebase_action = ask_for_data(
rebase_action = self._AskForData(
'Cannot rebase because of unstaged changes.\n'
'\'git reset --hard HEAD\' ?\n'
'WARNING: destroys any uncommitted work in your current branch!'

@ -16,7 +16,6 @@ import os
import sys
import tempfile
import unittest
import __builtin__
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
@ -752,6 +751,20 @@ from :3
M 100644 :4 a
M 100644 :5 b
blob
mark :7
data 5
Mooh
commit refs/heads/feature
mark :8
author Bob <bob@example.com> 1390311986 -0000
committer Bob <bob@example.com> 1390311986 -0000
data 6
Add C
from :3
M 100644 :7 c
reset refs/heads/master
from :3
"""
@ -785,6 +798,12 @@ from :3
stderr=STDOUT, cwd=path).communicate()
return True
def _GetAskForDataCallback(self, expected_prompt, return_value):
def AskForData(prompt, options):
self.assertEquals(prompt, expected_prompt)
return return_value
return AskForData
def setUp(self):
TestCaseUtils.setUp(self)
unittest.TestCase.setUp(self)
@ -967,6 +986,51 @@ class ManagedGitWrapperTestCase(BaseGitWrapperTestCase):
'a7142dc9f0009350b96a11f372b6ea658592aa95')
sys.stdout.close()
def testUpdateMerge(self):
if not self.enabled:
return
options = self.Options()
options.merge = True
scm = gclient_scm.CreateSCM(url=self.url, root_dir=self.root_dir,
relpath=self.relpath)
scm._Run(['checkout', '-q', 'feature'], options)
rev = scm.revinfo(options, (), None)
file_list = []
scm.update(options, (), file_list)
self.assertEquals(file_list, [join(self.base_path, x)
for x in ['a', 'b', 'c']])
# The actual commit that is created is unstable, so we verify its tree and
# parents instead.
self.assertEquals(scm._Capture(['rev-parse', 'HEAD:']),
'd2e35c10ac24d6c621e14a1fcadceb533155627d')
self.assertEquals(scm._Capture(['rev-parse', 'HEAD^1']), rev)
self.assertEquals(scm._Capture(['rev-parse', 'HEAD^2']),
scm._Capture(['rev-parse', 'origin/master']))
sys.stdout.close()
def testUpdateRebase(self):
if not self.enabled:
return
options = self.Options()
scm = gclient_scm.CreateSCM(url=self.url, root_dir=self.root_dir,
relpath=self.relpath)
scm._Run(['checkout', '-q', 'feature'], options)
file_list = []
# Fake a 'y' key press.
scm._AskForData = self._GetAskForDataCallback(
'Cannot fast-forward merge, attempt to rebase? '
'(y)es / (q)uit / (s)kip : ', 'y')
scm.update(options, (), file_list)
self.assertEquals(file_list, [join(self.base_path, x)
for x in ['a', 'b', 'c']])
# The actual commit that is created is unstable, so we verify its tree and
# parent instead.
self.assertEquals(scm._Capture(['rev-parse', 'HEAD:']),
'd2e35c10ac24d6c621e14a1fcadceb533155627d')
self.assertEquals(scm._Capture(['rev-parse', 'HEAD^']),
scm._Capture(['rev-parse', 'origin/master']))
sys.stdout.close()
def testUpdateReset(self):
if not self.enabled:
return
@ -1039,7 +1103,9 @@ class ManagedGitWrapperTestCase(BaseGitWrapperTestCase):
file_path = join(self.base_path, 'b')
open(file_path, 'w').writelines('conflict\n')
scm._Run(['commit', '-am', 'test'], options)
__builtin__.raw_input = lambda x: 'y'
scm._AskForData = self._GetAskForDataCallback(
'Cannot fast-forward merge, attempt to rebase? '
'(y)es / (q)uit / (s)kip : ', 'y')
exception = ('Conflict while rebasing this branch.\n'
'Fix the conflict and run gclient again.\n'
'See \'man git-rebase\' for details.\n')

Loading…
Cancel
Save