mirror of
https://github.com/facebook/sapling.git
synced 2024-10-16 11:52:02 +03:00
584656dff3
Summary: Turned on the auto formatter. Ran `arc lint --apply-patches --take BLACK **/*.py`. Then run `arc lint` again so some other autofixers like spellchecker etc. looked at the code base. Manually accept the changes whenever they make sense, or use a workaround (ex. changing "dict()" to "dict constructor") where autofix is false positive. Disabled linters on files that are hard (i18n/polib.py) to fix, or less interesting to fix (hgsubversion tests), or cannot be fixed without breaking OSS build (FBPYTHON4). Conflicted linters (test-check-module-imports.t, part of test-check-code.t, test-check-pyflakes.t) are removed or disabled. Duplicated linters (test-check-pyflakes.t, test-check-pylint.t) are removed. An issue of the auto-formatter is lines are no longer guarnateed to be <= 80 chars. But that seems less important comparing with the benefit auto-formatter provides. As we're here, also remove test-check-py3-compat.t, as it is currently broken if `PYTHON3=/bin/python3` is set. Reviewed By: wez, phillco, simpkins, pkaush, singhsrb Differential Revision: D8173629 fbshipit-source-id: 90e248ae0c5e6eaadbe25520a6ee42d32005621b
159 lines
5.4 KiB
Python
159 lines
5.4 KiB
Python
# discovery.py - protocol changeset discovery functions
|
|
#
|
|
# Copyright 2010 Matt Mackall <mpm@selenic.com>
|
|
#
|
|
# This software may be used and distributed according to the terms of the
|
|
# GNU General Public License version 2 or any later version.
|
|
|
|
from __future__ import absolute_import
|
|
|
|
import collections
|
|
|
|
from . import error, progress
|
|
from .i18n import _
|
|
from .node import nullid, short
|
|
|
|
|
|
try:
|
|
xrange(0)
|
|
except NameError:
|
|
xrange = range
|
|
|
|
|
|
def findcommonincoming(repo, remote, heads=None, force=False):
|
|
"""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.
|
|
"""
|
|
|
|
knownnode = repo.changelog.hasnode
|
|
search = []
|
|
fetch = set()
|
|
seen = set()
|
|
seenbranch = set()
|
|
base = set()
|
|
|
|
if not heads:
|
|
heads = remote.heads()
|
|
|
|
if repo.changelog.tip() == nullid:
|
|
base.add(nullid)
|
|
if heads != [nullid]:
|
|
return [nullid], [nullid], list(heads)
|
|
return [nullid], [], heads
|
|
|
|
# assume we're closer to the tip than the root
|
|
# and start by examining the heads
|
|
repo.ui.status(_("searching for changes\n"))
|
|
|
|
unknown = []
|
|
for h in heads:
|
|
if not knownnode(h):
|
|
unknown.append(h)
|
|
else:
|
|
base.add(h)
|
|
|
|
if not unknown:
|
|
return list(base), [], list(heads)
|
|
|
|
req = set(unknown)
|
|
reqcnt = 0
|
|
|
|
with progress.bar(repo.ui, _("searching"), _("queries")) as prog:
|
|
# 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)
|
|
unknown = collections.deque(remote.branches(unknown))
|
|
while unknown:
|
|
r = []
|
|
while unknown:
|
|
n = unknown.popleft()
|
|
if n[0] in seen:
|
|
continue
|
|
|
|
repo.ui.debug("examining %s:%s\n" % (short(n[0]), short(n[1])))
|
|
if n[0] == nullid: # found the end of the branch
|
|
pass
|
|
elif n in seenbranch:
|
|
repo.ui.debug("branch already found\n")
|
|
continue
|
|
elif n[1] and knownnode(n[1]): # do we know the base?
|
|
repo.ui.debug(
|
|
"found incomplete branch %s:%s\n" % (short(n[0]), short(n[1]))
|
|
)
|
|
search.append(n[0:2]) # schedule branch range for scanning
|
|
seenbranch.add(n)
|
|
else:
|
|
if n[1] not in seen and n[1] not in fetch:
|
|
if knownnode(n[2]) and knownnode(n[3]):
|
|
repo.ui.debug("found new changeset %s\n" % short(n[1]))
|
|
fetch.add(n[1]) # earliest unknown
|
|
for p in n[2:4]:
|
|
if knownnode(p):
|
|
base.add(p) # latest known
|
|
|
|
for p in n[2:4]:
|
|
if p not in req and not knownnode(p):
|
|
r.append(p)
|
|
req.add(p)
|
|
seen.add(n[0])
|
|
|
|
if r:
|
|
reqcnt += 1
|
|
prog.value = reqcnt
|
|
repo.ui.debug("request %d: %s\n" % (reqcnt, " ".join(map(short, r))))
|
|
for p in xrange(0, len(r), 10):
|
|
for b in remote.branches(r[p : p + 10]):
|
|
repo.ui.debug("received %s:%s\n" % (short(b[0]), short(b[1])))
|
|
unknown.append(b)
|
|
|
|
# do binary search on the branches we found
|
|
while search:
|
|
newsearch = []
|
|
reqcnt += 1
|
|
prog.value = reqcnt
|
|
for n, l in zip(search, remote.between(search)):
|
|
l.append(n[1])
|
|
p = n[0]
|
|
f = 1
|
|
for i in l:
|
|
repo.ui.debug("narrowing %d:%d %s\n" % (f, len(l), short(i)))
|
|
if knownnode(i):
|
|
if f <= 2:
|
|
repo.ui.debug("found new branch changeset %s\n" % short(p))
|
|
fetch.add(p)
|
|
base.add(i)
|
|
else:
|
|
repo.ui.debug(
|
|
"narrowed branch search to %s:%s\n"
|
|
% (short(p), short(i))
|
|
)
|
|
newsearch.append((p, i))
|
|
break
|
|
p, f = i, f * 2
|
|
search = newsearch
|
|
|
|
# sanity check our fetch list
|
|
for f in fetch:
|
|
if knownnode(f):
|
|
raise error.RepoError(_("already have changeset ") + short(f[:4]))
|
|
|
|
base = list(base)
|
|
if base == [nullid]:
|
|
if force:
|
|
repo.ui.warn(_("warning: repository is unrelated\n"))
|
|
else:
|
|
raise error.Abort(_("repository is unrelated"))
|
|
|
|
repo.ui.debug(
|
|
"found new changesets starting at " + " ".join([short(f) for f in fetch]) + "\n"
|
|
)
|
|
repo.ui.debug("%d total queries\n" % reqcnt)
|
|
|
|
return base, list(fetch), heads
|