##// END OF EJS Templates
dirstate: add a comment about a racy piece of code during updates...
dirstate: add a comment about a racy piece of code during updates This is a bit that is not really correct but works "fine" in practice. Let us write the details down so that people stop wondering how that logic might be correct… It is not. Differential Revision: https://phab.mercurial-scm.org/D11781

File last commit:

r47758:07b9ebea default
r49200:c655483e default
Show More
treediscovery.py
187 lines | 5.9 KiB | text/x-python | PythonLexer
Peter Arrenbrecht
discovery: add new set-based discovery...
r14164 # discovery.py - protocol changeset discovery functions
#
Raphaël Gomès
contributor: change mentions of mpm to olivia...
r47575 # Copyright 2010 Olivia Mackall <olivia@selenic.com>
Peter Arrenbrecht
discovery: add new set-based discovery...
r14164 #
# This software may be used and distributed according to the terms of the
# GNU General Public License version 2 or any later version.
Gregory Szorc
treediscovery: use absolute_import
r25987 from __future__ import absolute_import
Martin von Zweigbergk
util: drop alias for collections.deque...
r25113 import collections
Gregory Szorc
treediscovery: use absolute_import
r25987
from .i18n import _
Joerg Sonnenberger
node: replace nullid and friends with nodeconstants class...
r47771 from .node import short
Gregory Szorc
treediscovery: use absolute_import
r25987 from . import (
error,
Gregory Szorc
global: use pycompat.xrange()...
r38806 pycompat,
Gregory Szorc
treediscovery: use absolute_import
r25987 )
Peter Arrenbrecht
discovery: add new set-based discovery...
r14164
Augie Fackler
formatting: blacken the codebase...
r43346
debugdiscovery: display the number of roundtrip used...
r46726 def findcommonincoming(repo, remote, heads=None, force=False, audit=None):
Peter Arrenbrecht
discovery: add new set-based discovery...
r14164 """Return a tuple (common, fetch, heads) used to identify the common
subset of nodes between repo and remote.
"common" is a list of (at least) the heads of the common subset.
"fetch" is a list of roots of the nodes that would be incoming, to be
supplied to changegroupsubset.
"heads" is either the supplied heads, or else the remote's heads.
"""
Pierre-Yves David
discovery: stop using nodemap for membership testing...
r20225 knownnode = repo.changelog.hasnode
Peter Arrenbrecht
discovery: add new set-based discovery...
r14164 search = []
fetch = set()
seen = set()
seenbranch = set()
base = set()
if not heads:
Gregory Szorc
treediscovery: switch to command executor interface...
r37652 with remote.commandexecutor() as e:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 heads = e.callcommand(b'heads', {}).result()
Peter Arrenbrecht
discovery: add new set-based discovery...
r14164
debugdiscovery: display the number of roundtrip used...
r46726 if audit is not None:
audit[b'total-roundtrips'] = 1
Joerg Sonnenberger
node: replace nullid and friends with nodeconstants class...
r47771 if repo.changelog.tip() == repo.nullid:
base.add(repo.nullid)
if heads != [repo.nullid]:
return [repo.nullid], [repo.nullid], list(heads)
return [repo.nullid], [], heads
Peter Arrenbrecht
discovery: add new set-based discovery...
r14164
# assume we're closer to the tip than the root
# and start by examining the heads
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 repo.ui.status(_(b"searching for changes\n"))
Peter Arrenbrecht
discovery: add new set-based discovery...
r14164
unknown = []
for h in heads:
Pierre-Yves David
discovery: stop using nodemap for membership testing...
r20225 if not knownnode(h):
Peter Arrenbrecht
discovery: add new set-based discovery...
r14164 unknown.append(h)
else:
base.add(h)
Peter Arrenbrecht
treediscovery: fix regression when run against older repos (issue2793)...
r14199 if not unknown:
return list(base), [], list(heads)
Peter Arrenbrecht
discovery: add new set-based discovery...
r14164 req = set(unknown)
reqcnt = 0
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 progress = repo.ui.makeprogress(_(b'searching'), unit=_(b'queries'))
Peter Arrenbrecht
discovery: add new set-based discovery...
r14164
# search through remote branches
# a 'branch' here is a linear segment of history, with four parts:
# head, root, first parent, second parent
# (a branch always has two parents (or none) by definition)
Gregory Szorc
treediscovery: switch to command executor interface...
r37652 with remote.commandexecutor() as e:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 branches = e.callcommand(b'branches', {b'nodes': unknown}).result()
Gregory Szorc
treediscovery: switch to command executor interface...
r37652
unknown = collections.deque(branches)
Peter Arrenbrecht
discovery: add new set-based discovery...
r14164 while unknown:
r = []
while unknown:
Bryan O'Sullivan
cleanup: use the deque type where appropriate...
r16803 n = unknown.popleft()
Peter Arrenbrecht
discovery: add new set-based discovery...
r14164 if n[0] in seen:
continue
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 repo.ui.debug(b"examining %s:%s\n" % (short(n[0]), short(n[1])))
Joerg Sonnenberger
node: replace nullid and friends with nodeconstants class...
r47771 if n[0] == repo.nullid: # found the end of the branch
Peter Arrenbrecht
discovery: add new set-based discovery...
r14164 pass
elif n in seenbranch:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 repo.ui.debug(b"branch already found\n")
Peter Arrenbrecht
discovery: add new set-based discovery...
r14164 continue
Augie Fackler
formatting: blacken the codebase...
r43346 elif n[1] and knownnode(n[1]): # do we know the base?
repo.ui.debug(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b"found incomplete branch %s:%s\n"
Augie Fackler
formatting: blacken the codebase...
r43346 % (short(n[0]), short(n[1]))
)
search.append(n[0:2]) # schedule branch range for scanning
Peter Arrenbrecht
discovery: add new set-based discovery...
r14164 seenbranch.add(n)
else:
if n[1] not in seen and n[1] not in fetch:
Pierre-Yves David
discovery: stop using nodemap for membership testing...
r20225 if knownnode(n[2]) and knownnode(n[3]):
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 repo.ui.debug(b"found new changeset %s\n" % short(n[1]))
Augie Fackler
formatting: blacken the codebase...
r43346 fetch.add(n[1]) # earliest unknown
Peter Arrenbrecht
discovery: add new set-based discovery...
r14164 for p in n[2:4]:
Pierre-Yves David
discovery: stop using nodemap for membership testing...
r20225 if knownnode(p):
Augie Fackler
formatting: blacken the codebase...
r43346 base.add(p) # latest known
Peter Arrenbrecht
discovery: add new set-based discovery...
r14164
for p in n[2:4]:
Pierre-Yves David
discovery: stop using nodemap for membership testing...
r20225 if p not in req and not knownnode(p):
Peter Arrenbrecht
discovery: add new set-based discovery...
r14164 r.append(p)
req.add(p)
seen.add(n[0])
if r:
reqcnt += 1
Martin von Zweigbergk
treediscovery: use progress helper...
r38419 progress.increment()
Augie Fackler
formatting: blacken the codebase...
r43346 repo.ui.debug(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b"request %d: %s\n" % (reqcnt, b" ".join(map(short, r)))
Augie Fackler
formatting: blacken the codebase...
r43346 )
Gregory Szorc
global: use pycompat.xrange()...
r38806 for p in pycompat.xrange(0, len(r), 10):
Gregory Szorc
treediscovery: switch to command executor interface...
r37652 with remote.commandexecutor() as e:
Augie Fackler
formatting: blacken the codebase...
r43346 branches = e.callcommand(
Augie Fackler
formating: upgrade to black 20.8b1...
r46554 b'branches',
{
b'nodes': r[p : p + 10],
},
Augie Fackler
formatting: blacken the codebase...
r43346 ).result()
Gregory Szorc
treediscovery: switch to command executor interface...
r37652
for b in branches:
Augie Fackler
formatting: blacken the codebase...
r43346 repo.ui.debug(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b"received %s:%s\n" % (short(b[0]), short(b[1]))
Augie Fackler
formatting: blacken the codebase...
r43346 )
Peter Arrenbrecht
discovery: add new set-based discovery...
r14164 unknown.append(b)
# do binary search on the branches we found
while search:
newsearch = []
reqcnt += 1
Martin von Zweigbergk
treediscovery: use progress helper...
r38419 progress.increment()
Gregory Szorc
treediscovery: switch to command executor interface...
r37652
with remote.commandexecutor() as e:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 between = e.callcommand(b'between', {b'pairs': search}).result()
Gregory Szorc
treediscovery: switch to command executor interface...
r37652
for n, l in zip(search, between):
Peter Arrenbrecht
discovery: add new set-based discovery...
r14164 l.append(n[1])
p = n[0]
f = 1
for i in l:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 repo.ui.debug(b"narrowing %d:%d %s\n" % (f, len(l), short(i)))
Pierre-Yves David
discovery: stop using nodemap for membership testing...
r20225 if knownnode(i):
Peter Arrenbrecht
discovery: add new set-based discovery...
r14164 if f <= 2:
Augie Fackler
formatting: blacken the codebase...
r43346 repo.ui.debug(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b"found new branch changeset %s\n" % short(p)
Augie Fackler
formatting: blacken the codebase...
r43346 )
Peter Arrenbrecht
discovery: add new set-based discovery...
r14164 fetch.add(p)
base.add(i)
else:
Augie Fackler
formatting: blacken the codebase...
r43346 repo.ui.debug(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b"narrowed branch search to %s:%s\n"
Augie Fackler
formatting: blacken the codebase...
r43346 % (short(p), short(i))
)
Peter Arrenbrecht
discovery: add new set-based discovery...
r14164 newsearch.append((p, i))
break
p, f = i, f * 2
search = newsearch
# sanity check our fetch list
for f in fetch:
Pierre-Yves David
discovery: stop using nodemap for membership testing...
r20225 if knownnode(f):
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 raise error.RepoError(_(b"already have changeset ") + short(f[:4]))
Peter Arrenbrecht
discovery: add new set-based discovery...
r14164
base = list(base)
Joerg Sonnenberger
node: replace nullid and friends with nodeconstants class...
r47771 if base == [repo.nullid]:
Peter Arrenbrecht
discovery: add new set-based discovery...
r14164 if force:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 repo.ui.warn(_(b"warning: repository is unrelated\n"))
Peter Arrenbrecht
discovery: add new set-based discovery...
r14164 else:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 raise error.Abort(_(b"repository is unrelated"))
Peter Arrenbrecht
discovery: add new set-based discovery...
r14164
Augie Fackler
formatting: blacken the codebase...
r43346 repo.ui.debug(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b"found new changesets starting at "
+ b" ".join([short(f) for f in fetch])
+ b"\n"
Augie Fackler
formatting: blacken the codebase...
r43346 )
Peter Arrenbrecht
discovery: add new set-based discovery...
r14164
Martin von Zweigbergk
treediscovery: use progress helper...
r38419 progress.complete()
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 repo.ui.debug(b"%d total queries\n" % reqcnt)
debugdiscovery: display the number of roundtrip used...
r46726 if audit is not None:
audit[b'total-roundtrips'] = reqcnt
Peter Arrenbrecht
discovery: add new set-based discovery...
r14164
return base, list(fetch), heads