[PATCH 2 of 2 STABLE] changegroup: use unfiltered ancestor when common node is filtered (issue4982)
Gregory Szorc
gregory.szorc at gmail.com
Wed Dec 2 16:20:36 CST 2015
# HG changeset patch
# User Gregory Szorc <gregory.szorc at gmail.com>
# Date 1449094789 28800
# Wed Dec 02 14:19:49 2015 -0800
# Branch stable
# Node ID baae3bf31522f41dd5e6d7377d0edd8d1cf3fccc
# Parent 36b3a5ae03ae1df7a5a03e21f2f715da3116ea7c
changegroup: use unfiltered ancestor when common node is filtered (issue4982)
The current behavior of computeoutgoing() is to prune common nodes that
are unknown. This check is performed against the current repository's
view/filter, which for many cases (including hgweb) will be the
"visible" filter, which excludes hidden changesets.
If a hidden changeset is dropped from the common node list, every
unhidden changeset in that DAG head that isn't captured by another
entry in the common node list will be part of the outgoing changegroup.
In the worst case scenario, the resulting common node list will be
empty (all passed in nodes are filtered) and all unfiltered changesets
and their corresponding data will be included in the changegroup! This
could result in `hg pull` fetching what is effectivelly a full repo
bundle if the client sends a single common node which is hidden.
This patch teaches computeoutgoing() to be filtering aware. When we
encounter a filtered node, we trace its ancestors back to the first
unfiltered node and substitute that as the common node. All ancestors of
the first unfiltered node are thus excluded from the generated
changegroup.
diff --git a/mercurial/changegroup.py b/mercurial/changegroup.py
--- a/mercurial/changegroup.py
+++ b/mercurial/changegroup.py
@@ -874,12 +874,35 @@ def computeoutgoing(repo, heads, common)
the logic.
Returns a discovery.outgoing object.
"""
+
+ # If a common node is filtered, we trace back to the first unfiltered
+ # ancestor node and use that as a common node. If we don't do this,
+ # we'd have to send a nodes from that filtered nodes DAG head that
+ # aren't also in the common set. In the worst case, there could be
+ # a single filtered node in common and the resulting empty list of
+ # common nodes would result in *all* nodes being marked as outgoing.
+
cl = repo.changelog
+ ucl = repo.unfiltered().changelog
+
if common:
hasnode = cl.hasnode
- common = [n for n in common if hasnode(n)]
+ newcommon = []
+ for n in common:
+ if hasnode(n):
+ newcommon.append(n)
+ continue
+
+ for rev in ucl.ancestors([ucl.rev(n)]):
+ if rev in cl:
+ node = cl.node(rev)
+ if node not in newcommon:
+ newcommon.append(node)
+ break
+
+ common = newcommon
else:
common = [nullid]
if not heads:
heads = cl.heads()
diff --git a/tests/test-obsolete-changeset-exchange.t b/tests/test-obsolete-changeset-exchange.t
--- a/tests/test-obsolete-changeset-exchange.t
+++ b/tests/test-obsolete-changeset-exchange.t
@@ -126,12 +126,10 @@ commands ever stop saying they have hidd
pulling from $TESTTMP/pull-hidden-common
query 1; heads
searching for changes
all local heads known remotely
- 3 changesets found
+ 1 changesets found
list of changesets:
- 96ee1d7354c4ad7372047672c36a1f561e3a6a4c
- a33779fdfc23063680fc31e9ff637dff6876d3d2
bec0734cd68e84477ba7fc1d13e6cff53ab70129
listing keys for "phase"
listing keys for "bookmarks"
bundle2-output-bundle: "HG20", 3 parts total
@@ -140,16 +138,14 @@ commands ever stop saying they have hidd
bundle2-output-part: "listkeys" (params: 1 mandatory) empty payload
bundle2-input-bundle: with-transaction
bundle2-input-part: "changegroup" (params: 1 mandatory 1 advisory) supported
adding changesets
- add changeset 96ee1d7354c4
- add changeset a33779fdfc23
add changeset bec0734cd68e
adding manifests
adding file changes
adding foo revisions
added 1 changesets with 1 changes to 1 files (+1 heads)
- bundle2-input-part: total payload size 1378
+ bundle2-input-part: total payload size 474
bundle2-input-part: "listkeys" (params: 1 mandatory) supported
bundle2-input-part: "listkeys" (params: 1 mandatory) supported
bundle2-input-bundle: 2 parts total
checking for updated bookmarks
More information about the Mercurial-devel
mailing list