diff --git a/mercurial/configitems.py b/mercurial/configitems.py --- a/mercurial/configitems.py +++ b/mercurial/configitems.py @@ -532,6 +532,13 @@ coreconfigitem('experimental', 'evolutio coreconfigitem('experimental', 'evolution.track-operation', default=True, ) +# repo-level config to exclude a revset visibility +# +# The target use case is to use `share` to expose different subset of the same +# repository, especially server side. See also `server.view`. +coreconfigitem('experimental', 'extra-filter-revs', + default=None, +) coreconfigitem('experimental', 'maxdeltachainspan', default=-1, ) diff --git a/mercurial/localrepo.py b/mercurial/localrepo.py --- a/mercurial/localrepo.py +++ b/mercurial/localrepo.py @@ -1050,6 +1050,8 @@ class localrepository(object): # Signature to cached matcher instance. self._sparsematchercache = {} + self._extrafilterid = repoview.extrafilter(ui) + def _getvfsward(self, origfunc): """build a ward for self.vfs""" rref = weakref.ref(self) @@ -1197,6 +1199,9 @@ class localrepository(object): In other word, there is always only one level of `repoview` "filtering". """ + if self._extrafilterid is not None and '%' not in name: + name = name + '%' + self._extrafilterid + cls = repoview.newtype(self.unfiltered().__class__) return cls(self, name, visibilityexceptions) diff --git a/mercurial/repoview.py b/mercurial/repoview.py --- a/mercurial/repoview.py +++ b/mercurial/repoview.py @@ -17,6 +17,10 @@ from . import ( phases, pycompat, tags as tagsmod, + util, +) +from .utils import ( + repoviewutil, ) def hideablerevs(repo): @@ -154,6 +158,35 @@ filtertable = {'visible': computehidden, 'immutable': computemutable, 'base': computeimpactable} +_basefiltername = list(filtertable) + +def extrafilter(ui): + """initialize extra filter and return its id + + If extra filtering is configured, we make sure the associated filtered view + are declared and return the associated id. + """ + frevs = ui.config('experimental', 'extra-filter-revs') + if frevs is None: + return None + + fid = pycompat.sysbytes(util.DIGESTS['sha1'](frevs).hexdigest())[:12] + + combine = lambda fname: fname + '%' + fid + + subsettable = repoviewutil.subsettable + + if combine('base') not in filtertable: + for name in _basefiltername: + def extrafilteredrevs(repo, *args, **kwargs): + baserevs = filtertable[name](repo, *args, **kwargs) + extrarevs = frozenset(repo.revs(frevs)) + return baserevs | extrarevs + filtertable[combine(name)] = extrafilteredrevs + if name in subsettable: + subsettable[combine(name)] = combine(subsettable[name]) + return fid + def filterrevs(repo, filtername, visibilityexceptions=None): """returns set of filtered revision for this filter name diff --git a/mercurial/statichttprepo.py b/mercurial/statichttprepo.py --- a/mercurial/statichttprepo.py +++ b/mercurial/statichttprepo.py @@ -155,6 +155,7 @@ class statichttprepository(localrepo.loc self.names = namespaces.namespaces() self.filtername = None + self._extrafilterid = None try: requirements = set(self.vfs.read(b'requires').splitlines()) diff --git a/tests/test-server-view.t b/tests/test-server-view.t --- a/tests/test-server-view.t +++ b/tests/test-server-view.t @@ -34,5 +34,29 @@ date: Thu Jan 01 00:00:00 1970 +0000 summary: r0 + +Check same result using `experimental.extra-filter-revs` + + $ hg -R test --config experimental.extra-filter-revs='not public()' serve -p $HGPORT1 -d --pid-file=hg2.pid -E errors.log + $ cat hg2.pid >> $DAEMON_PIDS + $ hg -R test2 incoming http://foo:xyzzy@localhost:$HGPORT1/ + comparing with http://foo:***@localhost:$HGPORT1/ + changeset: 0:1ea73414a91b + tag: tip + user: debugbuilddag + date: Thu Jan 01 00:00:00 1970 +0000 + summary: r0 + + $ hg -R test --config experimental.extra-filter-revs='not public()' debugupdatecache + $ ls -1 test/.hg/cache/ + branch2-base%89c45d2fa07e + branch2-served + rbc-names-v1 + rbc-revs-v1 + tags2 + tags2-served%89c45d2fa07e + +cleanup + $ cat errors.log $ killdaemons.py