# HG changeset patch # User Pierre-Yves David # Date 1488302483 -3600 # Node ID 6942750831bb702a611c65df778f2c93a905fb4d # Parent c8b07459c9bbe40395b1569d1761ba668ba322c7 serveronly: deduplicate code with the main evolve extension Now that 'serveonly' is a sub module of evolve. We can access its content in evolve. As a result we stop duplicating code all common parts are defined in the 'serveronly' module and imported by evolve when needed. diff -r c8b07459c9bb -r 6942750831bb hgext3rd/evolve/__init__.py --- a/hgext3rd/evolve/__init__.py Tue Feb 28 16:12:34 2017 +0100 +++ b/hgext3rd/evolve/__init__.py Tue Feb 28 18:21:23 2017 +0100 @@ -123,6 +123,10 @@ from mercurial.i18n import _ from mercurial.node import nullid +from . import serveronly + +obsexcmsg = serveronly.obsexcmsg + cmdtable = {} command = cmdutil.command(cmdtable) @@ -387,6 +391,8 @@ extsetup = eh.final_extsetup reposetup = eh.final_reposetup +eh.extsetup(serveronly.extsetup) + ##################################################################### ### Option configuration ### ##################################################################### @@ -3307,14 +3313,6 @@ ### Obsolescence marker exchange experimenation ### ##################################################################### -def obsexcmsg(ui, message, important=False): - verbose = ui.configbool('experimental', 'verbose-obsolescence-exchange', - False) - if verbose: - message = 'OBSEXC: ' + message - if important or verbose: - ui.status(message) - def obsexcprg(ui, *args, **kwargs): topic = 'obsmarkers exchange' if ui.configbool('experimental', 'verbose-obsolescence-exchange', False): @@ -3362,65 +3360,25 @@ obsexcmsg(repo.ui, "markers already in sync\n") pushop.outobsmarkers = [] -@eh.wrapfunction(wireproto, 'capabilities') -def discocapabilities(orig, repo, proto): - """wrapper to advertise new capability""" - caps = orig(repo, proto) - if obsolete.isenabled(repo, obsolete.exchangeopt): - caps += ' _evoext_obshash_0' - return caps - @eh.extsetup def _installobsmarkersdiscovery(ui): - hgweb_mod.perms['evoext_obshash'] = 'pull' - hgweb_mod.perms['evoext_obshash1'] = 'pull' - # wrap command content - oldcap, args = wireproto.commands['capabilities'] - def newcap(repo, proto): - return discocapabilities(oldcap, repo, proto) - wireproto.commands['capabilities'] = (newcap, args) - wireproto.commands['evoext_obshash'] = (srv_obshash, 'nodes') - wireproto.commands['evoext_obshash1'] = (srv_obshash1, 'nodes') - if getattr(exchange, '_pushdiscoveryobsmarkers', None) is None: - ui.warn(_('evolve: your mercurial version is too old\n' - 'evolve: (running in degraded mode, push will ' - 'includes all markers)\n')) - else: - olddisco = exchange.pushdiscoverymapping['obsmarker'] - def newdisco(pushop): - _pushdiscoveryobsmarkers(olddisco, pushop) - exchange.pushdiscoverymapping['obsmarker'] = newdisco + olddisco = exchange.pushdiscoverymapping['obsmarker'] + def newdisco(pushop): + _pushdiscoveryobsmarkers(olddisco, pushop) + exchange.pushdiscoverymapping['obsmarker'] = newdisco ### Set discovery START from mercurial import dagutil from mercurial import setdiscovery -def _obshash(repo, nodes, version=0): - if version == 0: - hashs = _obsrelsethashtreefm0(repo) - elif version ==1: - hashs = _obsrelsethashtreefm1(repo) - else: - assert False - nm = repo.changelog.nodemap - revs = [nm.get(n) for n in nodes] - return [r is None and nullid or hashs[r][1] for r in revs] - -def srv_obshash(repo, proto, nodes): - return wireproto.encodelist(_obshash(repo, wireproto.decodelist(nodes))) - -def srv_obshash1(repo, proto, nodes): - return wireproto.encodelist(_obshash(repo, wireproto.decodelist(nodes), - version=1)) - @eh.addattr(localrepo.localpeer, 'evoext_obshash') def local_obshash(peer, nodes): - return _obshash(peer._repo, nodes) + return serveronly._obshash(peer._repo, nodes) @eh.addattr(localrepo.localpeer, 'evoext_obshash1') def local_obshash1(peer, nodes): - return _obshash(peer._repo, nodes, version=1) + return serveronly._obshash(peer._repo, nodes, version=1) @eh.addattr(wireproto.wirepeer, 'evoext_obshash') def peer_obshash(self, nodes): @@ -3453,10 +3411,10 @@ _takefullsample = setdiscovery._takefullsample if remote.capable('_evoext_obshash_1'): getremotehash = remote.evoext_obshash1 - localhash = _obsrelsethashtreefm1(local) + localhash = serveronly._obsrelsethashtreefm1(local) else: getremotehash = remote.evoext_obshash - localhash = _obsrelsethashtreefm0(local) + localhash = serveronly._obsrelsethashtreefm0(local) while undecided: @@ -3605,33 +3563,10 @@ caps.add('_evoext_pushobsmarkers_0') return caps -def _pushobsmarkers(repo, data): - tr = lock = None - try: - lock = repo.lock() - tr = repo.transaction('pushkey: obsolete markers') - new = repo.obsstore.mergemarkers(tr, data) - if new is not None: - obsexcmsg(repo.ui, "%i obsolescence markers added\n" % new, True) - tr.close() - finally: - lockmod.release(tr, lock) - repo.hook('evolve_pushobsmarkers') - @eh.addattr(localrepo.localpeer, 'evoext_pushobsmarkers_0') def local_pushobsmarkers(peer, obsfile): data = obsfile.read() - _pushobsmarkers(peer._repo, data) - -def srv_pushobsmarkers(repo, proto): - """wireprotocol command""" - fp = StringIO() - proto.redirect() - proto.getfile(fp) - data = fp.getvalue() - fp.close() - _pushobsmarkers(repo, data) - return wireproto.pushres(0) + serveronly._pushobsmarkers(peer._repo, data) def _buildpullobsmarkersboundaries(pullop): """small funtion returning the argument for pull markers call @@ -3664,29 +3599,6 @@ kwargs['evo_obscommon'] = common return ret -@eh.wrapfunction(exchange, '_getbundleobsmarkerpart') -def _getbundleobsmarkerpart(orig, bundler, repo, source, **kwargs): - if 'evo_obscommon' not in kwargs: - return orig(bundler, repo, source, **kwargs) - - heads = kwargs.get('heads') - if kwargs.get('obsmarkers', False): - if heads is None: - heads = repo.heads() - obscommon = kwargs.get('evo_obscommon', ()) - assert obscommon - obsset = repo.unfiltered().set('::%ln - ::%ln', heads, obscommon) - subset = [c.node() for c in obsset] - markers = repo.obsstore.relevantmarkers(subset) - exchange.buildobsmarkerspart(bundler, markers) - -@eh.uisetup -def installgetbundlepartgen(ui): - origfunc = exchange.getbundle2partsmapping['obsmarkers'] - def newfunc(*args, **kwargs): - return _getbundleobsmarkerpart(origfunc, *args, **kwargs) - exchange.getbundle2partsmapping['obsmarkers'] = newfunc - @eh.wrapfunction(exchange, '_pullobsolete') def _pullobsolete(orig, pullop): if not obsolete.isenabled(pullop.repo, obsolete.exchangeopt): @@ -3728,28 +3640,6 @@ pullop.repo.invalidatevolatilesets() return tr -def _getobsmarkersstream(repo, heads=None, common=None): - revset = '' - args = [] - repo = repo.unfiltered() - if heads is None: - revset = 'all()' - elif heads: - revset += "(::%ln)" - args.append(heads) - else: - assert False, 'pulling no heads?' - if common: - revset += ' - (::%ln)' - args.append(common) - nodes = [c.node() for c in repo.set(revset, *args)] - markers = repo.obsstore.relevantmarkers(nodes) - obsdata = StringIO() - for chunk in obsolete.encodemarkers(markers, True): - obsdata.write(chunk) - obsdata.seek(0) - return obsdata - @eh.addattr(wireproto.wirepeer, 'evoext_pullobsmarkers_0') def client_pullobsmarkers(self, heads=None, common=None): self.requirecap('_evoext_pullobsmarkers_0', _('look up remote obsmarkers')) @@ -3776,75 +3666,8 @@ @eh.addattr(localrepo.localpeer, 'evoext_pullobsmarkers_0') def local_pullobsmarkers(self, heads=None, common=None): - return _getobsmarkersstream(self._repo, heads=heads, common=common) - -# The wireproto.streamres API changed, handling chunking and compression -# directly. Handle either case. -if util.safehasattr(wireproto.abstractserverproto, 'groupchunks'): - # We need to handle chunking and compression directly - def streamres(d, proto): - return wireproto.streamres(proto.groupchunks(d)) -else: - # Leave chunking and compression to streamres - def streamres(d, proto): - return wireproto.streamres(reader=d, v1compressible=True) - -def srv_pullobsmarkers(repo, proto, others): - opts = wireproto.options('', ['heads', 'common'], others) - for k, v in opts.iteritems(): - if k in ('heads', 'common'): - opts[k] = wireproto.decodelist(v) - obsdata = _getobsmarkersstream(repo, **opts) - finaldata = StringIO() - obsdata = obsdata.getvalue() - finaldata.write('%20i' % len(obsdata)) - finaldata.write(obsdata) - finaldata.seek(0) - return streamres(finaldata, proto) - -def _obsrelsethashtreefm0(repo): - return _obsrelsethashtree(repo, obsolete._fm0encodeonemarker) - -def _obsrelsethashtreefm1(repo): - return _obsrelsethashtree(repo, obsolete._fm1encodeonemarker) - -def _obsrelsethashtree(repo, encodeonemarker): - cache = [] - unfi = repo.unfiltered() - markercache = {} - repo.ui.progress(_("preparing locally"), 0, total=len(unfi)) - for i in unfi: - ctx = unfi[i] - entry = 0 - sha = hashlib.sha1() - # add data from p1 - for p in ctx.parents(): - p = p.rev() - if p < 0: - p = nullid - else: - p = cache[p][1] - if p != nullid: - entry += 1 - sha.update(p) - tmarkers = repo.obsstore.relevantmarkers([ctx.node()]) - if tmarkers: - bmarkers = [] - for m in tmarkers: - if not m in markercache: - markercache[m] = encodeonemarker(m) - bmarkers.append(markercache[m]) - bmarkers.sort() - for m in bmarkers: - entry += 1 - sha.update(m) - if entry: - cache.append((ctx.node(), sha.digest())) - else: - cache.append((ctx.node(), nullid)) - repo.ui.progress(_("preparing locally"), i, total=len(unfi)) - repo.ui.progress(_("preparing locally"), None) - return cache + return serveronly._getobsmarkersstream(self._repo, heads=heads, + common=common) @command('debugobsrelsethashtree', [('', 'v0', None, 'hash on marker format "0"'), @@ -3858,9 +3681,9 @@ if v0 and v1: raise error.Abort('cannot only specify one format') elif v0: - treefunc = _obsrelsethashtreefm0 + treefunc = serveronly._obsrelsethashtreefm0 else: - treefunc = _obsrelsethashtreefm1 + treefunc = serveronly._obsrelsethashtreefm1 for chg, obs in treefunc(repo): ui.status('%s %s\n' % (node.hex(chg), node.hex(obs))) @@ -3912,32 +3735,6 @@ ui.write(_('Done!\n')) -@eh.wrapfunction(wireproto, 'capabilities') -def capabilities(orig, repo, proto): - """wrapper to advertise new capability""" - caps = orig(repo, proto) - if obsolete.isenabled(repo, obsolete.exchangeopt): - caps += ' _evoext_pushobsmarkers_0' - caps += ' _evoext_pullobsmarkers_0' - caps += ' _evoext_obshash_0' - caps += ' _evoext_obshash_1' - caps += ' _evoext_getbundle_obscommon' - return caps - - -@eh.extsetup -def _installwireprotocol(ui): - localrepo.moderncaps.add('_evoext_pullobsmarkers_0') - 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, '*') - # wrap command content - oldcap, args = wireproto.commands['capabilities'] - def newcap(repo, proto): - return capabilities(oldcap, repo, proto) - wireproto.commands['capabilities'] = (newcap, args) - def _helploader(ui): return help.gettext(evolutionhelptext) diff -r c8b07459c9bb -r 6942750831bb hgext3rd/evolve/serveronly.py --- a/hgext3rd/evolve/serveronly.py Tue Feb 28 16:12:34 2017 +0100 +++ b/hgext3rd/evolve/serveronly.py Tue Feb 28 18:21:23 2017 +0100 @@ -21,12 +21,14 @@ exchange, extensions, localrepo, + lock as lockmod, node, obsolete, util, wireproto ) from mercurial.hgweb import hgweb_mod +from mercurial.i18n import _ _pack = struct.pack gboptslist = gboptsmap = None @@ -51,29 +53,37 @@ # End of simple4server specific content +def obsexcmsg(ui, message, important=False): + verbose = ui.configbool('experimental', 'verbose-obsolescence-exchange', + False) + if verbose: + message = 'OBSEXC: ' + message + if important or verbose: + ui.status(message) -# from evolve extension: 1a23c7c52a43 +def _pushobsmarkers(repo, data): + tr = lock = None + try: + lock = repo.lock() + tr = repo.transaction('pushkey: obsolete markers') + new = repo.obsstore.mergemarkers(tr, data) + if new is not None: + obsexcmsg(repo.ui, "%i obsolescence markers added\n" % new, True) + tr.close() + finally: + lockmod.release(tr, lock) + repo.hook('evolve_pushobsmarkers') + def srv_pushobsmarkers(repo, proto): - """That receives a stream of markers and apply then to the repo""" + """wireprotocol command""" fp = StringIO() proto.redirect() proto.getfile(fp) data = fp.getvalue() fp.close() - lock = repo.lock() - try: - tr = repo.transaction('pushkey: obsolete markers') - try: - repo.obsstore.mergemarkers(tr, data) - tr.close() - finally: - tr.release() - finally: - lock.release() - repo.hook('evolve_pushobsmarkers') + _pushobsmarkers(repo, data) return wireproto.pushres(0) -# from evolve extension: 1a23c7c52a43 def _getobsmarkersstream(repo, heads=None, common=None): """Get a binary stream for all markers relevant to `:: - ::` """ @@ -98,64 +108,6 @@ obsdata.seek(0) return obsdata -if not util.safehasattr(obsolete.obsstore, 'relevantmarkers'): - # from evolve extension: 1a23c7c52a43 - class pruneobsstore(obsolete.obsstore): - """And extended obsstore class that read parent information from v1 - format - - Evolve extension adds parent information in prune marker. - We use it to make markers relevant to pushed changeset.""" - - def __init__(self, *args, **kwargs): - self.prunedchildren = {} - return super(pruneobsstore, self).__init__(*args, **kwargs) - - def _load(self, markers): - markers = self._prunedetectingmarkers(markers) - return super(pruneobsstore, self)._load(markers) - - - def _prunedetectingmarkers(self, markers): - for m in markers: - if not m[1]: # no successors - meta = obsolete.decodemeta(m[3]) - if 'p1' in meta: - p1 = node.bin(meta['p1']) - self.prunedchildren.setdefault(p1, set()).add(m) - if 'p2' in meta: - p2 = node.bin(meta['p2']) - self.prunedchildren.setdefault(p2, set()).add(m) - yield m - - # from evolve extension: 1a23c7c52a43 - def relevantmarkers(self, nodes): - """return a set of all obsolescence marker relevant to a set of node. - - "relevant" to a set of node mean: - - - marker that use this changeset as successors - - prune marker of direct children on this changeset. - - recursive application of the two rules on precursors of these markers - - It is a set so you cannot rely on order""" - seennodes = set(nodes) - seenmarkers = set() - pendingnodes = set(nodes) - precursorsmarkers = self.precursors - prunedchildren = self.prunedchildren - while pendingnodes: - direct = set() - for current in pendingnodes: - direct.update(precursorsmarkers.get(current, ())) - direct.update(prunedchildren.get(current, ())) - direct -= seenmarkers - pendingnodes = set([m[0] for m in direct]) - seenmarkers |= direct - pendingnodes -= seennodes - seennodes |= pendingnodes - return seenmarkers - # The wireproto.streamres API changed, handling chunking and compression # directly. Handle either case. if util.safehasattr(wireproto.abstractserverproto, 'groupchunks'): @@ -167,7 +119,6 @@ def streamres(d, proto): return wireproto.streamres(reader=d, v1compressible=True) -# from evolve extension: cf35f38d6a10 def srv_pullobsmarkers(repo, proto, others): """serves a binary stream of markers. @@ -186,20 +137,17 @@ finaldata.seek(0) return streamres(finaldata, proto) - -# from evolve extension: 3249814dabd1 def _obsrelsethashtreefm0(repo): return _obsrelsethashtree(repo, obsolete._fm0encodeonemarker) -# from evolve extension: 3249814dabd1 def _obsrelsethashtreefm1(repo): return _obsrelsethashtree(repo, obsolete._fm1encodeonemarker) -# from evolve extension: 3249814dabd1 def _obsrelsethashtree(repo, encodeonemarker): cache = [] unfi = repo.unfiltered() markercache = {} + repo.ui.progress(_("preparing locally"), 0, total=len(unfi)) for i in unfi: ctx = unfi[i] entry = 0 @@ -229,9 +177,10 @@ cache.append((ctx.node(), sha.digest())) else: cache.append((ctx.node(), node.nullid)) + repo.ui.progress(_("preparing locally"), i, total=len(unfi)) + repo.ui.progress(_("preparing locally"), None) return cache -# from evolve extension: 3249814dabd1 def _obshash(repo, nodes, version=0): if version == 0: hashs = _obsrelsethashtreefm0(repo) @@ -241,18 +190,15 @@ assert False nm = repo.changelog.nodemap revs = [nm.get(n) for n in nodes] - return [r is None and node.nullid or hashs[r][1] for r in revs] + return [r is None and nullid or hashs[r][1] for r in revs] -# from evolve extension: 3249814dabd1 def srv_obshash(repo, proto, nodes): return wireproto.encodelist(_obshash(repo, wireproto.decodelist(nodes))) -# from evolve extension: 3249814dabd1 def srv_obshash1(repo, proto, nodes): return wireproto.encodelist(_obshash(repo, wireproto.decodelist(nodes), version=1)) -# from evolve extension: 3249814dabd1 def capabilities(orig, repo, proto): """wrapper to advertise new capability""" caps = orig(repo, proto) @@ -270,29 +216,23 @@ return orig(bundler, repo, source, **kwargs) heads = kwargs.get('heads') - if 'evo_obscommon' not in kwargs: - return orig(bundler, repo, source, **kwargs) - if kwargs.get('obsmarkers', False): if heads is None: heads = repo.heads() obscommon = kwargs.get('evo_obscommon', ()) - obsset = repo.set('::%ln - ::%ln', heads, obscommon) + assert obscommon + obsset = repo.unfiltered().set('::%ln - ::%ln', heads, obscommon) subset = [c.node() for c in obsset] markers = repo.obsstore.relevantmarkers(subset) exchange.buildobsmarkerspart(bundler, markers) -# from evolve extension: 10867a8e27c6 -# heavily modified def extsetup(ui): localrepo.moderncaps.add('_evoext_b2x_obsmarkers_0') gboptsmap['evo_obscommon'] = 'nodes' - if not util.safehasattr(obsolete.obsstore, 'relevantmarkers'): - obsolete.obsstore = pruneobsstore - obsolete.obsstore.relevantmarkers = relevantmarkers hgweb_mod.perms['evoext_pushobsmarkers_0'] = 'push' hgweb_mod.perms['evoext_pullobsmarkers_0'] = 'pull' hgweb_mod.perms['evoext_obshash'] = 'pull' + hgweb_mod.perms['evoext_obshash1'] = 'pull' wireproto.commands['evoext_pushobsmarkers_0'] = (srv_pushobsmarkers, '') wireproto.commands['evoext_pullobsmarkers_0'] = (srv_pullobsmarkers, '*') # wrap module content diff -r c8b07459c9bb -r 6942750831bb tests/test-simple4server.t --- a/tests/test-simple4server.t Tue Feb 28 16:12:34 2017 +0100 +++ b/tests/test-simple4server.t Tue Feb 28 18:21:23 2017 +0100 @@ -99,6 +99,7 @@ remote: adding file changes remote: added 1 changesets with 1 changes to 1 files (+1 heads) pushing 2 obsolescence markers (* bytes) (glob) + remote: 2 obsolescence markers added $ cat ../errors.log $ hg push pushing to http://localhost:$HGPORT/