largefiles: prevent in-memory merge instead of switching to on-disk
authorMartin von Zweigbergk <martinvonz@google.com>
Tue, 22 Sep 2020 23:18:37 -0700
changeset 45545 e5e1285b6f6f
parent 45544 2b339c6c6e99
child 45546 3d47b5c7fe8d
largefiles: prevent in-memory merge instead of switching to on-disk I enabled in-memory merge by default while testing some changes. I spent quite some time troubleshooting why largefiles was still creating an on-disk mergestate. Then I found out that it ignores the callers `wc` argument to `mergemod._update()` and always uses on-disk merge. This patch changes that so we raise an error if largefiles is used with in-memory merge. That way we'll notice if in-memory merge is used with largefiles instead of silently replacing ignoring the `overlayworkingctx` instance and updating the working copy instead. I felt a little bad that this would break things more for users with both largefiles and in-memory rebase enabled. So I also added a higher-level override to make sure that largefiles disables in-memory rebase. It turns out that that fixes `run-tests.py -k largefiles --extra-config-opt rebase.experimental.inmemory=1`. Differential Revision: https://phab.mercurial-scm.org/D9069
hgext/largefiles/__init__.py
hgext/largefiles/overrides.py
--- a/hgext/largefiles/__init__.py	Mon Sep 21 09:56:48 2020 -0700
+++ b/hgext/largefiles/__init__.py	Tue Sep 22 23:18:37 2020 -0700
@@ -195,7 +195,9 @@
     for name, module in extensions.extensions():
         if name == b'rebase':
             # TODO: teach exthelper to handle this
-            extensions.wrapfunction(module, b'rebase', overrides.overriderebase)
+            extensions.wrapfunction(
+                module, b'rebase', overrides.overriderebasecmd
+            )
 
 
 revsetpredicate = eh.revsetpredicate
--- a/hgext/largefiles/overrides.py	Mon Sep 21 09:56:48 2020 -0700
+++ b/hgext/largefiles/overrides.py	Tue Sep 22 23:18:37 2020 -0700
@@ -1103,7 +1103,7 @@
 
 
 @eh.wrapcommand(b'rebase', extension=b'rebase')
-def overriderebase(orig, ui, repo, **opts):
+def overriderebasecmd(orig, ui, repo, **opts):
     if not util.safehasattr(repo, b'_largefilesenabled'):
         return orig(ui, repo, **opts)
 
@@ -1111,12 +1111,30 @@
     repo._lfcommithooks.append(lfutil.automatedcommithook(resuming))
     repo._lfstatuswriters.append(lambda *msg, **opts: None)
     try:
-        return orig(ui, repo, **opts)
+        with ui.configoverride(
+            {(b'rebase', b'experimental.inmemory'): False}, b"largefiles"
+        ):
+            return orig(ui, repo, **opts)
     finally:
         repo._lfstatuswriters.pop()
         repo._lfcommithooks.pop()
 
 
+@eh.extsetup
+def overriderebase(ui):
+    try:
+        rebase = extensions.find(b'rebase')
+    except KeyError:
+        pass
+    else:
+
+        def _dorebase(orig, *args, **kwargs):
+            kwargs['inmemory'] = False
+            return orig(*args, **kwargs)
+
+        extensions.wrapfunction(rebase, b'_dorebase', _dorebase)
+
+
 @eh.wrapcommand(b'archive')
 def overridearchivecmd(orig, ui, repo, dest, **opts):
     with lfstatus(repo.unfiltered()):
@@ -1758,10 +1776,13 @@
         lfdirstate.write()
 
         oldstandins = lfutil.getstandinsstate(repo)
-        # Make sure the merge runs on disk, not in-memory. largefiles is not a
-        # good candidate for in-memory merge (large files, custom dirstate,
-        # matcher usage).
-        kwargs['wc'] = repo[None]
+        wc = kwargs.get('wc')
+        if wc and wc.isinmemory():
+            # largefiles is not a good candidate for in-memory merge (large
+            # files, custom dirstate, matcher usage).
+            raise error.ProgrammingError(
+                b'largefiles is not compatible with in-memory merge'
+            )
         result = orig(repo, node, branchmerge, force, *args, **kwargs)
 
         newstandins = lfutil.getstandinsstate(repo)