# HG changeset patch # User Boris Feld # Date 2017-12-06 21:44:51 # Node ID f77121b6bf1b66b6f3cf6d7a665e2907577d1717 # Parent 67b7e39b441b21d08447d4929a466aff5affbb33 setdiscover: allow to ignore part of the local graph Currently, the push discovery first determines the full set of common nodes before looking into what changesets are outgoing. When pushing a specific subset, this can lead to pathological situations where we search for the status of thousand of local heads that are unrelated to the requested pushes. To fix this, we need to teach the discovery to ignores part of the graph. Most of the necessary pieces were already in place. This changeset just makes them available to higher level API and tests them. Change actually impacting pushes are coming in a later changeset. diff --git a/mercurial/dagutil.py b/mercurial/dagutil.py --- a/mercurial/dagutil.py +++ b/mercurial/dagutil.py @@ -154,8 +154,9 @@ class revlogbaseddag(basedag): class revlogdag(revlogbaseddag): '''dag interface to a revlog''' - def __init__(self, revlog): + def __init__(self, revlog, localsubset=None): revlogbaseddag.__init__(self, revlog, set(revlog)) + self._heads = localsubset def _getheads(self): return [r for r in self._revlog.headrevs() if r != nullrev] diff --git a/mercurial/debugcommands.py b/mercurial/debugcommands.py --- a/mercurial/debugcommands.py +++ b/mercurial/debugcommands.py @@ -734,6 +734,7 @@ def debugstate(ui, repo, **opts): [('', 'old', None, _('use old-style discovery')), ('', 'nonheads', None, _('use old-style discovery with non-heads included')), + ('', 'rev', [], 'restrict discovery to this set of revs'), ] + cmdutil.remoteopts, _('[-l REV] [-r REV] [-b BRANCH]... [OTHER]')) def debugdiscovery(ui, repo, remoteurl="default", **opts): @@ -747,11 +748,8 @@ def debugdiscovery(ui, repo, remoteurl=" # make sure tests are repeatable random.seed(12323) - def doit(localheads, remoteheads, remote=remote): + def doit(pushedrevs, remoteheads, remote=remote): if opts.get('old'): - if localheads: - raise error.Abort('cannot use localheads with old style ' - 'discovery') if not util.safehasattr(remote, 'branches'): # enable in-client legacy support remote = localrepo.locallegacypeer(remote.local()) @@ -765,7 +763,12 @@ def debugdiscovery(ui, repo, remoteurl=" all = dag.ancestorset(dag.internalizeall(common)) common = dag.externalizeall(dag.headsetofconnecteds(all)) else: - common, any, hds = setdiscovery.findcommonheads(ui, repo, remote) + nodes = None + if pushedrevs: + revs = scmutil.revrange(repo, pushedrevs) + nodes = [repo[r].node() for r in revs] + common, any, hds = setdiscovery.findcommonheads(ui, repo, remote, + ancestorsof=nodes) common = set(common) rheads = set(hds) lheads = set(repo.heads()) @@ -794,7 +797,7 @@ def debugdiscovery(ui, repo, remoteurl=" else: remoterevs, _checkout = hg.addbranchrevs(repo, remote, branches, opts.get('remote_head')) - localrevs = opts.get('local_head') + localrevs = opts.get('rev') doit(localrevs, remoterevs) @command('debugextensions', cmdutil.formatteropts, [], norepo=True) diff --git a/mercurial/setdiscovery.py b/mercurial/setdiscovery.py --- a/mercurial/setdiscovery.py +++ b/mercurial/setdiscovery.py @@ -133,7 +133,8 @@ def _limitsample(sample, desiredlen): def findcommonheads(ui, local, remote, initialsamplesize=100, fullsamplesize=200, - abortwhenunrelated=True): + abortwhenunrelated=True, + ancestorsof=None): '''Return a tuple (common, anyincoming, remoteheads) used to identify missing nodes from or in remote. ''' @@ -141,7 +142,11 @@ def findcommonheads(ui, local, remote, roundtrips = 0 cl = local.changelog - dag = dagutil.revlogdag(cl) + localsubset = None + if ancestorsof is not None: + rev = local.changelog.rev + localsubset = [rev(n) for n in ancestorsof] + dag = dagutil.revlogdag(cl, localsubset=localsubset) # early exit if we know all the specified remote heads already ui.debug("query 1; heads\n") diff --git a/tests/test-completion.t b/tests/test-completion.t --- a/tests/test-completion.t +++ b/tests/test-completion.t @@ -261,7 +261,7 @@ Show all commands + options debugdate: extended debugdeltachain: changelog, manifest, dir, template debugdirstate: nodates, datesort - debugdiscovery: old, nonheads, ssh, remotecmd, insecure + debugdiscovery: old, nonheads, rev, ssh, remotecmd, insecure debugextensions: template debugfileset: rev debugfsinfo: diff --git a/tests/test-setdiscovery.t b/tests/test-setdiscovery.t --- a/tests/test-setdiscovery.t +++ b/tests/test-setdiscovery.t @@ -16,11 +16,17 @@ Function to test discovery between two r > echo "% -- a -> b set" > hg -R a debugdiscovery b --verbose --debug --config progress.debug=true > echo + > echo "% -- a -> b set (tip only)" + > hg -R a debugdiscovery b --verbose --debug --config progress.debug=true --rev tip + > echo > echo "% -- b -> a tree" > hg -R b debugdiscovery a --verbose --old > echo > echo "% -- b -> a set" > hg -R b debugdiscovery a --verbose --debug --config progress.debug=true + > echo + > echo "% -- b -> a set (tip only)" + > hg -R b debugdiscovery a --verbose --debug --config progress.debug=true --rev tip > cd .. > } @@ -48,6 +54,13 @@ Small superset: common heads: 01241442b3c2 b5714e113bc0 local is subset + % -- a -> b set (tip only) + comparing with b + query 1; heads + searching for changes + all local heads known remotely + common heads: b5714e113bc0 + % -- b -> a tree comparing with a searching for changes @@ -62,6 +75,14 @@ Small superset: all remote heads known locally common heads: 01241442b3c2 b5714e113bc0 remote is subset + + % -- b -> a set (tip only) + comparing with a + query 1; heads + searching for changes + all remote heads known locally + common heads: 01241442b3c2 b5714e113bc0 + remote is subset Many new: @@ -86,6 +107,16 @@ Many new: 2 total queries in *.????s (glob) common heads: bebd167eb94d + % -- a -> b set (tip only) + comparing with b + query 1; heads + searching for changes + taking quick initial sample + searching: 2 queries + query 2; still undecided: 31, sample size is: 31 + 2 total queries in *.????s (glob) + common heads: 66f7d451a68b + % -- b -> a tree comparing with a searching for changes @@ -101,6 +132,16 @@ Many new: query 2; still undecided: 2, sample size is: 2 2 total queries in *.????s (glob) common heads: bebd167eb94d + + % -- b -> a set (tip only) + comparing with a + query 1; heads + searching for changes + taking initial sample + searching: 2 queries + query 2; still undecided: 2, sample size is: 2 + 2 total queries in *.????s (glob) + common heads: bebd167eb94d Both sides many new with stub: @@ -124,6 +165,16 @@ Both sides many new with stub: 2 total queries in *.????s (glob) common heads: 2dc09a01254d + % -- a -> b set (tip only) + comparing with b + query 1; heads + searching for changes + taking quick initial sample + searching: 2 queries + query 2; still undecided: 31, sample size is: 31 + 2 total queries in *.????s (glob) + common heads: 66f7d451a68b + % -- b -> a tree comparing with a searching for changes @@ -139,6 +190,16 @@ Both sides many new with stub: query 2; still undecided: 29, sample size is: 29 2 total queries in *.????s (glob) common heads: 2dc09a01254d + + % -- b -> a set (tip only) + comparing with a + query 1; heads + searching for changes + taking initial sample + searching: 2 queries + query 2; still undecided: 29, sample size is: 29 + 2 total queries in *.????s (glob) + common heads: 2dc09a01254d Both many new: @@ -163,6 +224,16 @@ Both many new: 2 total queries in *.????s (glob) common heads: 66f7d451a68b + % -- a -> b set (tip only) + comparing with b + query 1; heads + searching for changes + taking quick initial sample + searching: 2 queries + query 2; still undecided: 31, sample size is: 31 + 2 total queries in *.????s (glob) + common heads: 66f7d451a68b + % -- b -> a tree comparing with a searching for changes @@ -178,6 +249,16 @@ Both many new: query 2; still undecided: 31, sample size is: 31 2 total queries in *.????s (glob) common heads: 66f7d451a68b + + % -- b -> a set (tip only) + comparing with a + query 1; heads + searching for changes + taking quick initial sample + searching: 2 queries + query 2; still undecided: 31, sample size is: 31 + 2 total queries in *.????s (glob) + common heads: 66f7d451a68b Both many new skewed: @@ -202,6 +283,16 @@ Both many new skewed: 2 total queries in *.????s (glob) common heads: 66f7d451a68b + % -- a -> b set (tip only) + comparing with b + query 1; heads + searching for changes + taking quick initial sample + searching: 2 queries + query 2; still undecided: 51, sample size is: 51 + 2 total queries in *.????s (glob) + common heads: 66f7d451a68b + % -- b -> a tree comparing with a searching for changes @@ -217,6 +308,16 @@ Both many new skewed: query 2; still undecided: 31, sample size is: 31 2 total queries in *.????s (glob) common heads: 66f7d451a68b + + % -- b -> a set (tip only) + comparing with a + query 1; heads + searching for changes + taking quick initial sample + searching: 2 queries + query 2; still undecided: 31, sample size is: 31 + 2 total queries in *.????s (glob) + common heads: 66f7d451a68b Both many new on top of long history: @@ -244,6 +345,19 @@ Both many new on top of long history: 3 total queries in *.????s (glob) common heads: 7ead0cba2838 + % -- a -> b set (tip only) + comparing with b + query 1; heads + searching for changes + taking quick initial sample + searching: 2 queries + query 2; still undecided: 1049, sample size is: 11 + sampling from both directions + searching: 3 queries + query 3; still undecided: 31, sample size is: 31 + 3 total queries in *.????s (glob) + common heads: 7ead0cba2838 + % -- b -> a tree comparing with a searching for changes @@ -262,6 +376,19 @@ Both many new on top of long history: query 3; still undecided: 15, sample size is: 15 3 total queries in *.????s (glob) common heads: 7ead0cba2838 + + % -- b -> a set (tip only) + comparing with a + query 1; heads + searching for changes + taking quick initial sample + searching: 2 queries + query 2; still undecided: 1029, sample size is: 11 + sampling from both directions + searching: 3 queries + query 3; still undecided: 15, sample size is: 15 + 3 total queries in *.????s (glob) + common heads: 7ead0cba2838 One with >200 heads, which used to use up all of the sample: @@ -327,6 +454,18 @@ One with >200 heads, which used to use u query 6; still undecided: \d+, sample size is: \d+ (re) 6 total queries in *.????s (glob) common heads: 3ee37d65064a + $ hg -R a debugdiscovery b --debug --verbose --config progress.debug=true --rev tip + comparing with b + query 1; heads + searching for changes + taking quick initial sample + searching: 2 queries + query 2; still undecided: 303, sample size is: 9 + sampling from both directions + searching: 3 queries + query 3; still undecided: 3, sample size is: 3 + 3 total queries in *.????s (glob) + common heads: 3ee37d65064a Test actual protocol when pulling one new head in addition to common heads