# HG changeset patch # User Matt Harbison # Date 1523155211 14400 # Node ID 491edf2435a0c1257e2099755116b87789e7a6b6 # Parent 20808ddb49901008a227aee944dbcee071bcc85d lfs: add the ability to disable the usercache While the usercache is important for real world uses, I've been tripped up more than a couple of times by it in tests- thinking a file was being downloaded, but it was simply linked from the local cache. The syntax for setting it is the same as for setting a null remote endpoint, and like that endpoint, is left undocumented. This may or may not be a useful feature in the real world (I'd expect any sane filesystem to support hardlinks at this point). diff -r 20808ddb4990 -r 491edf2435a0 hgext/lfs/blobstore.py --- a/hgext/lfs/blobstore.py Tue Apr 10 22:57:55 2018 -0400 +++ b/hgext/lfs/blobstore.py Sat Apr 07 22:40:11 2018 -0400 @@ -7,6 +7,7 @@ from __future__ import absolute_import +import errno import hashlib import json import os @@ -59,6 +60,26 @@ yield ('', [], oids) +class nullvfs(lfsvfs): + def __init__(self): + pass + + def exists(self, oid): + return False + + def read(self, oid): + # store.read() calls into here if the blob doesn't exist in its + # self.vfs. Raise the same error as a normal vfs when asked to read a + # file that doesn't exist. The only difference is the full file path + # isn't available in the error. + raise IOError(errno.ENOENT, '%s: No such file or directory' % oid) + + def walk(self, path=None, onerror=None): + return ('', [], []) + + def write(self, oid, data): + pass + class filewithprogress(object): """a file-like object that supports __len__ and read. @@ -97,8 +118,14 @@ def __init__(self, repo): fullpath = repo.svfs.join('lfs/objects') self.vfs = lfsvfs(fullpath) - usercache = lfutil._usercachedir(repo.ui, 'lfs') - self.cachevfs = lfsvfs(usercache) + usercache = util.url(lfutil._usercachedir(repo.ui, 'lfs')) + if usercache.scheme in (None, 'file'): + self.cachevfs = lfsvfs(usercache.localpath()) + elif usercache.scheme == 'null': + self.cachevfs = nullvfs() + else: + raise error.Abort(_('unknown lfs cache scheme: %s') + % usercache.scheme) self.ui = repo.ui def open(self, oid): @@ -129,11 +156,7 @@ if realoid != oid: raise error.Abort(_('corrupt remote lfs object: %s') % oid) - # XXX: should we verify the content of the cache, and hardlink back to - # the local store on success, but truncate, write and link on failure? - if not self.cachevfs.exists(oid): - self.ui.note(_('lfs: adding %s to the usercache\n') % oid) - lfutil.link(self.vfs.join(oid), self.cachevfs.join(oid)) + self._linktousercache(oid) def write(self, oid, data): """Write blob to local blobstore. @@ -144,9 +167,13 @@ with self.vfs(oid, 'wb', atomictemp=True) as fp: fp.write(data) + self._linktousercache(oid) + + def _linktousercache(self, oid): # XXX: should we verify the content of the cache, and hardlink back to # the local store on success, but truncate, write and link on failure? - if not self.cachevfs.exists(oid): + if (not self.cachevfs.exists(oid) + and not isinstance(self.cachevfs, nullvfs)): self.ui.note(_('lfs: adding %s to the usercache\n') % oid) lfutil.link(self.vfs.join(oid), self.cachevfs.join(oid)) diff -r 20808ddb4990 -r 491edf2435a0 tests/test-lfs-serve.t --- a/tests/test-lfs-serve.t Tue Apr 10 22:57:55 2018 -0400 +++ b/tests/test-lfs-serve.t Sat Apr 07 22:40:11 2018 -0400 @@ -35,6 +35,7 @@ $ cat >> $HGRCPATH < [lfs] > url=file:$TESTTMP/dummy-remote/ + > usercache = null:// > threshold=10 > [web] > allow_push=*