# HG changeset patch # User Pierre-Yves David # Date 1508899531 -7200 # Node ID 79a926b557f10d5c23c5bcff132889054b409bd2 # Parent 0ed75e700ad80d88f4682a7ee7e0289fe272ba67 compat: drop support for older exchange protocol Their have been better alternative for years. In addition they have been officially deprecated for quite some time. So we official stop support them to ease the maintainance. diff -r 0ed75e700ad8 -r 79a926b557f1 hgext3rd/evolve/__init__.py --- a/hgext3rd/evolve/__init__.py Tue Oct 24 14:30:48 2017 +0200 +++ b/hgext3rd/evolve/__init__.py Wed Oct 25 04:45:31 2017 +0200 @@ -420,6 +420,8 @@ if not evolveopts: evolveopts = ['all'] ui.setconfig('experimental', 'evolution', evolveopts, 'evolve') + if obsolete.isenabled(repo, 'exchange'): + repo.ui.setconfig('server', 'bundle1', False) @eh.uisetup def _configurecmdoptions(ui): diff -r 0ed75e700ad8 -r 79a926b557f1 hgext3rd/evolve/obsexchange.py --- a/hgext3rd/evolve/obsexchange.py Tue Oct 24 14:30:48 2017 +0200 +++ b/hgext3rd/evolve/obsexchange.py Wed Oct 25 04:45:31 2017 +0200 @@ -14,24 +14,16 @@ import io StringIO = io.StringIO -import errno -import socket - from mercurial import ( bundle2, - error, exchange, extensions, - httppeer, - localrepo, lock as lockmod, node, obsolete, util, wireproto, ) -from mercurial.hgweb import hgweb_mod -from mercurial.i18n import _ from . import ( exthelper, @@ -199,244 +191,3 @@ finaldata.write(obsdata) finaldata.seek(0) return wireproto.streamres(reader=finaldata, v1compressible=True) - -############################################### -### Support for old legacy exchange methods ### -############################################### - -class pushobsmarkerStringIO(StringIO): - """hacky string io for progress""" - - @util.propertycache - def length(self): - return len(self.getvalue()) - - def read(self, size=None): - obsexcprg(self.ui, self.tell(), unit=_("bytes"), total=self.length) - return StringIO.read(self, size) - - def __iter__(self): - d = self.read(4096) - while d: - yield d - d = self.read(4096) - -# compat-code: _pushobsolete -# -# the _pushobsolete function is a core function used to exchange -# obsmarker with repository that does not support bundle2 - -@eh.wrapfunction(exchange, '_pushobsolete') -def _pushobsolete(orig, pushop): - """utility function to push obsolete markers to a remote""" - if not obsolete.isenabled(pushop.repo, obsolete.exchangeopt): - return - if 'obsmarkers' in pushop.stepsdone: - return - pushop.stepsdone.add('obsmarkers') - if pushop.cgresult == 0: - return - pushop.ui.debug('try to push obsolete markers to remote\n') - repo = pushop.repo - remote = pushop.remote - if (repo.obsstore and 'obsolete' in remote.listkeys('namespaces')): - markers = pushop.outobsmarkers - if not markers: - obsexcmsg(repo.ui, "no marker to push\n") - elif remote.capable('_evoext_pushobsmarkers_0'): - msg = ('the remote repository use years old versions of Mercurial' - ' and evolve\npushing obsmarker using legacy method\n') - repo.ui.warn(msg) - repo.ui.warn('(please upgrade your server)\n') - obsdata = pushobsmarkerStringIO() - for chunk in obsolete.encodemarkers(markers, True): - obsdata.write(chunk) - obsdata.seek(0) - obsdata.ui = repo.ui - obsexcmsg(repo.ui, "pushing %i obsolescence markers (%i bytes)\n" - % (len(markers), len(obsdata.getvalue())), - True) - remote.evoext_pushobsmarkers_0(obsdata) - obsexcprg(repo.ui, None) - - else: - # XXX core could be able do the same things but without the debug - # and progress output. - msg = ('the remote repository usea years old version of Mercurial' - ' and not evolve extension\n') - repo.ui.warn(msg) - msg = 'pushing obsmarker using and extremely slow legacy method\n' - repo.ui.warn(msg) - repo.ui.warn('(please upgrade your server and enable evolve.serveronly on it)\n') - rslts = [] - remotedata = obsolete._pushkeyescape(markers).items() - totalbytes = sum(len(d) for k, d in remotedata) - sentbytes = 0 - obsexcmsg(repo.ui, "pushing %i obsolescence markers in %i " - "pushkey payload (%i bytes)\n" - % (len(markers), len(remotedata), totalbytes), - True) - for key, data in remotedata: - obsexcprg(repo.ui, sentbytes, item=key, unit=_("bytes"), - total=totalbytes) - rslts.append(remote.pushkey('obsolete', key, '', data)) - sentbytes += len(data) - obsexcprg(repo.ui, sentbytes, item=key, unit=_("bytes"), - total=totalbytes) - obsexcprg(repo.ui, None) - if [r for r in rslts if not r]: - msg = _('failed to push some obsolete markers!\n') - repo.ui.warn(msg) - obsexcmsg(repo.ui, "DONE\n") - -# Supporting legacy way to push obsmarker so that old client can still push -# them somewhat efficiently - -@eh.addattr(wireproto.wirepeer, 'evoext_pushobsmarkers_0') -def client_pushobsmarkers(self, obsfile): - """wireprotocol peer method""" - self.requirecap('_evoext_pushobsmarkers_0', - _('push obsolete markers faster')) - ret, output = self._callpush('evoext_pushobsmarkers_0', obsfile) - for l in output.splitlines(True): - self.ui.status(_('remote: '), l) - return ret - -@eh.addattr(httppeer.httppeer, 'evoext_pushobsmarkers_0') -def httpclient_pushobsmarkers(self, obsfile): - """httpprotocol peer method - (Cannot simply use _callpush as http is doing some special handling)""" - self.requirecap('_evoext_pushobsmarkers_0', - _('push obsolete markers faster')) - try: - r = self._call('evoext_pushobsmarkers_0', data=obsfile) - vals = r.split('\n', 1) - if len(vals) < 2: - raise error.ResponseError(_("unexpected response:"), r) - - for l in vals[1].splitlines(True): - if l.strip(): - self.ui.status(_('remote: '), l) - return vals[0] - except socket.error as err: - if err.args[0] in (errno.ECONNRESET, errno.EPIPE): - raise error.Abort(_('push failed: %s') % err.args[1]) - raise error.Abort(err.args[1]) - -@eh.wrapfunction(localrepo.localrepository, '_restrictcapabilities') -def local_pushobsmarker_capabilities(orig, repo, caps): - caps = orig(repo, caps) - caps.add('_evoext_pushobsmarkers_0') - return caps - -@eh.addattr(localrepo.localpeer, 'evoext_pushobsmarkers_0') -def local_pushobsmarkers(peer, obsfile): - data = obsfile.read() - _pushobsmarkers(peer._repo, data) - -# compat-code: _pullobsolete -# -# the _pullobsolete function is a core function used to exchange -# obsmarker with repository that does not support bundle2 - -@eh.wrapfunction(exchange, '_pullobsolete') -def _pullobsolete(orig, pullop): - if not obsolete.isenabled(pullop.repo, obsolete.exchangeopt): - return None - if 'obsmarkers' in pullop.stepsdone: - return None - wirepull = pullop.remote.capable('_evoext_pullobsmarkers_0') - if 'obsolete' not in pullop.remote.listkeys('namespaces'): - return None # remote opted out of obsolescence marker exchange - if not wirepull: - return orig(pullop) - tr = None - ui = pullop.repo.ui - boundaries = obsdiscovery.buildpullobsmarkersboundaries(pullop, bundle2=False) - if 'missing' in boundaries and not boundaries['missing']: - obsexcmsg(ui, "nothing to pull\n") - return None - elif not set(boundaries['heads']) - set(boundaries['common']): - obsexcmsg(ui, "nothing to pull\n") - return None - - obsexcmsg(ui, "pull obsolescence markers\n", True) - new = 0 - - msg = ('the remote repository use years old versions of Mercurial and evolve\n' - 'pulling obsmarker using legacy method\n') - ui.warn(msg) - ui.warn('(please upgrade your server)\n') - - obsdata = pullop.remote.evoext_pullobsmarkers_0(**boundaries) - obsdata = obsdata.read() - if len(obsdata) > 5: - msg = "merging obsolescence markers (%i bytes)\n" % len(obsdata) - obsexcmsg(ui, msg) - tr = pullop.gettransaction() - old = len(pullop.repo.obsstore._all) - pullop.repo.obsstore.mergemarkers(tr, obsdata) - new = len(pullop.repo.obsstore._all) - old - obsexcmsg(ui, "%i obsolescence markers added\n" % new, True) - else: - obsexcmsg(ui, "no unknown remote markers\n") - obsexcmsg(ui, "DONE\n") - if new: - pullop.repo.invalidatevolatilesets() - return tr - -@eh.addattr(wireproto.wirepeer, 'evoext_pullobsmarkers_0') -def client_pullobsmarkers(self, heads=None, common=None): - self.requirecap('_evoext_pullobsmarkers_0', _('look up remote obsmarkers')) - opts = {} - if heads is not None: - opts['heads'] = wireproto.encodelist(heads) - if common is not None: - opts['common'] = wireproto.encodelist(common) - f = self._callcompressable("evoext_pullobsmarkers_0", **opts) - length = int(f.read(20)) - chunk = 4096 - current = 0 - data = StringIO() - ui = self.ui - obsexcprg(ui, current, unit=_("bytes"), total=length) - while current < length: - readsize = min(length - current, chunk) - data.write(f.read(readsize)) - current += readsize - obsexcprg(ui, current, unit=_("bytes"), total=length) - obsexcprg(ui, None) - data.seek(0) - return data - -@eh.addattr(localrepo.localpeer, 'evoext_pullobsmarkers_0') -def local_pullobsmarkers(self, heads=None, common=None): - return _getobsmarkersstream(self._repo, heads=heads, - common=common) - -def _legacypush_capabilities(orig, repo, proto): - """wrapper to advertise new capability""" - caps = orig(repo, proto) - if obsolete.isenabled(repo, obsolete.exchangeopt): - caps = caps.split() - caps.append('_evoext_pushobsmarkers_0') - caps.append('_evoext_pullobsmarkers_0') - caps.sort() - caps = ' '.join(caps) - return caps - -@eh.extsetup -def extsetup(ui): - # legacy standalone method - hgweb_mod.perms['evoext_pushobsmarkers_0'] = 'push' - hgweb_mod.perms['evoext_pullobsmarkers_0'] = 'pull' - wireproto.commands['evoext_pushobsmarkers_0'] = (srv_pushobsmarkers, '') - wireproto.commands['evoext_pullobsmarkers_0'] = (srv_pullobsmarkers, '*') - - extensions.wrapfunction(wireproto, 'capabilities', _legacypush_capabilities) - # wrap command content - oldcap, args = wireproto.commands['capabilities'] - - def newcap(repo, proto): - return _legacypush_capabilities(oldcap, repo, proto) - wireproto.commands['capabilities'] = (newcap, args) diff -r 0ed75e700ad8 -r 79a926b557f1 hgext3rd/evolve/serveronly.py --- a/hgext3rd/evolve/serveronly.py Tue Oct 24 14:30:48 2017 +0200 +++ b/hgext3rd/evolve/serveronly.py Wed Oct 25 04:45:31 2017 +0200 @@ -13,6 +13,8 @@ import sys import os +from mercurial import obsolete + try: from . import ( compat, @@ -55,3 +57,5 @@ if not evolveopts: evolveopts = 'all' ui.setconfig('experimental', 'evolution', evolveopts) + if obsolete.isenabled(repo, 'exchange'): + repo.ui.setconfig('server', 'bundle1', False) diff -r 0ed75e700ad8 -r 79a926b557f1 tests/test-discovery-obshashrange.t --- a/tests/test-discovery-obshashrange.t Tue Oct 24 14:30:48 2017 +0200 +++ b/tests/test-discovery-obshashrange.t Wed Oct 25 04:45:31 2017 +0200 @@ -183,8 +183,8 @@ running python "*/dummyssh" 'user@dummy' 'hg -R server serve --stdio' (glob) sending hello command sending between command - remote: 533 - remote: capabilities: _evoext_getbundle_obscommon _evoext_obshash_0 _evoext_obshash_1 _evoext_obshashrange_v0 _evoext_pullobsmarkers_0 _evoext_pushobsmarkers_0 batch branchmap bundle2=HG20%0Achangegroup%3D01%2C02%0Adigests%3Dmd5%2Csha1%2Csha512%0Aerror%3Dabort%2Cunsupportedcontent%2Cpushraced%2Cpushkey%0Ahgtagsfnodes%0Alistkeys%0Aobsmarkers%3DV0%2CV1%0Aphases%3Dheads%0Apushkey%0Aremote-changegroup%3Dhttp%2Chttps changegroupsubset getbundle known lookup pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash + remote: 483 + remote: capabilities: _evoext_getbundle_obscommon _evoext_obshash_0 _evoext_obshash_1 _evoext_obshashrange_v0 batch * (glob) remote: 1 preparing listkeys for "phases" sending listkeys command diff -r 0ed75e700ad8 -r 79a926b557f1 tests/test-evolve-serveronly-bundle2.t --- a/tests/test-evolve-serveronly-bundle2.t Tue Oct 24 14:30:48 2017 +0200 +++ b/tests/test-evolve-serveronly-bundle2.t Wed Oct 25 04:45:31 2017 +0200 @@ -86,9 +86,9 @@ =================== $ curl -s http://localhost:$HGPORT/?cmd=hello - capabilities: _evoext_getbundle_obscommon _evoext_obshash_0 _evoext_obshash_1 _evoext_pullobsmarkers_0 _evoext_pushobsmarkers_0 batch * (glob) + capabilities: _evoext_getbundle_obscommon _evoext_obshash_0 _evoext_obshash_1 batch * (glob) $ curl -s http://localhost:$HGPORT/?cmd=capabilities - _evoext_getbundle_obscommon _evoext_obshash_0 _evoext_obshash_1 _evoext_pullobsmarkers_0 _evoext_pushobsmarkers_0 batch * (no-eol) (glob) + _evoext_getbundle_obscommon _evoext_obshash_0 _evoext_obshash_1 batch * (no-eol) (glob) $ curl -s "http://localhost:$HGPORT/?cmd=listkeys&namespace=namespaces" | sort bookmarks @@ -151,9 +151,9 @@ obsolete phases $ curl -s http://localhost:$HGPORT/?cmd=hello - capabilities: _evoext_getbundle_obscommon _evoext_obshash_0 _evoext_obshash_1 _evoext_pullobsmarkers_0 _evoext_pushobsmarkers_0 batch * (glob) + capabilities: _evoext_getbundle_obscommon _evoext_obshash_0 _evoext_obshash_1 batch * (glob) $ curl -s http://localhost:$HGPORT/?cmd=capabilities - _evoext_getbundle_obscommon _evoext_obshash_0 _evoext_obshash_1 _evoext_pullobsmarkers_0 _evoext_pushobsmarkers_0 batch * (no-eol) (glob) + _evoext_getbundle_obscommon _evoext_obshash_0 _evoext_obshash_1 batch * (no-eol) (glob) $ echo '[experimental]' >> server/.hg/hgrc $ echo 'evolution=!' >> server/.hg/hgrc @@ -178,9 +178,9 @@ phases $ curl -s http://localhost:$HGPORT/?cmd=hello - capabilities: _evoext_getbundle_obscommon _evoext_obshash_0 _evoext_obshash_1 _evoext_pullobsmarkers_0 _evoext_pushobsmarkers_0 batch * (glob) + capabilities: _evoext_getbundle_obscommon _evoext_obshash_0 _evoext_obshash_1 batch * (glob) $ curl -s http://localhost:$HGPORT/?cmd=capabilities - _evoext_getbundle_obscommon _evoext_obshash_0 _evoext_obshash_1 _evoext_pullobsmarkers_0 _evoext_pushobsmarkers_0 batch * (no-eol) (glob) + _evoext_getbundle_obscommon _evoext_obshash_0 _evoext_obshash_1 batch * (no-eol) (glob) Test obshashrange discover =========================================== diff -r 0ed75e700ad8 -r 79a926b557f1 tests/test-evolve-serveronly-legacy.t --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tests/test-evolve-serveronly-legacy.t Wed Oct 25 04:45:31 2017 +0200 @@ -0,0 +1,63 @@ + + $ . ${TESTDIR}/testlib/pythonpath.sh + + $ cat >> $HGRCPATH < [defaults] + > amend=-d "0 0" + > [web] + > push_ssl = false + > allow_push = * + > [phases] + > publish = False + > [experimental] + > bundle2-exp=False # < Mercurial-4.0 + > [devel] + > legacy.exchange=bundle1 + > [extensions] + > EOF + + $ mkcommit() { + > echo "$1" > "$1" + > hg add "$1" + > hg ci -m "add $1" + > } + + + $ hg init server + +Try the multiple ways to setup the extension + + $ hg -R server log --config 'extensions.evolve.serveronly=' + $ hg -R server log --config "extensions.evolve.serveronly=${SRCDIR}/hgext3rd/evolve/serveronly.py" + $ PYTHONPATH=$HGTEST_ORIG_PYTHONPATH hg -R server log --config "extensions.evolve.serveronly=${SRCDIR}/hgext3rd/evolve/serveronly.py" + +setup repo + + $ echo "[extensions]" >> ./server/.hg/hgrc + $ echo "evolve.serveronly=" >> ./server/.hg/hgrc + $ hg serve -R server -n test -p $HGPORT -d --pid-file=hg.pid -A access.log -E errors.log --traceback + $ cat hg.pid >> $DAEMON_PIDS + + $ hg clone http://localhost:$HGPORT/ client + no changes found + updating to branch default + 0 files updated, 0 files merged, 0 files removed, 0 files unresolved + $ cat ./errors.log + $ echo "[extensions]" >> ./client/.hg/hgrc + $ echo "evolve=" >> ./client/.hg/hgrc + $ cp -r client other + +Smoke testing +=============== + + $ cd client + $ mkcommit 0 + $ mkcommit a + $ hg push + pushing to http://localhost:$HGPORT/ + searching for changes + abort: remote error: + incompatible Mercurial client; bundle2 required + (see https://www.mercurial-scm.org/wiki/IncompatibleClient) + [255] + $ cat ../errors.log diff -r 0ed75e700ad8 -r 79a926b557f1 tests/test-evolve-serveronly.t --- a/tests/test-evolve-serveronly.t Tue Oct 24 14:30:48 2017 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,198 +0,0 @@ - - $ . ${TESTDIR}/testlib/pythonpath.sh - - $ cat >> $HGRCPATH < [defaults] - > amend=-d "0 0" - > [web] - > push_ssl = false - > allow_push = * - > [phases] - > publish = False - > [experimental] - > bundle2-exp=False # < Mercurial-4.0 - > [devel] - > legacy.exchange=bundle1 - > [extensions] - > EOF - - $ mkcommit() { - > echo "$1" > "$1" - > hg add "$1" - > hg ci -m "add $1" - > } - - - $ hg init server - -Try the multiple ways to setup the extension - - $ hg -R server log --config 'extensions.evolve.serveronly=' - $ hg -R server log --config "extensions.evolve.serveronly=${SRCDIR}/hgext3rd/evolve/serveronly.py" - $ PYTHONPATH=$HGTEST_ORIG_PYTHONPATH hg -R server log --config "extensions.evolve.serveronly=${SRCDIR}/hgext3rd/evolve/serveronly.py" - -setup repo - - $ echo "[extensions]" >> ./server/.hg/hgrc - $ echo "evolve.serveronly=" >> ./server/.hg/hgrc - $ hg serve -R server -n test -p $HGPORT -d --pid-file=hg.pid -A access.log -E errors.log --traceback - $ cat hg.pid >> $DAEMON_PIDS - - $ hg clone http://localhost:$HGPORT/ client - no changes found - updating to branch default - 0 files updated, 0 files merged, 0 files removed, 0 files unresolved - $ cat ./errors.log - $ echo "[extensions]" >> ./client/.hg/hgrc - $ echo "evolve=" >> ./client/.hg/hgrc - $ cp -r client other - -Smoke testing -=============== - - $ cd client - $ mkcommit 0 - $ mkcommit a - $ hg push - pushing to http://localhost:$HGPORT/ - searching for changes - remote: adding changesets - remote: adding manifests - remote: adding file changes - remote: added 2 changesets with 2 changes to 2 files - $ hg pull - pulling from http://localhost:$HGPORT/ - searching for changes - no changes found - $ cat ../errors.log - $ hg pull -R ../other - pulling from http://localhost:$HGPORT/ - requesting all changes - adding changesets - adding manifests - adding file changes - added 2 changesets with 2 changes to 2 files - pull obsolescence markers - the remote repository use years old versions of Mercurial and evolve - pulling obsmarker using legacy method - (please upgrade your server) - new changesets 8685c6d34325:4957bfdac07e - (run 'hg update' to get a working copy) - $ cat ../errors.log - $ hg push -R ../other - pushing to http://localhost:$HGPORT/ - searching for changes - no changes found - [1] - $ cat ../errors.log - -Capacity testing -=================== - - $ curl -s http://localhost:$HGPORT/?cmd=hello - capabilities: _evoext_getbundle_obscommon _evoext_obshash_0 _evoext_obshash_1 _evoext_pullobsmarkers_0 _evoext_pushobsmarkers_0 batch * (glob) - $ curl -s http://localhost:$HGPORT/?cmd=capabilities - _evoext_getbundle_obscommon _evoext_obshash_0 _evoext_obshash_1 _evoext_pullobsmarkers_0 _evoext_pushobsmarkers_0 batch * (no-eol) (glob) - - $ curl -s "http://localhost:$HGPORT/?cmd=listkeys&namespace=namespaces" | sort - bookmarks - namespaces - obsolete - phases - -Push -============= - - $ echo 'A' > a - $ hg amend - $ hg push - pushing to http://localhost:$HGPORT/ - searching for changes - remote: adding changesets - remote: adding manifests - remote: adding file changes - remote: added 1 changesets with 1 changes to 1 files (+1 heads) - the remote repository use years old versions of Mercurial and evolve - pushing obsmarker using legacy method - (please upgrade your server) - pushing 1 obsolescence markers (* bytes) (glob) - remote: 1 obsolescence markers added - remote: obsoleted 1 changesets - $ cat ../errors.log - $ hg push - pushing to http://localhost:$HGPORT/ - searching for changes - no changes found - [1] - $ cat ../errors.log - -Pull -============= - - $ hg -R ../other pull - pulling from http://localhost:$HGPORT/ - searching for changes - adding changesets - adding manifests - adding file changes - added 1 changesets with 1 changes to [12] files \(\+1 heads\) (re) - pull obsolescence markers - the remote repository use years old versions of Mercurial and evolve - pulling obsmarker using legacy method - (please upgrade your server) - 1 obsolescence markers added - obsoleted 1 changesets - new changesets 9d1c114e7797 - (run 'hg heads' to see heads) - $ cat ../errors.log - $ hg -R ../other pull - pulling from http://localhost:$HGPORT/ - searching for changes - no changes found - $ cat ../errors.log - - $ cd .. - -Test disabling obsolete advertisement -=========================================== -(used by bitbucket to select which repo use evolve) - - $ curl -s "http://localhost:$HGPORT/?cmd=listkeys&namespace=namespaces" | sort - bookmarks - namespaces - obsolete - phases - $ curl -s http://localhost:$HGPORT/?cmd=hello - capabilities: _evoext_getbundle_obscommon _evoext_obshash_0 _evoext_obshash_1 _evoext_pullobsmarkers_0 _evoext_pushobsmarkers_0 batch * (glob) - $ curl -s http://localhost:$HGPORT/?cmd=capabilities - _evoext_getbundle_obscommon _evoext_obshash_0 _evoext_obshash_1 _evoext_pullobsmarkers_0 _evoext_pushobsmarkers_0 batch * (no-eol) (glob) - - $ echo '[experimental]' >> server/.hg/hgrc - $ echo 'evolution=!' >> server/.hg/hgrc - $ $RUNTESTDIR/killdaemons.py $DAEMON_PIDS - $ hg serve -R server -n test -p $HGPORT -d --pid-file=hg.pid -A access.log -E errors.log - $ cat hg.pid >> $DAEMON_PIDS - - $ curl -s "http://localhost:$HGPORT/?cmd=listkeys&namespace=namespaces" | sort - bookmarks - namespaces - phases - $ curl -s http://localhost:$HGPORT/?cmd=hello | grep _evoext_pushobsmarkers_0 - [1] - $ curl -s http://localhost:$HGPORT/?cmd=capabilities | grep _evoext_pushobsmarkers_0 - [1] - - $ echo 'evolution=' >> server/.hg/hgrc - $ $RUNTESTDIR/killdaemons.py $DAEMON_PIDS - $ hg serve -R server -n test -p $HGPORT -d --pid-file=hg.pid -A access.log -E errors.log - $ cat hg.pid >> $DAEMON_PIDS - - $ curl -s "http://localhost:$HGPORT/?cmd=listkeys&namespace=namespaces" | sort - bookmarks - namespaces - obsolete - phases - $ curl -s http://localhost:$HGPORT/?cmd=hello - capabilities: _evoext_getbundle_obscommon _evoext_obshash_0 _evoext_obshash_1 _evoext_pullobsmarkers_0 _evoext_pushobsmarkers_0 batch * (glob) - $ curl -s http://localhost:$HGPORT/?cmd=capabilities - _evoext_getbundle_obscommon _evoext_obshash_0 _evoext_obshash_1 _evoext_pullobsmarkers_0 _evoext_pushobsmarkers_0 batch * (no-eol) (glob)