setdiscovery: include tip in localheads if it's empty

Summary:
Previously we include tip in sample. But that is problematic for fast paths
like:

    if set(commonsample).issuperset(set(localheads) - {nullid}):
        ui.note(_("all local heads known remotely\n"))
        return localheads, True, remoteheads

If `localheads` is empty, then the returned "common heads" are empty, causing
downloading the entire repo inefficiently.

Fix the issue by moving `tip` from `sample` to `localheads` so the common
heads will include tip in the fast path.

Reviewed By: DurhamG

Differential Revision: D26374303

fbshipit-source-id: 45a2a44e4db4c4ec2a341522a257d46a62b058d5
This commit is contained in:
Jun Wu 2021-02-10 14:06:26 -08:00 committed by Facebook GitHub Bot
parent 74a34dd8c4
commit 334ff0a4ca
2 changed files with 64 additions and 4 deletions

View File

@ -372,6 +372,13 @@ def _findcommonheadsnew(
else:
localheads = ancestorsof
# localheads can be empty in special case: after initial streamclone,
# because both remotenames and visible heads are empty. Ensure 'tip' is
# part of 'localheads' so we don't pull the entire repo.
# TODO: Improve clone protocol so streamclone transfers remote names.
if not localheads:
localheads = [local["tip"].node()]
# Filter out 'nullid' immediately.
localheads = sorted(h for h in localheads if h != nullid)
unknown = set()
@ -416,14 +423,15 @@ def _findcommonheadsnew(
remotename = remotenameforurl(ui, remote.url()) # ex. 'default' or 'remote'
selected = list(selectivepullbookmarknames(local, remotename))
# Include names that the server might have. 'tip' is useful during clone
# code path where remote names are not known yet.
# TODO: Improve clone protocol so streamclone transfers remote names.
for name in selected + ["tip"]:
# Include names (public heads) that the server might have in sample.
# This can efficiently extend the "common" set, if the server does
# have them.
for name in selected:
if name in local:
node = local[name].node()
if node not in sample:
sample.add(node)
# Drop nullid special case.
sample.discard(nullid)
sample = list(sample)

View File

@ -0,0 +1,52 @@
#chg-compatible
$ configure modern
$ newserver server
Populate commits
$ clone server client1
$ cd client1
$ drawdag << 'EOS'
> B
> |
> A
> EOS
$ hg push -r $B --to master --create -q
Check stream clone "pull"
$ hg clone --shallow -U "ssh://user@dummy/server" client2 --debug
running /home/quark/bin/python3 /data/users/quark/fbsource/fbcode/eden/scm/tests/dummyssh 'user@dummy' 'hg -R server serve --stdio'
sending hello command
sending between command
remote: 658
remote: capabilities: treeonly unbundle=HG10GZ,HG10BZ,HG10UN unbundlereplay streamreqs=generaldelta,lz4revlog,revlogv1 knownnodes pushkey batch listkeyspatterns branchmap bundle2=HG20%0Ab2x%253Ainfinitepush%0Ab2x%253Ainfinitepushmutation%0Ab2x%253Ainfinitepushscratchbookmarks%0Abookmarks%0Achangegroup%3D01%2C02%2C03%0Adigests%3Dmd5%2Csha1%2Csha512%0Aerror%3Dabort%2Cunsupportedcontent%2Cpushraced%2Cpushkey%0Alistkeys%0Aphases%3Dheads%0Apushkey%0Aremote-changegroup%3Dhttp%2Chttps%0Atreemanifest%3DTrue%0Atreemanifestserver%3DTrue%0Atreeonly%3DTrue known unbundlehash lookup getbundle changegroupsubset stream_option gettreepack remotefilelog getflogheads getfile
remote: 1
fetching changelog
running /home/quark/bin/python3 /data/users/quark/fbsource/fbcode/eden/scm/tests/dummyssh 'user@dummy' 'hg -R server serve --stdio'
sending hello command
sending between command
remote: 658
remote: capabilities: treeonly unbundle=HG10GZ,HG10BZ,HG10UN unbundlereplay streamreqs=generaldelta,lz4revlog,revlogv1 knownnodes pushkey batch listkeyspatterns branchmap bundle2=HG20%0Ab2x%253Ainfinitepush%0Ab2x%253Ainfinitepushmutation%0Ab2x%253Ainfinitepushscratchbookmarks%0Abookmarks%0Achangegroup%3D01%2C02%2C03%0Adigests%3Dmd5%2Csha1%2Csha512%0Aerror%3Dabort%2Cunsupportedcontent%2Cpushraced%2Cpushkey%0Alistkeys%0Aphases%3Dheads%0Apushkey%0Aremote-changegroup%3Dhttp%2Chttps%0Atreemanifest%3DTrue%0Atreemanifestserver%3DTrue%0Atreeonly%3DTrue known unbundlehash lookup getbundle changegroupsubset stream_option gettreepack remotefilelog getflogheads getfile
remote: 1
sending stream_out_shallow command
3 files to transfer, 465 bytes of data
adding 00manifesttree.i (227 bytes)
adding 00changelog.i (128 bytes)
adding 00changelog.d (110 bytes)
transferred 465 bytes in 0.0 seconds (454 KB/sec)
fetching selected remote bookmarks
reusing connection from pool
preparing listkeys for "bookmarks" with pattern "['master']"
sending listkeyspatterns command
received listkey for "bookmarks": 47 bytes
no changes found
sending getbundle command
bundle2-input-bundle: with-transaction
bundle2-input-part: "bookmarks" supported
bundle2-input-part: total payload size 28
bundle2-input-part: "phase-heads" supported
bundle2-input-part: total payload size 24
bundle2-input-bundle: 1 parts total