[PATCH 3 of 3 STABLE] largefiles: don't copy largefiles from working dir to the store while converting

Matt Harbison matt_harbison at yahoo.com
Mon Oct 22 23:04:12 CDT 2012

# HG changeset patch
# User Matt Harbison <matt_harbison at yahoo.com>
# Date 1350959915 14400
# Branch stable
# Node ID bf99167cc61bc66ae71c96b25da34688902a515f
# Parent  a233e59d55e75f810488a0c94ff2e1e17696ba23
largefiles: don't copy largefiles from working dir to the store while converting

Previously, if one or more largefiles for a repo being converted were not in the
usercache, the convert would abort with a reference to the largefile being
missing (as opposed to the previous patch, where the standin was referenced as
missing).  This is because commitctx() tries to copy all largefiles to the
local store, first from the user cache, and if the file isn't found there, from
the working directory.  No files will exist in the working directory during a
convert, however.  It is not sufficient to force the source repo to be local
before proceeding, because clone and pull do not download largefiles by default.

This is slightly less than ideal because while the conversion will now complete,
it won't be possible to update to revs with missing largefiles unless the user
intervenes manually, because there is no default path pointing back to the
source repo.  Ideally these files would be cached during the conversion.

This check could have been done in reposetup.commitctx() instead, but this
ensures the local store directory is created, which is necessary to enable the
standin matcher.

diff --git a/hgext/largefiles/lfutil.py b/hgext/largefiles/lfutil.py
--- a/hgext/largefiles/lfutil.py
+++ b/hgext/largefiles/lfutil.py
@@ -234,7 +234,7 @@
     util.makedirs(os.path.dirname(storepath(repo, hash)))
     if inusercache(repo.ui, hash):
         link(usercachepath(repo.ui, hash), storepath(repo, hash))
-    else:
+    elif not getattr(repo, "_isconverting", False):
         dst = util.atomictempfile(storepath(repo, hash),
         for chunk in util.filechunkiter(open(file, 'rb')):
diff --git a/hgext/largefiles/overrides.py b/hgext/largefiles/overrides.py
--- a/hgext/largefiles/overrides.py
+++ b/hgext/largefiles/overrides.py
@@ -1113,3 +1113,11 @@
         result = orig(ui, repo, file1, *pats, **opts)
         return result
     return lfcommands.catlfile(repo, file1, ctx.rev(), opts.get('output'))
+def mercurialsinkbefore(orig, sink):
+    sink.repo._isconverting = True
+    orig(sink)
+def mercurialsinkafter(orig, sink):
+    sink.repo._isconverting = False
+    orig(sink)
diff --git a/hgext/largefiles/uisetup.py b/hgext/largefiles/uisetup.py
--- a/hgext/largefiles/uisetup.py
+++ b/hgext/largefiles/uisetup.py
@@ -168,3 +168,10 @@
         if name == 'transplant':
             extensions.wrapcommand(getattr(module, 'cmdtable'), 'transplant',
+        if name == 'convert':
+            convcmd = getattr(module, 'convcmd')
+            hgsink = getattr(convcmd, 'mercurial_sink')
+            extensions.wrapfunction(hgsink, 'before',
+                                    overrides.mercurialsinkbefore)
+            extensions.wrapfunction(hgsink, 'after',
+                                    overrides.mercurialsinkafter)
diff --git a/tests/test-lfconvert.t b/tests/test-lfconvert.t
--- a/tests/test-lfconvert.t
+++ b/tests/test-lfconvert.t
@@ -275,6 +275,9 @@
   $ cd ..
+Clearing the usercache ensures that commitctx doesn't try to cache largefiles
+from the working dir on a convert.
+  $ rm -f "${USERCACHE}"/*
   $ hg convert largefiles-repo
   assuming destination largefiles-repo-hg
   initializing destination largefiles-repo-hg repository

More information about the Mercurial-devel mailing list