[PATCH 5 of 5 RFC] exchange: support phases discovery via public heads

Gregory Szorc gregory.szorc at gmail.com
Mon Feb 15 21:03:36 EST 2016


# HG changeset patch
# User Gregory Szorc <gregory.szorc at gmail.com>
# Date 1455588068 28800
#      Mon Feb 15 18:01:08 2016 -0800
# Node ID d51ed0ddd05c3c716df5fbd2e811285bcac7366c
# Parent  8b939990c70a4e545f18db3338f7798f09a94ada
exchange: support phases discovery via public heads

Now that we can detect when the server supports exposing phases via
public heads, we leverage this namespace as part of phases discovery.

On Mozilla's Try repository, the phases listkeys response drops from
~64k entries / 2.8 MB to < 1000 entries and < 65 kbytes.

diff --git a/mercurial/exchange.py b/mercurial/exchange.py
--- a/mercurial/exchange.py
+++ b/mercurial/exchange.py
@@ -8,16 +8,17 @@
 from __future__ import absolute_import
 
 import errno
 import urllib
 import urllib2
 
 from .i18n import _
 from .node import (
+    bin,
     hex,
     nullid,
 )
 from . import (
     base85,
     bookmarks as bookmod,
     bundle2,
     changegroup,
@@ -506,36 +507,45 @@ def _pushdiscoverychangeset(pushop):
 
 @pushdiscovery('phase')
 def _pushdiscoveryphase(pushop):
     """discover the phase that needs to be pushed
 
     (computed for both success and failure case for changesets push)"""
     outgoing = pushop.outgoing
     unfi = pushop.repo.unfiltered()
-    remotephases = pushop.remote.listkeys('phases')
-    publishing = remotephases.get('publishing', False)
-    if (pushop.ui.configbool('ui', '_usedassubrepo', False)
-        and remotephases    # server supports phases
-        and not pushop.outgoing.missing # no changesets to be pushed
-        and publishing):
-        # When:
-        # - this is a subrepo push
-        # - and remote support phase
-        # - and no changeset are to be pushed
-        # - and remote is publishing
-        # We may be in issue 3871 case!
-        # We drop the possible phase synchronisation done by
-        # courtesy to publish changesets possibly locally draft
-        # on the remote.
-        remotephases = {'publishing': 'True'}
-    ana = phases.analyzeremotephases(pushop.repo,
-                                     pushop.fallbackheads,
-                                     remotephases)
-    pheads, droots = ana
+
+    if pushop.remote.capable('nonpublishing'):
+        publishing = False
+        publicheads = pushop.remote.listkeys('publicphases')
+        pheads = [bin(n) for n in publicheads]
+        revset = pushop.repo.set('roots(children(%ln))', pheads)
+        droots = [c.node() for c in revset]
+    else:
+        remotephases = pushop.remote.listkeys('phases')
+        publishing = remotephases.get('publishing', False)
+        if (pushop.ui.configbool('ui', '_usedassubrepo', False)
+            and remotephases    # server supports phases
+            and not pushop.outgoing.missing # no changesets to be pushed
+            and publishing):
+            # When:
+            # - this is a subrepo push
+            # - and remote support phase
+            # - and no changeset are to be pushed
+            # - and remote is publishing
+            # We may be in issue 3871 case!
+            # We drop the possible phase synchronisation done by
+            # courtesy to publish changesets possibly locally draft
+            # on the remote.
+            remotephases = {'publishing': 'True'}
+        ana = phases.analyzeremotephases(pushop.repo,
+                                         pushop.fallbackheads,
+                                         remotephases)
+        pheads, droots = ana
+
     extracond = ''
     if not publishing:
         extracond = ' and public()'
     revset = 'heads((%%ln::%%ln) %s)' % extracond
     # Get the list of all revs draft on remote by public here.
     # XXX Beware that revset break if droots is not strictly
     # XXX root we may want to ensure it is but it is costly
     fallback = list(unfi.set(revset, droots, pushop.fallbackheads))


More information about the Mercurial-devel mailing list