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
--- 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)