D5406: wireprotov2: unify file revision collection and linknode derivation
indygreg (Gregory Szorc)
phabricator at mercurial-scm.org
Mon Dec 10 16:26:10 EST 2018
This revision was automatically updated to reflect the committed changes.
Closed by commit rHG08cfa77d7288: wireprotov2: unify file revision collection and linknode derivation (authored by indygreg, committed by ).
REPOSITORY
rHG Mercurial
CHANGES SINCE LAST UPDATE
https://phab.mercurial-scm.org/D5406?vs=12811&id=12818
REVISION DETAIL
https://phab.mercurial-scm.org/D5406
AFFECTED FILES
mercurial/help/internals/wireprotocolv2.txt
mercurial/wireprotov2server.py
tests/test-wireproto-command-filesdata.t
tests/test-wireproto-exchangev2.t
CHANGE DETAILS
diff --git a/tests/test-wireproto-exchangev2.t b/tests/test-wireproto-exchangev2.t
--- a/tests/test-wireproto-exchangev2.t
+++ b/tests/test-wireproto-exchangev2.t
@@ -1300,21 +1300,6 @@
#if reporevlogstore
$ hg -R client-linknode-2 debugrevlogindex dupe-file
- abort: revlog 'dupe-file' not found
- [255]
+ rev linkrev nodeid p1 p2
+ 0 2 2ed2a3912a0b 000000000000 000000000000
#endif
-
- $ hg -R client-linknode-2 verify
- checking changesets
- checking manifests
- crosschecking files in changesets and manifests
- checking files
- warning: revlog 'data/dupe-file.i' not in fncache!
- 2: empty or missing dupe-file
- dupe-file at 2: manifest refers to unknown revision 2ed2a3912a0b
- checked 3 changesets with 2 changes to 3 files
- 1 warnings encountered!
- hint: run "hg debugrebuildfncache" to recover from corrupt fncache
- 2 integrity errors encountered!
- (first damaged changeset appears to be 2)
- [1]
diff --git a/tests/test-wireproto-command-filesdata.t b/tests/test-wireproto-command-filesdata.t
--- a/tests/test-wireproto-command-filesdata.t
+++ b/tests/test-wireproto-command-filesdata.t
@@ -1267,8 +1267,6 @@
}
]
-TODO this is buggy
-
$ sendhttpv2peer << EOF
> command filesdata
> revisions eval:[{
@@ -1284,8 +1282,16 @@
sending filesdata command
response: gen[
{
- b'totalitems': 0,
- b'totalpaths': 0
+ b'totalitems': 1,
+ b'totalpaths': 1
+ },
+ {
+ b'path': b'dupe-file',
+ b'totalitems': 1
+ },
+ {
+ b'linknode': b'G\xfc0X\t\x11#,\xb2dg[@(\x19\xde\xdd\xf6\xc6\xf0',
+ b'node': b'.\xd2\xa3\x91*\x0b$P C\xea\xe8N\xe4\xb2y\xc1\x8b\x90\xdd'
}
]
diff --git a/mercurial/wireprotov2server.py b/mercurial/wireprotov2server.py
--- a/mercurial/wireprotov2server.py
+++ b/mercurial/wireprotov2server.py
@@ -1156,48 +1156,38 @@
# changeset, it should probably be allowed to access files data for that
# changeset.
- cl = repo.changelog
- clnode = cl.node
outgoing = resolvenodes(repo, revisions)
filematcher = makefilematcher(repo, pathfilter)
- # Figure out what needs to be emitted.
- changedpaths = set()
# path -> {fnode: linknode}
fnodes = collections.defaultdict(dict)
+ # We collect the set of relevant file revisions by iterating the changeset
+ # revisions and either walking the set of files recorded in the changeset
+ # or by walking the manifest at that revision. There is probably room for a
+ # storage-level API to request this data, as it can be expensive to compute
+ # and would benefit from caching or alternate storage from what revlogs
+ # provide.
for node in outgoing:
ctx = repo[node]
- changedpaths.update(ctx.files())
-
- changedpaths = sorted(p for p in changedpaths if filematcher(p))
+ mctx = ctx.manifestctx()
+ md = mctx.read()
- # If ancestors are known, we send file revisions having a linkrev in the
- # outgoing set of changeset revisions.
- if haveparents:
- outgoingclrevs = set(cl.rev(n) for n in outgoing)
-
- for path in changedpaths:
- try:
- store = getfilestore(repo, proto, path)
- except FileAccessError as e:
- raise error.WireprotoCommandError(e.msg, e.args)
+ if haveparents:
+ checkpaths = ctx.files()
+ else:
+ checkpaths = md.keys()
- for rev in store:
- linkrev = store.linkrev(rev)
-
- if linkrev in outgoingclrevs:
- fnodes[path].setdefault(store.node(rev), clnode(linkrev))
+ for path in checkpaths:
+ fnode = md[path]
- # If ancestors aren't known, we walk the manifests and send all
- # encountered file revisions.
- else:
- for node in outgoing:
- mctx = repo[node].manifestctx()
+ if path in fnodes and fnode in fnodes[path]:
+ continue
- for path, fnode in mctx.read().items():
- if filematcher(path):
- fnodes[path].setdefault(fnode, node)
+ if not filematcher(path):
+ continue
+
+ fnodes[path].setdefault(fnode, node)
yield {
b'totalpaths': len(fnodes),
diff --git a/mercurial/help/internals/wireprotocolv2.txt b/mercurial/help/internals/wireprotocolv2.txt
--- a/mercurial/help/internals/wireprotocolv2.txt
+++ b/mercurial/help/internals/wireprotocolv2.txt
@@ -426,8 +426,10 @@
has no file revisions data. This means that all referenced file revisions
in the queried set of changeset revisions will be sent.
-TODO we'll probably want a more complicated mechanism for the client to
-specify which ancestor revisions are known.
+TODO we want a more complicated mechanism for the client to specify which
+ancestor revisions are known. This is needed so intelligent deltas can be
+emitted and so updated linknodes can be sent if the client needs to adjust
+its linknodes for existing file nodes to older changeset revisions.
TODO we may want to make linknodes an array so multiple changesets can be
marked as introducing a file revision, since this can occur with e.g. hidden
changesets.
To: indygreg, #hg-reviewers
Cc: mjpieters, mercurial-devel
More information about the Mercurial-devel
mailing list