Patchwork D9040: merge: use in-memory mergestate when using in-memory context

login
register
mail settings
Submitter phabricator
Date Sept. 17, 2020, 8:11 p.m.
Message ID <differential-rev-PHID-DREV-p5etle57jpismvs3lost-req@mercurial-scm.org>
Download mbox | patch
Permalink /patch/47201/
State Superseded
Headers show

Comments

phabricator - Sept. 17, 2020, 8:11 p.m.
martinvonz created this revision.
Herald added a reviewer: hg-reviewers.
Herald added a subscriber: mercurial-patches.

REVISION SUMMARY
  This is my version of Augie's D8568 <https://phab.mercurial-scm.org/D8568>. It makes it so we don't touch the
  mergestate on disk when using an in-memory context.
  
  The reason that I want this is not the same as the reason that Augie
  write his patch (though I agree with that reason too). My hope is to
  make in-memory rebase not fall back to on-disk rebase when there are
  conflict. I plan to do that by adding a
  `overlayworkingctx.reflect_in_workingcopy()`. The idea is that that
  will update the working copy, the dirstate and the mergestate as
  necessary.

REPOSITORY
  rHG Mercurial

BRANCH
  default

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

AFFECTED FILES
  mercurial/context.py
  mercurial/merge.py
  mercurial/mergestate.py

CHANGE DETAILS




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

Patch

diff --git a/mercurial/mergestate.py b/mercurial/mergestate.py
--- a/mercurial/mergestate.py
+++ b/mercurial/mergestate.py
@@ -802,6 +802,32 @@ 
         shutil.rmtree(self._repo.vfs.join(b'merge'), True)
 
 
+class memmergestate(_mergestate_base):
+    def __init__(self, repo):
+        super(memmergestate, self).__init__(repo)
+        self._backups = {}
+
+    def _make_backup(self, fctx, localkey):
+        self._backups[localkey] = fctx.data()
+
+    def _restore_backup(self, fctx, localkey, flags):
+        fctx.write(self._backups[localkey], flags)
+
+    @util.propertycache
+    def mergedriver(self):
+        configmergedriver = self._repo.ui.config(
+            b'experimental', b'mergedriver'
+        )
+        if configmergedriver:
+            raise error.InMemoryMergeConflictsError(
+                b"in-memory merge does not support mergedriver"
+            )
+        return None
+
+    def commit(self):
+        pass
+
+
 def recordupdates(repo, actions, branchmerge, getfiledata):
     """record merge actions to the dirstate"""
     # remove (must come first)
diff --git a/mercurial/merge.py b/mercurial/merge.py
--- a/mercurial/merge.py
+++ b/mercurial/merge.py
@@ -1398,7 +1398,7 @@ 
     _prefetchfiles(repo, mctx, mresult)
 
     updated, merged, removed = 0, 0, 0
-    ms = mergestatemod.mergestate.clean(repo)
+    ms = wctx.mergestate(clean=True)
     ms.start(wctx.p1().node(), mctx.node(), labels)
 
     for f, op in pycompat.iteritems(mresult.commitinfo):
@@ -1611,10 +1611,6 @@ 
     usemergedriver = not overwrite and mergeactions and ms.mergedriver
 
     if usemergedriver:
-        if wctx.isinmemory():
-            raise error.InMemoryMergeConflictsError(
-                b"in-memory merge does not support mergedriver"
-            )
         ms.commit()
         proceed = driverpreprocess(repo, ms, wctx, labels=labels)
         # the driver might leave some files unresolved
@@ -1895,7 +1891,7 @@ 
         if not overwrite:
             if len(pl) > 1:
                 raise error.Abort(_(b"outstanding uncommitted merge"))
-            ms = mergestatemod.mergestate.read(repo)
+            ms = wc.mergestate()
             if list(ms.unresolved()):
                 raise error.Abort(
                     _(b"outstanding merge conflicts"),
diff --git a/mercurial/context.py b/mercurial/context.py
--- a/mercurial/context.py
+++ b/mercurial/context.py
@@ -2528,6 +2528,7 @@ 
         return path in self._cache
 
     def clean(self):
+        self._mergestate = None
         self._cache = {}
 
     def _compact(self):
@@ -2592,6 +2593,11 @@ 
             self._repo, path, parent=self, filelog=filelog
         )
 
+    def mergestate(self, clean=False):
+        if clean or self._mergestate is None:
+            self._mergestate = mergestatemod.memmergestate(self._repo)
+        return self._mergestate
+
 
 class overlayworkingfilectx(committablefilectx):
     """Wrap a ``workingfilectx`` but intercepts all writes into an in-memory