Mercurial > evolve
view hgext3rd/topic/discovery.py @ 1925:8f8a48a2e97d
stack: whitespace
author | Sean Farley <sean@farley.io> |
---|---|
date | Mon, 21 Mar 2016 21:30:14 -0700 |
parents | 4898296d7d25 |
children | 9d6d30e36cdd |
line wrap: on
line source
import weakref from mercurial import branchmap from mercurial import error from mercurial import exchange from mercurial.i18n import _ from . import topicmap def _headssummary(orig, repo, remote, outgoing): publishing = ('phases' not in remote.listkeys('namespaces') or bool(remote.listkeys('phases').get('publishing', False))) if publishing or not remote.capable('topics'): return orig(repo, remote, outgoing) oldrepo = repo.__class__ oldbranchcache = branchmap.branchcache oldfilename = branchmap._filename try: class repocls(repo.__class__): def __getitem__(self, key): ctx = super(repocls, self).__getitem__(key) oldbranch = ctx.branch def branch(): branch = oldbranch() topic = ctx.topic() if topic: branch = "%s:%s" % (branch, topic) return branch ctx.branch = branch return ctx repo.__class__ = repocls branchmap.branchcache = topicmap.topiccache branchmap._filename = topicmap._filename summary = orig(repo, remote, outgoing) for key, value in summary.iteritems(): if ':' in key: # This is a topic if value[0] is None and value[1]: summary[key] = ([value[1].pop(0)], ) + value[1:] return summary finally: repo.__class__ = oldrepo branchmap.branchcache = oldbranchcache branchmap._filename = oldfilename def wireprotobranchmap(orig, repo, proto): oldrepo = repo.__class__ try: class repocls(repo.__class__): def branchmap(self): usetopic = not self.publishing() return super(repocls, self).branchmap(topic=usetopic) repo.__class__ = repocls return orig(repo, proto) finally: repo.__class__ = oldrepo # Discovery have deficiency around phases, branch can get new heads with pure # phases change. This happened with a changeset was allowed to be pushed # because it had a topic, but it later become public and create a new branch # head. # # Handle this by doing an extra check for new head creation server side def _nbheads(repo): data = {} for b in repo.branchmap().iterbranches(): if ':' in b[0]: continue data[b[0]] = len(b[1]) return data def handlecheckheads(orig, op, inpart): orig(op, inpart) if op.repo.publishing(): return tr = op.gettransaction() if tr.hookargs['source'] not in ('push', 'serve'): # not a push return tr._prepushheads = _nbheads(op.repo) reporef = weakref.ref(op.repo) oldvalidator = tr.validator def validator(tr): repo = reporef() if repo is not None: repo.invalidatecaches() finalheads = _nbheads(repo) for branch, oldnb in tr._prepushheads.iteritems(): newnb = finalheads.pop(branch, 0) if oldnb < newnb: msg = _('push create a new head on branch "%s"' % branch) raise error.Abort(msg) for branch, newnb in finalheads.iteritems(): if 1 < newnb: msg = _('push create more than 1 head on new branch "%s"' % branch) raise error.Abort(msg) return oldvalidator(tr) tr.validator = validator handlecheckheads.params = frozenset() def _pushb2phases(orig, pushop, bundler): hascheck = any(p.type == 'check:heads' for p in bundler._parts) if pushop.outdatedphases and not hascheck: exchange._pushb2ctxcheckheads(pushop, bundler) return orig(pushop, bundler) def wireprotocaps(orig, repo, proto): caps = orig(repo, proto) if repo.peer().capable('topics'): caps.append('topics') return caps