Comments
Patch
@@ -243,16 +243,23 @@ class phasecache(object):
return public
if rev < nullrev:
raise ValueError(_('cannot lookup negative revision'))
if self._phaserevs is None or rev >= len(self._phaserevs):
self.invalidate()
self.loadphaserevs(repo)
return self._phaserevs[rev]
+ def publicheads(self, repo):
+ """Return the set of nodes that are "heads" of the public graph."""
+ revset = repo.set('parents(%ln + %ln) & public()',
+ self.phaseroots[secret],
+ self.phaseroots[draft])
+ return set(c.node() for c in revset)
+
def write(self):
if not self.dirty:
return
f = self.opener('phaseroots', 'w', atomictemp=True)
try:
self._write(f)
finally:
f.close()
@@ -369,22 +376,35 @@ def retractboundary(repo, tr, targetphas
This function move boundary *backward* this means that all nodes
are set in the target phase or kept in a *higher* phase.
Simplify boundary to contains phase roots only."""
phcache = repo._phasecache.copy()
phcache.retractboundary(repo, tr, targetphase, nodes)
repo._phasecache.replace(phcache)
-def listphases(repo):
- """List phases root for serialization over pushkey"""
+def listphases(repo, publicheads=False):
+ """List phases heads/root for serialization over pushkey.
+
+ By default, returns a dict of draft phase roots in hex to the draft
+ phase value (``1``). If ``publicheads`` is set, returns a
+ dict of public phase heads to the public phase value (``0``).
+
+ If the repo is publishing, the key ``publishing`` will be set to
+ string value ``True``.
+ """
keys = {}
- value = '%i' % draft
- for root in repo._phasecache.phaseroots[draft]:
- keys[hex(root)] = value
+ if publicheads:
+ value = '%i' % public
+ for head in repo._phasecache.publicheads(repo):
+ keys[hex(head)] = value
+ else:
+ value = '%i' % draft
+ for root in repo._phasecache.phaseroots[draft]:
+ keys[hex(root)] = value
if repo.publishing():
# Add an extra data to let remote know we are a publishing
# repo. Publishing repo can't just pretend they are old repo.
# When pushing to a publishing repo, the client still need to
# push phase boundary
#
# Push do not only push changeset. It also push phase data.
@@ -396,16 +416,20 @@ def listphases(repo):
# 3) repo B push to repo A. X is not pushed but the data that
# X as now public should
#
# The server can't handle it on it's own as it has no idea of
# client phase data.
keys['publishing'] = 'True'
return keys
+def listpublicphases(repo):
+ """Wrapper to be used for listkey registration."""
+ return listphases(repo, publicheads=True)
+
def pushphase(repo, nhex, oldphasestr, newphasestr):
"""List phases root for serialization over pushkey"""
repo = repo.unfiltered()
with repo.lock():
currentphase = repo[nhex].phase()
newphase = abs(int(newphasestr)) # let's avoid negative index surprise
oldphase = abs(int(oldphasestr)) # let's avoid negative index surprise
if currentphase == oldphase and newphase < oldphase:
# HG changeset patch # User Gregory Szorc <gregory.szorc@gmail.com> # Date 1455585317 28800 # Mon Feb 15 17:15:17 2016 -0800 # Node ID 52961d59851f8455f31ca996134870b94e6ea8a0 # Parent 8449ef66f732a71008dc887ffd6efbfb6dc64ee0 phases: enable listphases to emit public phase heads Currently, the phases namespace exposes draft phase roots. On mega-headed non-publishing repositories such as Mozilla's Try and code review repositories, the listkey for draft phase roots can be >1 MB. For clients on slow connections, the exchange of phases information in this manner is inefficient. Upcoming patches will teach the phases discovery mechanism to talk in terms of public phase heads as opposed to draft phase roots. This will require phases exchange to use far less data. The first step of this is enabling the phases listkeys to expose public phase heads instead of draft phase roots. This patch implements that.