# HG changeset patch # User Boris Feld # Date 2018-12-28 02:14:34 # Node ID 3023bc4b3da060f0b855a83858686d9fd7aedbc2 # Parent 3c85a62d746292686d7557c855148508027fed96 discovery: introduce a partialdiscovery object This object will ultimately gather the data about common, undecided and missing revs in a single place and deal with most graph related computations. The goal is both to clarify the algorithm and to help provides a simple and clear API that can be reimplemented in Rust. For now, we only moved the `common` set in the object. In this commit, some direct access to the "private" `disco._common` attribute persist. They have not been removed yet because we won't need to expose a full API identical to `incrementalmissingancestors` and it seems simpler to access the attribute directly until the replacement is in place. diff --git a/mercurial/setdiscovery.py b/mercurial/setdiscovery.py --- a/mercurial/setdiscovery.py +++ b/mercurial/setdiscovery.py @@ -161,6 +161,28 @@ def _limitsample(sample, desiredlen): sample = set(random.sample(sample, desiredlen)) return sample +class partialdiscovery(object): + """an object representing ongoing discovery + + Feed with data from the remote repository, this object keep track of the + current set of changeset in various states: + + - common: own nodes I know we both know + """ + + def __init__(self, repo): + self._repo = repo + self._common = repo.changelog.incrementalmissingrevs() + + def addcommons(self, commons): + """registrer nodes known as common""" + self._common.addbases(commons) + + def hasinfo(self): + """return True is we have any clue about the remote state""" + return self._common.hasbases() + + def findcommonheads(ui, local, remote, initialsamplesize=100, fullsamplesize=200, @@ -227,14 +249,14 @@ def findcommonheads(ui, local, remote, # full blown discovery - # own nodes I know we both know + disco = partialdiscovery(local) # treat remote heads (and maybe own heads) as a first implicit sample # response - common = cl.incrementalmissingrevs(srvheads) + disco.addcommons(srvheads) commoninsample = set(n for i, n in enumerate(sample) if yesno[i]) - common.addbases(commoninsample) + disco.addcommons(commoninsample) # own nodes where I don't know if remote knows them - undecided = set(common.missingancestors(ownheads)) + undecided = set(disco._common.missingancestors(ownheads)) # own nodes I know remote lacks missing = set() @@ -256,7 +278,7 @@ def findcommonheads(ui, local, remote, if not undecided: break - if full or common.hasbases(): + if full or disco.hasinfo(): if full: ui.note(_("sampling from both directions\n")) else: @@ -286,13 +308,13 @@ def findcommonheads(ui, local, remote, if sample: commoninsample = set(n for i, n in enumerate(sample) if yesno[i]) - common.addbases(commoninsample) - common.removeancestorsfrom(undecided) + disco.addcommons(commoninsample) + disco._common.removeancestorsfrom(undecided) # heads(common) == heads(common.bases) since common represents common.bases # and all its ancestors # The presence of nullrev will confuse heads(). So filter it out. - result = set(local.revs('heads(%ld)', common.bases - {nullrev})) + result = set(local.revs('heads(%ld)', disco._common.bases - {nullrev})) elapsed = util.timer() - start progress.complete() ui.debug("%d total queries in %.4fs\n" % (roundtrips, elapsed))