Patchwork D9076: rebase: teach in-memory rebase to not restart with on-disk rebase on conflict

login
register
mail settings
Submitter phabricator
Date Sept. 23, 2020, 5:30 p.m.
Message ID <differential-rev-PHID-DREV-f5g2qadj3ooewc533ql4-req@mercurial-scm.org>
Download mbox | patch
Permalink /patch/47262/
State Superseded
Headers show

Comments

phabricator - Sept. 23, 2020, 5:30 p.m.
martinvonz created this revision.
Herald added a reviewer: hg-reviewers.
Herald added a subscriber: mercurial-patches.

REVISION SUMMARY
  When in-memory rebase runs into conflicts, it redoes the whole rebase
  operation. This patch teaches it to instead discard just the current
  `overlayworkingctx` and redo that node on disk.
  
  I've tested this by enabling in-memory rebase by default and checking
  that there are no unexpected differences after this patch.
  
  The next step is to make it so that `hg rebase --continue` can use
  in-memory merge.

REPOSITORY
  rHG Mercurial

BRANCH
  default

REVISION DETAIL
  https://phab.mercurial-scm.org/D9076

AFFECTED FILES
  hgext/rebase.py
  tests/test-rebase-inmemory.t

CHANGE DETAILS




To: martinvonz, #hg-reviewers
Cc: mercurial-patches, mercurial-devel

Patch

diff --git a/tests/test-rebase-inmemory.t b/tests/test-rebase-inmemory.t
--- a/tests/test-rebase-inmemory.t
+++ b/tests/test-rebase-inmemory.t
@@ -415,8 +415,6 @@ 
   rebasing 3:055a42cdd887 "d"
   rebasing 4:e860deea161a "e"
   merging e
-  transaction abort!
-  rollback completed
   hit a merge conflict
   [1]
   $ hg diff
@@ -463,12 +461,7 @@ 
   rebasing 3:055a42cdd887 "d"
   rebasing 4:e860deea161a "e"
   merging e
-  transaction abort!
-  rollback completed
-  hit merge conflicts; re-running rebase without in-memory merge
-  rebasing 2:177f92b77385 "c"
-  rebasing 3:055a42cdd887 "d"
-  rebasing 4:e860deea161a "e"
+  hit merge conflicts; rebasing that commit again in the working copy
   merging e
   warning: conflicts while merging e! (edit, then use 'hg resolve --mark')
   unresolved conflicts (see 'hg resolve', then 'hg rebase --continue')
@@ -487,9 +480,9 @@ 
   rebasing 3:055a42cdd887 "d"
   rebasing 4:e860deea161a "e"
   merging e
+  hit merge conflicts; rebasing that commit again in the working copy
   transaction abort!
   rollback completed
-  hit merge conflicts; re-running rebase without in-memory merge
   abort: uncommitted changes
   [255]
   $ cat a
@@ -859,8 +852,7 @@ 
   $ hg rebase -r . -d 1 --config ui.merge=internal:merge3
   rebasing 2:fb62b706688e "add b to foo" (tip)
   merging foo
-  hit merge conflicts; re-running rebase without in-memory merge
-  rebasing 2:fb62b706688e "add b to foo" (tip)
+  hit merge conflicts; rebasing that commit again in the working copy
   merging foo
   warning: conflicts while merging foo! (edit, then use 'hg resolve --mark')
   unresolved conflicts (see 'hg resolve', then 'hg rebase --continue')
@@ -893,8 +885,7 @@ 
   $ hg rebase -r 2 -d 1 -t:merge3
   rebasing 2:b4d249fbf8dd "bye from foo"
   merging foo
-  hit merge conflicts; re-running rebase without in-memory merge
-  rebasing 2:b4d249fbf8dd "bye from foo"
+  hit merge conflicts; rebasing that commit again in the working copy
   merging foo
   warning: conflicts while merging foo! (edit, then use 'hg resolve --mark')
   unresolved conflicts (see 'hg resolve', then 'hg rebase --continue')
diff --git a/hgext/rebase.py b/hgext/rebase.py
--- a/hgext/rebase.py
+++ b/hgext/rebase.py
@@ -614,9 +614,43 @@ 
             else:
                 overrides = {(b'ui', b'forcemerge'): opts.get(b'tool', b'')}
                 with ui.configoverride(overrides, b'rebase'):
-                    rebasenode(
-                        repo, rev, p1, p2, base, self.collapsef, wctx=self.wctx,
-                    )
+                    try:
+                        rebasenode(
+                            repo,
+                            rev,
+                            p1,
+                            p2,
+                            base,
+                            self.collapsef,
+                            wctx=self.wctx,
+                        )
+                    except error.InMemoryMergeConflictsError:
+                        if self.dryrun:
+                            raise error.ConflictResolutionRequired(b'rebase')
+                        if self.collapsef:
+                            # TODO: Make the overlayworkingctx reflected
+                            # in the working copy here instead of re-raising
+                            # so the entire rebase operation is retried.
+                            raise
+                        ui.status(
+                            _(
+                                b"hit merge conflicts; rebasing that "
+                                b"commit again in the working copy\n"
+                            )
+                        )
+                        cmdutil.bailifchanged(repo)
+                        self.inmemory = False
+                        self._assignworkingcopy()
+                        mergemod.update(repo[p1])
+                        rebasenode(
+                            repo,
+                            rev,
+                            p1,
+                            p2,
+                            base,
+                            self.collapsef,
+                            wctx=self.wctx,
+                        )
             if not self.collapsef:
                 merging = p2 != nullrev
                 editform = cmdutil.mergeeditform(merging, b'rebase')
@@ -1099,7 +1133,7 @@ 
                 _origrebase(
                     ui, repo, action, opts, rbsrt,
                 )
-        except error.InMemoryMergeConflictsError:
+        except error.ConflictResolutionRequired:
             ui.status(_(b'hit a merge conflict\n'))
             return 1
         except error.Abort: