From 5bde48530744a26c252d152df34524522a80b29a Mon Sep 17 00:00:00 2001 From: "msb@chromium.org" Date: Mon, 14 Dec 2009 16:47:12 +0000 Subject: [PATCH] gclient: Add better error reporting and handling when there is a rebase conflict When a rebase generates a conflict, report an error and exit immediately. If in an existing conflict (no branch), report an error and exit immediately. Review URL: http://codereview.chromium.org/496003 git-svn-id: svn://svn.chromium.org/chrome/trunk/tools/depot_tools@34459 0039d316-1c4b-4281-b951-d872f2087c98 --- gclient_scm.py | 32 ++++++++++++++++++++++++++++++-- tests/gclient_scm_test.py | 25 ++++++++++++++++++++++++- 2 files changed, 54 insertions(+), 3 deletions(-) diff --git a/gclient_scm.py b/gclient_scm.py index 8c7e70f206..a3e902cf64 100644 --- a/gclient_scm.py +++ b/gclient_scm.py @@ -140,13 +140,32 @@ class GitWrapper(SCMWrapper, scm.GIT): new_base = 'origin' if revision: new_base = revision - cur_branch = self._Run(['symbolic-ref', 'HEAD']).split('/')[-1] + cur_branch = self._GetCurrentBranch() + + # Check if we are in a rebase conflict + if cur_branch is None: + raise gclient_utils.Error('\n____ %s%s\n' + '\tAlready in a conflict, i.e. (no branch).\n' + '\tFix the conflict and run gclient again.\n' + '\tOr to abort run:\n\t\tgit-rebase --abort\n' + '\tSee man git-rebase for details.\n' + % (self.relpath, rev_str)) + merge_base = self._Run(['merge-base', 'HEAD', new_base]) self._Run(['remote', 'update'], redirect_stdout=False) files = self._Run(['diff', new_base, '--name-only']).split() file_list.extend([os.path.join(self.checkout_path, f) for f in files]) self._Run(['rebase', '-v', '--onto', new_base, merge_base, cur_branch], - redirect_stdout=False) + redirect_stdout=False, checkrc=False) + + # If the rebase generated a conflict, abort and ask user to fix + if self._GetCurrentBranch() is None: + raise gclient_utils.Error('\n____ %s%s\n' + '\nConflict while rebasing this branch.\n' + 'Fix the conflict and run gclient again.\n' + 'See man git-rebase for details.\n' + % (self.relpath, rev_str)) + print "Checked out revision %s." % self.revinfo(options, (), None) def revert(self, options, args, file_list): @@ -204,6 +223,15 @@ class GitWrapper(SCMWrapper, scm.GIT): elif min_ver < ver: return + def _GetCurrentBranch(self): + # Returns name of current branch + # Returns None if inside a (no branch) + tokens = self._Run(['branch']).split() + branch = tokens[tokens.index('*') + 1] + if branch == '(no': + return None + return branch + def _Run(self, args, cwd=None, checkrc=True, redirect_stdout=True): # TODO(maruel): Merge with Capture? if cwd is None: diff --git a/tests/gclient_scm_test.py b/tests/gclient_scm_test.py index 8d37678ddc..a5413ca136 100755 --- a/tests/gclient_scm_test.py +++ b/tests/gclient_scm_test.py @@ -279,7 +279,7 @@ class SVNWrapperTestCase(BaseTestCase): scm.update(options, self.args, file_list) -class GitWrapperTestCase(SuperMoxBaseTestBase): +class GitWrapperTestCase(BaseTestCase): """This class doesn't use pymox.""" class OptionsObject(object): def __init__(self, test_case, verbose=False, revision=None): @@ -506,6 +506,29 @@ from :3 self.assertEquals(scm.revinfo(options, (), None), 'a7142dc9f0009350b96a11f372b6ea658592aa95') + def testUpdateConflict(self): + if not self.enabled: + return + options = self.Options() + scm = gclient_scm.CreateSCM(url=self.url, root_dir=self.root_dir, + relpath=self.relpath) + file_path = gclient_scm.os.path.join(self.base_path, 'b') + f = open(file_path, 'w').writelines('conflict\n') + scm._Run(['commit', '-am', 'test']) + exception = \ + '\n____ .\n' \ + '\nConflict while rebasing this branch.\n' \ + 'Fix the conflict and run gclient again.\n' \ + 'See man git-rebase for details.\n' + self.assertRaisesError(exception, scm.update, options, (), []) + exception = \ + '\n____ .\n' \ + '\tAlready in a conflict, i.e. (no branch).\n' \ + '\tFix the conflict and run gclient again.\n' \ + '\tOr to abort run:\n\t\tgit-rebase --abort\n' \ + '\tSee man git-rebase for details.\n' + self.assertRaisesError(exception, scm.update, options, (), []) + def testRevinfo(self): if not self.enabled: return