# HG changeset patch # User Pierre-Yves David # Date 1326077236 -3600 # Node ID cd956049fc14b023c80a440025d3b01cb0ba02f1 # Parent 926c9ee8d4be59e979afa183b9960596748d2c88 discovery: introduce outgoing object for result of findcommonoutgoing Simplifies client logic in multiple places since it encapsulates the computation of the common and, more importantly, the missing node lists. This also allows an upcomping patch to communicate precomputed versions of these lists to clients. diff -r 926c9ee8d4be -r cd956049fc14 mercurial/commands.py --- a/mercurial/commands.py Mon Jan 09 04:16:00 2012 +0100 +++ b/mercurial/commands.py Mon Jan 09 03:47:16 2012 +0100 @@ -977,18 +977,18 @@ raise util.Abort(_("--base is incompatible with specifying " "a destination")) common = [repo.lookup(rev) for rev in base] - outheads = revs and map(repo.lookup, revs) or revs + heads = revs and map(repo.lookup, revs) or revs + cg = repo.getbundle('bundle', heads=heads, common=common) else: dest = ui.expandpath(dest or 'default-push', dest or 'default') dest, branches = hg.parseurl(dest, opts.get('branch')) other = hg.peer(repo, opts, dest) revs, checkout = hg.addbranchrevs(repo, other, branches, revs) heads = revs and map(repo.lookup, revs) or revs - common, outheads = discovery.findcommonoutgoing(repo, other, - onlyheads=heads, - force=opts.get('force')) - - cg = repo.getbundle('bundle', common=common, heads=outheads) + outgoing = discovery.findcommonoutgoing(repo, other, + onlyheads=heads, + force=opts.get('force')) + cg = repo.getlocalbundle('bundle', outgoing) if not cg: ui.status(_("no changes found\n")) return 1 @@ -5436,10 +5436,10 @@ commoninc = None ui.debug('comparing with %s\n' % util.hidepassword(dest)) repo.ui.pushbuffer() - common, outheads = discovery.findcommonoutgoing(repo, other, - commoninc=commoninc) + outgoing = discovery.findcommonoutgoing(repo, other, + commoninc=commoninc) repo.ui.popbuffer() - o = repo.changelog.findmissing(common=common, heads=outheads) + o = outgoing.missing if o: t.append(_('%d outgoing') % len(o)) if 'bookmarks' in other.listkeys('namespaces'): diff -r 926c9ee8d4be -r cd956049fc14 mercurial/discovery.py --- a/mercurial/discovery.py Mon Jan 09 04:16:00 2012 +0100 +++ b/mercurial/discovery.py Mon Jan 09 03:47:16 2012 +0100 @@ -46,20 +46,56 @@ common, anyinc, srvheads = res return (list(common), anyinc, heads or list(srvheads)) +class outgoing(object): + '''Represents the set of nodes present in a local repo but not in a + (possibly) remote one. + + Members: + + missing is a list of all nodes present in local but not in remote. + common is a list of all nodes shared between the two repos. + missingheads is the list of heads of missing. + commonheads is the list of heads of common. + + The sets are computed on demand from the heads, unless provided upfront + by discovery.''' + + def __init__(self, revlog, commonheads, missingheads): + self.commonheads = commonheads + self.missingheads = missingheads + self._revlog = revlog + self._common = None + self._missing = None + + def _computecommonmissing(self): + sets = self._revlog.findcommonmissing(self.commonheads, + self.missingheads) + self._common, self._missing = sets + + @util.propertycache + def common(self): + if self._common is None: + self._computecommonmissing() + return self._common + + @util.propertycache + def missing(self): + if self._missing is None: + self._computecommonmissing() + return self._missing + def findcommonoutgoing(repo, other, onlyheads=None, force=False, commoninc=None): - '''Return a tuple (common, anyoutgoing, heads) used to identify the set - of nodes present in repo but not in other. + '''Return an outgoing instance to identify the nodes present in repo but + not in other. If onlyheads is given, only nodes ancestral to nodes in onlyheads (inclusive) are included. If you already know the local repo's heads, passing them in onlyheads is faster than letting them be recomputed here. If commoninc is given, it must the the result of a prior call to - findcommonincoming(repo, other, force) to avoid recomputing it here. - - The returned tuple is meant to be passed to changelog.findmissing.''' + findcommonincoming(repo, other, force) to avoid recomputing it here.''' common, _any, _hds = commoninc or findcommonincoming(repo, other, force=force) - return (common, onlyheads or repo.heads()) + return outgoing(repo.changelog, common, onlyheads or repo.heads()) def prepush(repo, remote, force, revs, newbranch): '''Analyze the local and remote repositories and determine which @@ -80,12 +116,13 @@ be after push completion. ''' commoninc = findcommonincoming(repo, remote, force=force) - common, revs = findcommonoutgoing(repo, remote, onlyheads=revs, + outgoing = findcommonoutgoing(repo, remote, onlyheads=revs, commoninc=commoninc, force=force) _common, inc, remoteheads = commoninc cl = repo.changelog - alloutg = cl.findmissing(common, revs) + alloutg = outgoing.missing + common = outgoing.commonheads outg = [] secret = [] for o in alloutg: @@ -208,7 +245,7 @@ # use the fast path, no race possible on push cg = repo._changegroup(outg, 'push') else: - cg = repo.getbundle('push', heads=revs, common=common) + cg = repo.getlocalbundle('push', outgoing) # no need to compute outg ancestor. All node in outg have either: # - parents in outg # - parents in common diff -r 926c9ee8d4be -r cd956049fc14 mercurial/hg.py --- a/mercurial/hg.py Mon Jan 09 04:16:00 2012 +0100 +++ b/mercurial/hg.py Mon Jan 09 03:47:16 2012 +0100 @@ -507,9 +507,9 @@ revs = [repo.lookup(rev) for rev in revs] other = peer(repo, opts, dest) - common, outheads = discovery.findcommonoutgoing(repo, other, revs, - force=opts.get('force')) - o = repo.changelog.findmissing(common, outheads) + outgoing = discovery.findcommonoutgoing(repo, other, revs, + force=opts.get('force')) + o = outgoing.missing if not o: ui.status(_("no changes found\n")) return None diff -r 926c9ee8d4be -r cd956049fc14 mercurial/localrepo.py --- a/mercurial/localrepo.py Mon Jan 09 04:16:00 2012 +0100 +++ b/mercurial/localrepo.py Mon Jan 09 03:47:16 2012 +0100 @@ -1739,6 +1739,18 @@ common = set(cl.ancestors(*[cl.rev(n) for n in bases])) return self._changegroupsubset(common, csets, heads, source) + def getlocalbundle(self, source, outgoing): + """Like getbundle, but taking a discovery.outgoing as an argument. + + This is only implemented for local repos and reuses potentially + precomputed sets in outgoing.""" + if not outgoing.missing: + return None + return self._changegroupsubset(outgoing.common, + outgoing.missing, + outgoing.missingheads, + source) + def getbundle(self, source, heads=None, common=None): """Like changegroupsubset, but returns the set difference between the ancestors of heads and the ancestors common. @@ -1756,10 +1768,8 @@ common = [nullid] if not heads: heads = cl.heads() - common, missing = cl.findcommonmissing(common, heads) - if not missing: - return None - return self._changegroupsubset(common, missing, heads, source) + return self.getlocalbundle(source, + discovery.outgoing(cl, common, heads)) def _changegroupsubset(self, commonrevs, csets, heads, source): diff -r 926c9ee8d4be -r cd956049fc14 mercurial/revset.py --- a/mercurial/revset.py Mon Jan 09 04:16:00 2012 +0100 +++ b/mercurial/revset.py Mon Jan 09 03:47:16 2012 +0100 @@ -644,10 +644,10 @@ revs = [repo.lookup(rev) for rev in revs] other = hg.peer(repo, {}, dest) repo.ui.pushbuffer() - common, outheads = discovery.findcommonoutgoing(repo, other, onlyheads=revs) + outgoing = discovery.findcommonoutgoing(repo, other, onlyheads=revs) repo.ui.popbuffer() cl = repo.changelog - o = set([cl.rev(r) for r in repo.changelog.findmissing(common, outheads)]) + o = set([cl.rev(r) for r in outgoing.missing]) return [r for r in subset if r in o] def p1(repo, subset, x):