diff mercurial/setdiscovery.py @ 46316:6ee9bd69ff7f

discovery: add a devel.discovery.exchange-heads Currently all discovery start with testing local and remote heads. For analysis purpose we make it possible to disable that initial "handshake" and start discovery with the whole repository as undecided. Differential Revision: https://phab.mercurial-scm.org/D9801
author Pierre-Yves David <pierre-yves.david@octobus.net>
date Sat, 16 Jan 2021 01:02:03 +0100
parents 9689d3f3f8c5
children 0600e8467101
line wrap: on
line diff
--- a/mercurial/setdiscovery.py	Sun Jan 17 02:48:15 2021 +0100
+++ b/mercurial/setdiscovery.py	Sat Jan 16 01:02:03 2021 +0100
@@ -314,6 +314,8 @@
     else:
         ownheads = [rev for rev in cl.headrevs() if rev != nullrev]
 
+    initial_head_exchange = ui.configbool(b'devel', b'discovery.exchange-heads')
+
     # We also ask remote about all the local heads. That set can be arbitrarily
     # large, so we used to limit it size to `initialsamplesize`. We no longer
     # do as it proved counter productive. The skipped heads could lead to a
@@ -365,33 +367,39 @@
     #     graph (with many heads) attached to, but very independant to a the
     #     "simple" graph on the server. This is a fairly usual case and have
     #     not been met in the wild so far.
-    if remote.limitedarguments:
-        sample = _limitsample(ownheads, initialsamplesize)
-        # indices between sample and externalized version must match
-        sample = list(sample)
-    else:
-        sample = ownheads
+    if initial_head_exchange:
+        if remote.limitedarguments:
+            sample = _limitsample(ownheads, initialsamplesize)
+            # indices between sample and externalized version must match
+            sample = list(sample)
+        else:
+            sample = ownheads
 
-    ui.debug(b"query 1; heads\n")
-    roundtrips += 1
-    with remote.commandexecutor() as e:
-        fheads = e.callcommand(b'heads', {})
-        fknown = e.callcommand(
-            b'known',
-            {
-                b'nodes': [clnode(r) for r in sample],
-            },
-        )
+        ui.debug(b"query 1; heads\n")
+        roundtrips += 1
+        with remote.commandexecutor() as e:
+            fheads = e.callcommand(b'heads', {})
+            fknown = e.callcommand(
+                b'known',
+                {
+                    b'nodes': [clnode(r) for r in sample],
+                },
+            )
+
+        srvheadhashes, yesno = fheads.result(), fknown.result()
 
-    srvheadhashes, yesno = fheads.result(), fknown.result()
-
-    if audit is not None:
-        audit[b'total-roundtrips'] = 1
+        if audit is not None:
+            audit[b'total-roundtrips'] = 1
 
-    if cl.tip() == nullid:
-        if srvheadhashes != [nullid]:
-            return [nullid], True, srvheadhashes
-        return [nullid], False, []
+        if cl.tip() == nullid:
+            if srvheadhashes != [nullid]:
+                return [nullid], True, srvheadhashes
+            return [nullid], False, []
+    else:
+        # we still need the remote head for the function return
+        with remote.commandexecutor() as e:
+            fheads = e.callcommand(b'heads', {})
+        srvheadhashes = fheads.result()
 
     # start actual discovery (we note this before the next "if" for
     # compatibility reasons)
@@ -408,15 +416,16 @@
         except error.LookupError:
             continue
 
-    # early exit if we know all the specified remote heads already
-    if len(knownsrvheads) == len(srvheadhashes):
-        ui.debug(b"all remote heads known locally\n")
-        return srvheadhashes, False, srvheadhashes
+    if initial_head_exchange:
+        # early exit if we know all the specified remote heads already
+        if len(knownsrvheads) == len(srvheadhashes):
+            ui.debug(b"all remote heads known locally\n")
+            return srvheadhashes, False, srvheadhashes
 
-    if len(sample) == len(ownheads) and all(yesno):
-        ui.note(_(b"all local changesets known remotely\n"))
-        ownheadhashes = [clnode(r) for r in ownheads]
-        return ownheadhashes, True, srvheadhashes
+        if len(sample) == len(ownheads) and all(yesno):
+            ui.note(_(b"all local changesets known remotely\n"))
+            ownheadhashes = [clnode(r) for r in ownheads]
+            return ownheadhashes, True, srvheadhashes
 
     # full blown discovery
 
@@ -429,12 +438,13 @@
     disco = partialdiscovery(
         local, ownheads, hard_limit_sample, randomize=randomize
     )
-    # treat remote heads (and maybe own heads) as a first implicit sample
-    # response
-    disco.addcommons(knownsrvheads)
-    disco.addinfo(zip(sample, yesno))
+    if initial_head_exchange:
+        # treat remote heads (and maybe own heads) as a first implicit sample
+        # response
+        disco.addcommons(knownsrvheads)
+        disco.addinfo(zip(sample, yesno))
 
-    full = False
+    full = not initial_head_exchange
     progress = ui.makeprogress(_(b'searching'), unit=_(b'queries'))
     while not disco.iscomplete():