Submitter | Remi Chaintron |
---|---|
Date | Oct. 27, 2016, 3:04 p.m. |
Message ID | <c7dc98eb24cd40e46e73.1477580644@remi-mbp2.dhcp.thefacebook.com> |
Download | mbox | patch |
Permalink | /patch/17206/ |
State | Deferred |
Headers | show |
Comments
On Thu, Oct 27, 2016 at 04:04:04PM +0100, Remi Chaintron wrote: > # HG changeset patch > # User Remi Chaintron <remi@fb.com> > # Date 1477579974 -3600 > # Thu Oct 27 15:52:54 2016 +0100 > # Branch stable > # Node ID c7dc98eb24cd40e46e73dea275b4c5b245155efb > # Parent 202b2a6872d3b3ffb1f373910c4eadffda8f727a > [RFC] extension: `dummy` and composition with `lfs` > > This is a proof of concept for the composition of non-reflexive operations on > filelogs using extensions relying on the flagprocessor design. Could this be tested using censor instead? > > diff --git a/hgext/dummy.py b/hgext/dummy.py > new file mode 100644 > --- /dev/null > +++ b/hgext/dummy.py > @@ -0,0 +1,83 @@ > +# coding=UTF-8 > + > +from __future__ import absolute_import > + > +from mercurial import ( > + cmdutil, > + commands, > + extensions, > + filelog, > + revlog, > +) > + > +def wrappedread(self, text): > + return text[6:], True > + > +def getfilelogcontent(self, text): > + return text, False > + > +extensionflag = revlog.REVIDX_ISDUMMY > +transformmap = { > + extensionflag: wrappedread > +} > + > +def revision(orig, self, nodeorrev, _df=None): > + self.flagprocessor.register(transformmap) > + try: > + return orig(self, nodeorrev, _df=_df) > + finally: > + self.flagprocessor.unregister(transformmap) > + > + > +def addrevision(orig, self, text, transaction, link, p1, p2, cachedelta=None, > + node=None, flags=revlog.REVLOG_DEFAULT_FLAGS): > + self.flagprocessor.register(transformmap) > + try: > + if self._peek_isdummy(text): > + if node is None: > + node = revlog.hash(text, p1, p2) > + text = 'DUMMY:%s' % (text) > + flags |= extensionflag > + return orig(self, text, transaction, link, p1, p2, cachedelta=cachedelta, > + node=node, flags=flags) > + finally: > + self.flagprocessor.unregister(transformmap) > + > +def addgroup(orig, self, cg, linkmapper, transaction, addrevisioncb=None): > + self.flagprocessor.register(transformmap) > + try: > + return orig(self, cg, linkmapper, transaction, > + addrevisioncb=addrevisioncb) > + finally: > + self.flagprocessor.unregister(transformmap) > + > +def debugdata(orig, ui, repo, file_, rev=None, **opts): > + transformmap[extensionflag] = getfilelogcontent > + orig(ui, repo, file_, rev=rev, **opts) > + transformmap[extensionflag] = wrappedread > + > +def push(orig, ui, repo, dest=None, **opts): > + transformmap[extensionflag] = getfilelogcontent > + orig(ui, repo, dest=dest, **opts) > + transformmap[extensionflag] = wrappedread > + > +def pull(orig, ui, repo, source="default", **opts): > + transformmap[extensionflag] = getfilelogcontent > + orig(ui, repo, source=source, **opts) > + transformmap[extensionflag] = wrappedread > + > +def _peek_isdummy(orig, self, text): > + return 'dummy' in text > + > +def extsetup(ui): > + wrapfunction = extensions.wrapfunction > + wrapcommand = extensions.wrapcommand > + > + wrapfunction(filelog.filelog, 'revision', revision) > + wrapfunction(filelog.filelog, 'addrevision', addrevision) > + wrapfunction(filelog.filelog, 'addgroup', addgroup) > + wrapfunction(filelog.filelog, '_peek_isdummy', _peek_isdummy) > + > + wrapcommand(commands.table, 'debugdata', debugdata) > + wrapcommand(commands.table, 'push', push) > + wrapcommand(commands.table, 'pull', pull) > diff --git a/mercurial/revlog.py b/mercurial/revlog.py > --- a/mercurial/revlog.py > +++ b/mercurial/revlog.py > @@ -55,8 +55,9 @@ > # revlog index flags > REVIDX_ISCENSORED = (1 << 15) # revision has censor metadata, must be verified > REVIDX_ISLARGEFILE = (1 << 14) > +REVIDX_ISDUMMY = (1 << 13) > REVIDX_DEFAULT_FLAGS = 0 > -REVIDX_KNOWN_FLAGS = REVIDX_ISCENSORED | REVIDX_ISLARGEFILE > +REVIDX_KNOWN_FLAGS = REVIDX_ISCENSORED | REVIDX_ISLARGEFILE | REVIDX_ISDUMMY > > # max size of revlog with inline data > _maxinline = 131072 > @@ -97,6 +98,7 @@ > self.flagsbypriority = [ > REVIDX_ISCENSORED, > REVIDX_ISLARGEFILE, > + REVIDX_ISDUMMY, > ] > self.transformmap = {} > self.revlogobject = revlogobject > @@ -1775,6 +1777,9 @@ > def islargefile(self, rev): > return False > > + def _peek_isdummy(self, text): > + return False > + > def _peek_iscensored(self, baserev, delta, flush): > """Quickly check if a delta produces a censored revision.""" > return False > diff --git a/tests/test-lfs.t b/tests/test-lfs.t > --- a/tests/test-lfs.t > +++ b/tests/test-lfs.t > @@ -19,6 +19,7 @@ > $ cat >> .hg/hgrc <<EOF > > [extensions] > > lfs=$TESTDIR/../hgext/lfs/ > + > dummy= > > [lfs] > > threshold=1000B > > blobstore=cache/localblobstore > @@ -49,19 +50,43 @@ > version https://git-lfs.github.com/spec/v1 > oid sha256:1228f8759b018cca5b58d3e5d1740d0b827f06cecf8868fd17f35a87ef8aacf6 > size 1501 > - > -# Check the contents of the file are fetched from the blobstore when requested > - $ hg cat -r . largefile > + $ hg cat --traceback -r . largefile > AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA > > -# Push the blobs to the server > - $ hg push > +# Commit a dummy file (will take the dummy flag) > + $ echo 'dummy' > dummyfile > + $ hg commit -Aqm 'add dummy file' > + > +# Check the dummy extension adds metadata on write > + $ hg debugdata dummyfile 0 > + DUMMY:dummy > + > +# Check the extension removes the metadata on read > + $ hg cat -r . dummyfile > + dummy > + > +# Commit a lfs + dummy triggering file > + $ echo dummyAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA > dummylargefile > + $ hg commit -Aqm 'add dummy large file' > + > +# Check the filelog contains metadata (as dummy has priority on lfs) > + $ hg debugdata dummylargefile 0 > + version https://git-lfs.github.com/spec/v1 > + oid sha256:22a3bdbccf152a786e35ca856dfef423c022968fc42f80f1c2eff8e8b116c37d > + size 1512 > + > +# Check the file contents are restored on read > + $ hg cat -r . dummylargefile > + dummyAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA > + > +# Push changes to the server > + $ hg push --traceback > pushing to $TESTTMP/server (glob) > searching for changes > adding changesets > adding manifests > adding file changes > - added 2 changesets with 2 changes to 2 files > + added 4 changesets with 4 changes to 4 files > > # Initialize new client (not cloning) and setup extension > $ cd ../ > @@ -76,6 +101,7 @@ > > default = $TESTTMP/server > > [extensions] > > lfs=$TESTDIR/../hgext/lfs/ > + > dummy= > > [lfs] > > threshold=1000B > > blobstore=cache/localblobstore > @@ -88,7 +114,7 @@ > adding changesets > adding manifests > adding file changes > - added 2 changesets with 2 changes to 2 files > + added 4 changesets with 4 changes to 4 files > (run 'hg update' to get a working copy) > > # Check the blobstore is not yet populated > @@ -97,7 +123,7 @@ > > # Update to the last revision containing the large file > $ hg update > - 2 files updated, 0 files merged, 0 files removed, 0 files unresolved > + 4 files updated, 0 files merged, 0 files removed, 0 files unresolved > > # Check the filelog contents actually contain metadata > $ hg debugdata largefile 0 > @@ -110,6 +136,8 @@ > .hg/cache/localblobstore > .hg/cache/localblobstore/12 > .hg/cache/localblobstore/12/28f8759b018cca5b58d3e5d1740d0b827f06cecf8868fd17f35a87ef8aacf6 > + .hg/cache/localblobstore/22 > + .hg/cache/localblobstore/22/a3bdbccf152a786e35ca856dfef423c022968fc42f80f1c2eff8e8b116c37d > > # Check the contents of the file are fetched from blobstore when requested > $ hg cat -r . largefile > _______________________________________________ > Mercurial-devel mailing list > Mercurial-devel@mercurial-scm.org > https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
On 11/9/16, 5:17 PM, "Augie Fackler" <raf@durin42.com> wrote: On Thu, Oct 27, 2016 at 04:04:04PM +0100, Remi Chaintron wrote: > # HG changeset patch > # User Remi Chaintron <remi@fb.com> > # Date 1477579974 -3600 > # Thu Oct 27 15:52:54 2016 +0100 > # Branch stable > # Node ID c7dc98eb24cd40e46e73dea275b4c5b245155efb > # Parent 202b2a6872d3b3ffb1f373910c4eadffda8f727a > [RFC] extension: `dummy` and composition with `lfs` > > This is a proof of concept for the composition of non-reflexive operations on > filelogs using extensions relying on the flagprocessor design. Could this be tested using censor instead? I currently have a prototype to move various bits and pieces from censor related core code into the extension, but given the extensive rework and redesign involved, I found it more applicable to provide an easier proof of concept instead. I’d love to get a proposal up for review in regards to moving censor to the extension, but I’m not positive I will have the time to get everything in order to make it happen before the end of the year. > > diff --git a/hgext/dummy.py b/hgext/dummy.py > new file mode 100644 > --- /dev/null > +++ b/hgext/dummy.py > @@ -0,0 +1,83 @@ > +# coding=UTF-8 > + > +from __future__ import absolute_import > + > +from mercurial import ( > + cmdutil, > + commands, > + extensions, > + filelog, > + revlog, > +) > + > +def wrappedread(self, text): > + return text[6:], True > + > +def getfilelogcontent(self, text): > + return text, False > + > +extensionflag = revlog.REVIDX_ISDUMMY > +transformmap = { > + extensionflag: wrappedread > +} > + > +def revision(orig, self, nodeorrev, _df=None): > + self.flagprocessor.register(transformmap) > + try: > + return orig(self, nodeorrev, _df=_df) > + finally: > + self.flagprocessor.unregister(transformmap) > + > + > +def addrevision(orig, self, text, transaction, link, p1, p2, cachedelta=None, > + node=None, flags=revlog.REVLOG_DEFAULT_FLAGS): > + self.flagprocessor.register(transformmap) > + try: > + if self._peek_isdummy(text): > + if node is None: > + node = revlog.hash(text, p1, p2) > + text = 'DUMMY:%s' % (text) > + flags |= extensionflag > + return orig(self, text, transaction, link, p1, p2, cachedelta=cachedelta, > + node=node, flags=flags) > + finally: > + self.flagprocessor.unregister(transformmap) > + > +def addgroup(orig, self, cg, linkmapper, transaction, addrevisioncb=None): > + self.flagprocessor.register(transformmap) > + try: > + return orig(self, cg, linkmapper, transaction, > + addrevisioncb=addrevisioncb) > + finally: > + self.flagprocessor.unregister(transformmap) > + > +def debugdata(orig, ui, repo, file_, rev=None, **opts): > + transformmap[extensionflag] = getfilelogcontent > + orig(ui, repo, file_, rev=rev, **opts) > + transformmap[extensionflag] = wrappedread > + > +def push(orig, ui, repo, dest=None, **opts): > + transformmap[extensionflag] = getfilelogcontent > + orig(ui, repo, dest=dest, **opts) > + transformmap[extensionflag] = wrappedread > + > +def pull(orig, ui, repo, source="default", **opts): > + transformmap[extensionflag] = getfilelogcontent > + orig(ui, repo, source=source, **opts) > + transformmap[extensionflag] = wrappedread > + > +def _peek_isdummy(orig, self, text): > + return 'dummy' in text > + > +def extsetup(ui): > + wrapfunction = extensions.wrapfunction > + wrapcommand = extensions.wrapcommand > + > + wrapfunction(filelog.filelog, 'revision', revision) > + wrapfunction(filelog.filelog, 'addrevision', addrevision) > + wrapfunction(filelog.filelog, 'addgroup', addgroup) > + wrapfunction(filelog.filelog, '_peek_isdummy', _peek_isdummy) > + > + wrapcommand(commands.table, 'debugdata', debugdata) > + wrapcommand(commands.table, 'push', push) > + wrapcommand(commands.table, 'pull', pull) > diff --git a/mercurial/revlog.py b/mercurial/revlog.py > --- a/mercurial/revlog.py > +++ b/mercurial/revlog.py > @@ -55,8 +55,9 @@ > # revlog index flags > REVIDX_ISCENSORED = (1 << 15) # revision has censor metadata, must be verified > REVIDX_ISLARGEFILE = (1 << 14) > +REVIDX_ISDUMMY = (1 << 13) > REVIDX_DEFAULT_FLAGS = 0 > -REVIDX_KNOWN_FLAGS = REVIDX_ISCENSORED | REVIDX_ISLARGEFILE > +REVIDX_KNOWN_FLAGS = REVIDX_ISCENSORED | REVIDX_ISLARGEFILE | REVIDX_ISDUMMY > > # max size of revlog with inline data > _maxinline = 131072 > @@ -97,6 +98,7 @@ > self.flagsbypriority = [ > REVIDX_ISCENSORED, > REVIDX_ISLARGEFILE, > + REVIDX_ISDUMMY, > ] > self.transformmap = {} > self.revlogobject = revlogobject > @@ -1775,6 +1777,9 @@ > def islargefile(self, rev): > return False > > + def _peek_isdummy(self, text): > + return False > + > def _peek_iscensored(self, baserev, delta, flush): > """Quickly check if a delta produces a censored revision.""" > return False > diff --git a/tests/test-lfs.t b/tests/test-lfs.t > --- a/tests/test-lfs.t > +++ b/tests/test-lfs.t > @@ -19,6 +19,7 @@ > $ cat >> .hg/hgrc <<EOF > > [extensions] > > lfs=$TESTDIR/../hgext/lfs/ > + > dummy= > > [lfs] > > threshold=1000B > > blobstore=cache/localblobstore > @@ -49,19 +50,43 @@ > version https://git-lfs.github.com/spec/v1 > oid sha256:1228f8759b018cca5b58d3e5d1740d0b827f06cecf8868fd17f35a87ef8aacf6 > size 1501 > - > -# Check the contents of the file are fetched from the blobstore when requested > - $ hg cat -r . largefile > + $ hg cat --traceback -r . largefile > AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA > > -# Push the blobs to the server > - $ hg push > +# Commit a dummy file (will take the dummy flag) > + $ echo 'dummy' > dummyfile > + $ hg commit -Aqm 'add dummy file' > + > +# Check the dummy extension adds metadata on write > + $ hg debugdata dummyfile 0 > + DUMMY:dummy > + > +# Check the extension removes the metadata on read > + $ hg cat -r . dummyfile > + dummy > + > +# Commit a lfs + dummy triggering file > + $ echo dummyAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA > dummylargefile > + $ hg commit -Aqm 'add dummy large file' > + > +# Check the filelog contains metadata (as dummy has priority on lfs) > + $ hg debugdata dummylargefile 0 > + version https://git-lfs.github.com/spec/v1 > + oid sha256:22a3bdbccf152a786e35ca856dfef423c022968fc42f80f1c2eff8e8b116c37d > + size 1512 > + > +# Check the file contents are restored on read > + $ hg cat -r . dummylargefile > + dummyAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA > + > +# Push changes to the server > + $ hg push --traceback > pushing to $TESTTMP/server (glob) > searching for changes > adding changesets > adding manifests > adding file changes > - added 2 changesets with 2 changes to 2 files > + added 4 changesets with 4 changes to 4 files > > # Initialize new client (not cloning) and setup extension > $ cd ../ > @@ -76,6 +101,7 @@ > > default = $TESTTMP/server > > [extensions] > > lfs=$TESTDIR/../hgext/lfs/ > + > dummy= > > [lfs] > > threshold=1000B > > blobstore=cache/localblobstore > @@ -88,7 +114,7 @@ > adding changesets > adding manifests > adding file changes > - added 2 changesets with 2 changes to 2 files > + added 4 changesets with 4 changes to 4 files > (run 'hg update' to get a working copy) > > # Check the blobstore is not yet populated > @@ -97,7 +123,7 @@ > > # Update to the last revision containing the large file > $ hg update > - 2 files updated, 0 files merged, 0 files removed, 0 files unresolved > + 4 files updated, 0 files merged, 0 files removed, 0 files unresolved > > # Check the filelog contents actually contain metadata > $ hg debugdata largefile 0 > @@ -110,6 +136,8 @@ > .hg/cache/localblobstore > .hg/cache/localblobstore/12 > .hg/cache/localblobstore/12/28f8759b018cca5b58d3e5d1740d0b827f06cecf8868fd17f35a87ef8aacf6 > + .hg/cache/localblobstore/22 > + .hg/cache/localblobstore/22/a3bdbccf152a786e35ca856dfef423c022968fc42f80f1c2eff8e8b116c37d > > # Check the contents of the file are fetched from blobstore when requested > $ hg cat -r . largefile > _______________________________________________ > Mercurial-devel mailing list > Mercurial-devel@mercurial-scm.org > https://urldefense.proofpoint.com/v2/url?u=https-3A__www.mercurial-2Dscm.org_mailman_listinfo_mercurial-2Ddevel&d=DQIFAg&c=5VD0RTtNlTh3ycd41b3MUw&r=RjAECLzUoKvzn49UTozsUg&m=5RyPgFuzIirEktiCbTiLncwaRvGm6WhEv21cqfaP5-o&s=40rBjU8_W8S68vg_RCGfz4bO3GsV4mSj784C1r4Jk70&e=
> On Nov 16, 2016, at 09:12, Rémi Chaintron <remi@fb.com> wrote: > > On 11/9/16, 5:17 PM, "Augie Fackler" <raf@durin42.com> wrote: > >> On Thu, Oct 27, 2016 at 04:04:04PM +0100, Remi Chaintron wrote: >>> # HG changeset patch >>> # User Remi Chaintron <remi@fb.com> >>> # Date 1477579974 -3600 >>> # Thu Oct 27 15:52:54 2016 +0100 >>> # Branch stable >>> # Node ID c7dc98eb24cd40e46e73dea275b4c5b245155efb >>> # Parent 202b2a6872d3b3ffb1f373910c4eadffda8f727a >>> [RFC] extension: `dummy` and composition with `lfs` >>> >>> This is a proof of concept for the composition of non-reflexive operations on >>> filelogs using extensions relying on the flagprocessor design. >> >> Could this be tested using censor instead? > > I currently have a prototype to move various bits and pieces from censor related core code into the extension, but given the extensive rework and redesign involved, I found it more applicable to provide an easier proof of concept instead. > I’d love to get a proposal up for review in regards to moving censor to the extension, but I’m not positive I will have the time to get everything in order to make it happen before the end of the year. Does that mean that with this series as-is, censor doesn't use the new code paths? Have you explored how much refactoring has to happen in censor to make censor use the new system? I'd rather that the first-party consumer of this infrastructure used it right away, rather than it being a TODO unless it's extremely onerous.
On 11/16/16, 3:44 PM, "Augie Fackler" <raf@durin42.com> wrote: >> On Nov 16, 2016, at 09:12, Rémi Chaintron <remi@fb.com> wrote: >> >> On 11/9/16, 5:17 PM, "Augie Fackler" <raf@durin42.com> wrote: >> >>> On Thu, Oct 27, 2016 at 04:04:04PM +0100, Remi Chaintron wrote: >>>> # HG changeset patch >>>> # User Remi Chaintron <remi@fb.com> >>>> # Date 1477579974 -3600 >>>> # Thu Oct 27 15:52:54 2016 +0100 >>>> # Branch stable >>>> # Node ID c7dc98eb24cd40e46e73dea275b4c5b245155efb >>>> # Parent 202b2a6872d3b3ffb1f373910c4eadffda8f727a >>>> [RFC] extension: `dummy` and composition with `lfs` >>>> >>>> This is a proof of concept for the composition of non-reflexive operations on >>>> filelogs using extensions relying on the flagprocessor design. >>> >>> Could this be tested using censor instead? >> >> I currently have a prototype to move various bits and pieces from censor related core code into the extension, but given the extensive rework and redesign involved, I found it more applicable to provide an easier proof of concept instead. >> I’d love to get a proposal up for review in regards to moving censor to the extension, but I’m not positive I will have the time to get everything in order to make it happen before the end of the year. > > Does that mean that with this series as-is, censor doesn't use the new code paths? Have you explored how much refactoring has to happen in censor to make censor use the new system? > > I'd rather that the first-party consumer of this infrastructure used it right away, rather than it being a TODO unless it's extremely onerous. Precisions following VC discussion with Augie: - Moving censor to use the new flagprocessor design allows for cleaning all censor related filelog code, and much of the revlog censor related code. There are however a number of issues that I didn’t have time to push through on completely cleaning censor code out of core and will take another stab at it when possible. - Censor can be considered a special case of this new design as it doesn’t allow two-way transformations. Once a node has been censored, there’s no going back and reading such a node should fail, irrelevant of the place of censor in the stack of transforms to be applied. - This is a proof a concept for the flagprocessor design handling multiple non-commutative operations on the filelog contents.
Patch
diff --git a/hgext/dummy.py b/hgext/dummy.py new file mode 100644 --- /dev/null +++ b/hgext/dummy.py @@ -0,0 +1,83 @@ +# coding=UTF-8 + +from __future__ import absolute_import + +from mercurial import ( + cmdutil, + commands, + extensions, + filelog, + revlog, +) + +def wrappedread(self, text): + return text[6:], True + +def getfilelogcontent(self, text): + return text, False + +extensionflag = revlog.REVIDX_ISDUMMY +transformmap = { + extensionflag: wrappedread +} + +def revision(orig, self, nodeorrev, _df=None): + self.flagprocessor.register(transformmap) + try: + return orig(self, nodeorrev, _df=_df) + finally: + self.flagprocessor.unregister(transformmap) + + +def addrevision(orig, self, text, transaction, link, p1, p2, cachedelta=None, + node=None, flags=revlog.REVLOG_DEFAULT_FLAGS): + self.flagprocessor.register(transformmap) + try: + if self._peek_isdummy(text): + if node is None: + node = revlog.hash(text, p1, p2) + text = 'DUMMY:%s' % (text) + flags |= extensionflag + return orig(self, text, transaction, link, p1, p2, cachedelta=cachedelta, + node=node, flags=flags) + finally: + self.flagprocessor.unregister(transformmap) + +def addgroup(orig, self, cg, linkmapper, transaction, addrevisioncb=None): + self.flagprocessor.register(transformmap) + try: + return orig(self, cg, linkmapper, transaction, + addrevisioncb=addrevisioncb) + finally: + self.flagprocessor.unregister(transformmap) + +def debugdata(orig, ui, repo, file_, rev=None, **opts): + transformmap[extensionflag] = getfilelogcontent + orig(ui, repo, file_, rev=rev, **opts) + transformmap[extensionflag] = wrappedread + +def push(orig, ui, repo, dest=None, **opts): + transformmap[extensionflag] = getfilelogcontent + orig(ui, repo, dest=dest, **opts) + transformmap[extensionflag] = wrappedread + +def pull(orig, ui, repo, source="default", **opts): + transformmap[extensionflag] = getfilelogcontent + orig(ui, repo, source=source, **opts) + transformmap[extensionflag] = wrappedread + +def _peek_isdummy(orig, self, text): + return 'dummy' in text + +def extsetup(ui): + wrapfunction = extensions.wrapfunction + wrapcommand = extensions.wrapcommand + + wrapfunction(filelog.filelog, 'revision', revision) + wrapfunction(filelog.filelog, 'addrevision', addrevision) + wrapfunction(filelog.filelog, 'addgroup', addgroup) + wrapfunction(filelog.filelog, '_peek_isdummy', _peek_isdummy) + + wrapcommand(commands.table, 'debugdata', debugdata) + wrapcommand(commands.table, 'push', push) + wrapcommand(commands.table, 'pull', pull) diff --git a/mercurial/revlog.py b/mercurial/revlog.py --- a/mercurial/revlog.py +++ b/mercurial/revlog.py @@ -55,8 +55,9 @@ # revlog index flags REVIDX_ISCENSORED = (1 << 15) # revision has censor metadata, must be verified REVIDX_ISLARGEFILE = (1 << 14) +REVIDX_ISDUMMY = (1 << 13) REVIDX_DEFAULT_FLAGS = 0 -REVIDX_KNOWN_FLAGS = REVIDX_ISCENSORED | REVIDX_ISLARGEFILE +REVIDX_KNOWN_FLAGS = REVIDX_ISCENSORED | REVIDX_ISLARGEFILE | REVIDX_ISDUMMY # max size of revlog with inline data _maxinline = 131072 @@ -97,6 +98,7 @@ self.flagsbypriority = [ REVIDX_ISCENSORED, REVIDX_ISLARGEFILE, + REVIDX_ISDUMMY, ] self.transformmap = {} self.revlogobject = revlogobject @@ -1775,6 +1777,9 @@ def islargefile(self, rev): return False + def _peek_isdummy(self, text): + return False + def _peek_iscensored(self, baserev, delta, flush): """Quickly check if a delta produces a censored revision.""" return False diff --git a/tests/test-lfs.t b/tests/test-lfs.t --- a/tests/test-lfs.t +++ b/tests/test-lfs.t @@ -19,6 +19,7 @@ $ cat >> .hg/hgrc <<EOF > [extensions] > lfs=$TESTDIR/../hgext/lfs/ + > dummy= > [lfs] > threshold=1000B > blobstore=cache/localblobstore @@ -49,19 +50,43 @@ version https://git-lfs.github.com/spec/v1 oid sha256:1228f8759b018cca5b58d3e5d1740d0b827f06cecf8868fd17f35a87ef8aacf6 size 1501 - -# Check the contents of the file are fetched from the blobstore when requested - $ hg cat -r . largefile + $ hg cat --traceback -r . largefile AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -# Push the blobs to the server - $ hg push +# Commit a dummy file (will take the dummy flag) + $ echo 'dummy' > dummyfile + $ hg commit -Aqm 'add dummy file' + +# Check the dummy extension adds metadata on write + $ hg debugdata dummyfile 0 + DUMMY:dummy + +# Check the extension removes the metadata on read + $ hg cat -r . dummyfile + dummy + +# Commit a lfs + dummy triggering file + $ echo dummyAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA > dummylargefile + $ hg commit -Aqm 'add dummy large file' + +# Check the filelog contains metadata (as dummy has priority on lfs) + $ hg debugdata dummylargefile 0 + version https://git-lfs.github.com/spec/v1 + oid sha256:22a3bdbccf152a786e35ca856dfef423c022968fc42f80f1c2eff8e8b116c37d + size 1512 + +# Check the file contents are restored on read + $ hg cat -r . dummylargefile + dummyAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + +# Push changes to the server + $ hg push --traceback pushing to $TESTTMP/server (glob) searching for changes adding changesets adding manifests adding file changes - added 2 changesets with 2 changes to 2 files + added 4 changesets with 4 changes to 4 files # Initialize new client (not cloning) and setup extension $ cd ../ @@ -76,6 +101,7 @@ > default = $TESTTMP/server > [extensions] > lfs=$TESTDIR/../hgext/lfs/ + > dummy= > [lfs] > threshold=1000B > blobstore=cache/localblobstore @@ -88,7 +114,7 @@ adding changesets adding manifests adding file changes - added 2 changesets with 2 changes to 2 files + added 4 changesets with 4 changes to 4 files (run 'hg update' to get a working copy) # Check the blobstore is not yet populated @@ -97,7 +123,7 @@ # Update to the last revision containing the large file $ hg update - 2 files updated, 0 files merged, 0 files removed, 0 files unresolved + 4 files updated, 0 files merged, 0 files removed, 0 files unresolved # Check the filelog contents actually contain metadata $ hg debugdata largefile 0 @@ -110,6 +136,8 @@ .hg/cache/localblobstore .hg/cache/localblobstore/12 .hg/cache/localblobstore/12/28f8759b018cca5b58d3e5d1740d0b827f06cecf8868fd17f35a87ef8aacf6 + .hg/cache/localblobstore/22 + .hg/cache/localblobstore/22/a3bdbccf152a786e35ca856dfef423c022968fc42f80f1c2eff8e8b116c37d # Check the contents of the file are fetched from blobstore when requested $ hg cat -r . largefile