diff --git a/hgext3rd/lfs/__init__.py b/hgext3rd/lfs/__init__.py --- a/hgext3rd/lfs/__init__.py +++ b/hgext3rd/lfs/__init__.py @@ -73,6 +73,10 @@ wrapfunction(filelog, 'renamed', wrapper.filelogrenamed) wrapfunction(filelog, 'size', wrapper.filelogsize) +def wrapfileserverclient(service): + wrapfunction = extensions.wrapfunction + wrapfunction(service, 'prefetch', wrapper.prefetch) + def extsetup(ui): wrapfilelog(filelog.filelog) diff --git a/hgext3rd/lfs/wrapper.py b/hgext3rd/lfs/wrapper.py --- a/hgext3rd/lfs/wrapper.py +++ b/hgext3rd/lfs/wrapper.py @@ -12,6 +12,7 @@ from mercurial import ( error, filelog, + node, revlog, util, ) @@ -180,6 +181,10 @@ # if remotestore is a null store, upload is a no-op and can be skipped return isinstance(repo.svfs.lfsremoteblobstore, blobstore._nullremote) +def _candownload(repo): + # if remotestore is a null store, downloads will lead to nothing + return not isinstance(repo.svfs.lfsremoteblobstore, blobstore._nullremote) + def uploadblobsfromrevs(repo, revs): '''upload lfs blobs introduced by revs @@ -241,3 +246,23 @@ remoteblob = repo.svfs.lfsremoteblobstore remoteblob.writebatch(pointers, repo.svfs.lfslocalblobstore) + +def prefetch(orig, self, fileids, force=False, fetchdata=True, + fetchhistory=False): + orig(self, fileids, force, fetchdata, fetchhistory) + if not _candownload(self.repo): + return + pointers = [] + store = self.repo.svfs.lfslocalblobstore + for file, id in fileids: + nodehash = node.bin(id) + rlog = self.repo.file(file) + if rlog.flags(nodehash) & revlog.REVIDX_EXTSTORED: + text = rlog.revision(nodehash, raw=True) + p = pointer.deserialize(text) + oid = p.oid() + if not store.has(oid): + pointers.append(p) + if len(pointers) > 0: + self.repo.svfs.lfsremoteblobstore.readbatch(pointers, store) + assert all(store.has(p.oid()) for p in pointers) diff --git a/remotefilelog/__init__.py b/remotefilelog/__init__.py --- a/remotefilelog/__init__.py +++ b/remotefilelog/__init__.py @@ -123,6 +123,7 @@ except KeyError: pass if lfsmod: + lfsmod.wrapfileserverclient(fileserverclient.fileserverclient) lfsmod.wrapfilelog(remotefilelog.remotefilelog) extensions.afterloaded('lfs', _lfsloaded) diff --git a/tests/library.sh b/tests/library.sh --- a/tests/library.sh +++ b/tests/library.sh @@ -38,6 +38,30 @@ EOF } +hgcloneshallowlfs() { + local name + local dest + local lfsdir + orig=$1 + shift + dest=$1 + shift + lfsdir=$1 + shift + hg clone --shallow --config "extensions.lfs=" --config "lfs.url=$lfsdir" --config remotefilelog.reponame=master $orig $dest $@ + cat >> $dest/.hg/hgrc <> $HGRCPATH < [extensions] + > lfs=$TESTDIR/../hgext3rd/lfs + > [lfs] + > url=file://$LFSPATH + > EOF + $ cat >> .hg/hgrc < [remotefilelog] + > server=True + > EOF + $ echo x > x + $ echo z > z + $ hg commit -qAm x + $ echo x2 > x + $ echo y > y + $ hg commit -qAm y + $ echo large > large + $ hg --config 'lfs.threshold=1' commit -qAm y + $ hg bookmark foo + $ hg debuglfsupload -r tip + + $ cd .. + +# prefetch a revision + + $ hgcloneshallowlfs ssh://user@dummy/master shallow file://$LFSPATH --noupdate + streaming all changes + 2 files to transfer, 774 bytes of data + transferred 774 bytes in * seconds (*/sec) (glob) + searching for changes + no changes found + $ cd shallow + + $ hg prefetch -r 0 + 2 files fetched over 1 fetches - (2 misses, 0.00% hit ratio) over *s (glob) + + $ hg cat -r 0 x + x + +# prefetch a range of revisions + + $ clearcache + $ hg prefetch -r 0::1 + 4 files fetched over 1 fetches - (4 misses, 0.00% hit ratio) over *s (glob) + + $ hg cat -r 0 x + x + $ hg cat -r 1 x + x2 + +# prefetch certain files + + $ clearcache + $ hg prefetch -r 1 x + 1 files fetched over 1 fetches - (1 misses, 0.00% hit ratio) over *s (glob) + + $ hg cat -r 1 x + x2 + + $ hg cat -r 1 y + y + 1 files fetched over 1 fetches - (1 misses, 0.00% hit ratio) over *s (glob) + +# prefetch large file + + $ hg prefetch -r 2 + 2 files fetched over 1 fetches - (2 misses, 0.00% hit ratio) over *s (glob) + +# prefetch on pull when configured + + $ printf "[remotefilelog]\npullprefetch=bookmark()\n" >> .hg/hgrc + $ hg strip tip + saved backup bundle to $TESTTMP/shallow/.hg/strip-backup/730e2b7b175c-acada81e-backup.hg (glob) + + $ clearcache + $ hg pull + pulling from ssh://user@dummy/master + searching for changes + adding changesets + adding manifests + adding file changes + added 1 changesets with 0 changes to 0 files + updating bookmark foo + (run 'hg update' to get a working copy) + prefetching file contents + 4 files fetched over 1 fetches - (4 misses, 0.00% hit ratio) over *s (glob) + + $ hg up tip + 4 files updated, 0 files merged, 0 files removed, 0 files unresolved