Patchwork D5405: wireprotov2: send linknodes to emitfilerevisions()

login
register
mail settings
Submitter phabricator
Date Dec. 10, 2018, 9:25 p.m.
Message ID <d1399de5c232283cb5cd005371a8e426@localhost.localdomain>
Download mbox | patch
Permalink /patch/37100/
State Not Applicable
Headers show

Comments

phabricator - Dec. 10, 2018, 9:25 p.m.
This revision was automatically updated to reflect the committed changes.
Closed by commit rHG3ed77780f4a6: wireprotov2: send linknodes to emitfilerevisions() (authored by indygreg, committed by ).

REPOSITORY
  rHG Mercurial

CHANGES SINCE LAST UPDATE
  https://phab.mercurial-scm.org/D5405?vs=12810&id=12816

REVISION DETAIL
  https://phab.mercurial-scm.org/D5405

AFFECTED FILES
  mercurial/wireprotov2server.py
  tests/test-wireproto-command-filesdata.t
  tests/test-wireproto-exchangev2-shallow.t

CHANGE DETAILS




To: indygreg, #hg-reviewers
Cc: mercurial-devel

Patch

diff --git a/tests/test-wireproto-exchangev2-shallow.t b/tests/test-wireproto-exchangev2-shallow.t
--- a/tests/test-wireproto-exchangev2-shallow.t
+++ b/tests/test-wireproto-exchangev2-shallow.t
@@ -196,34 +196,34 @@ 
      node = I\x1d\xa1\xbb\x89\xeax\xc0\xc0\xa2s[\x16\xce}\x93\x1d\xc8\xe2\r (esc)
     p1rev = -1
     p2rev = -1
-  linkrev = 4
+  linkrev = 5
     flags = 2
   
        id = 4
      path = dir0/d
    revnum = 0
      node = S\x82\x06\xdc\x97\x1eR\x15@\xd6\x84:\xbf\xe6\xd1`2\xf6\xd4& (esc)
     p1rev = -1
     p2rev = -1
-  linkrev = 1
+  linkrev = 5
     flags = 0
   
        id = 5
      path = dir1/e
    revnum = 0
      node = ]\xf3\xac\xd8\xd0\xc7\xfaP\x98\xd0'\x9a\x044\xc3\x02\x9e+x\xe1 (esc)
     p1rev = -1
     p2rev = -1
-  linkrev = 4
+  linkrev = 5
     flags = 2
   
        id = 6
      path = dir1/f
    revnum = 0
      node = (\xc7v\xae\x08\xd0\xd5^\xb4\x06H\xb4\x01\xb9\x0f\xf5DH4\x8e (esc)
     p1rev = -1
     p2rev = -1
-  linkrev = 4
+  linkrev = 5
     flags = 2
 
 Test a shallow clone with only some files
@@ -342,16 +342,16 @@ 
      node = I\x1d\xa1\xbb\x89\xeax\xc0\xc0\xa2s[\x16\xce}\x93\x1d\xc8\xe2\r (esc)
     p1rev = -1
     p2rev = -1
-  linkrev = 4
+  linkrev = 5
     flags = 2
   
        id = 2
      path = dir0/d
    revnum = 0
      node = S\x82\x06\xdc\x97\x1eR\x15@\xd6\x84:\xbf\xe6\xd1`2\xf6\xd4& (esc)
     p1rev = -1
     p2rev = -1
-  linkrev = 1
+  linkrev = 5
     flags = 0
 
 Cloning an old revision with depth=1 works
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
@@ -1239,7 +1239,6 @@ 
 
 Request for changeset where recorded linknode isn't in DAG ancestry will get
 rewritten accordingly
-TODO this is buggy
 
   $ sendhttpv2peer << EOF
   > command filesdata
@@ -1263,7 +1262,7 @@ 
       b'totalitems': 1
     },
     {
-      b'linknode': b'\xb1l\xce)g\xc1t\x9e\xf4\xf4\xe3\x08j\x80l\xfb\xad\x8a:\xf7',
+      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
@@ -984,9 +984,7 @@ 
 
     return fl
 
-def emitfilerevisions(repo, path, revisions, fields):
-    clnode = repo.changelog.node
-
+def emitfilerevisions(repo, path, revisions, linknodes, fields):
     for revision in revisions:
         d = {
             b'node': revision.node,
@@ -996,13 +994,7 @@ 
             d[b'parents'] = [revision.p1node, revision.p2node]
 
         if b'linknode' in fields:
-            # TODO by creating the filectx against a specific file revision
-            # instead of changeset, linkrev() is always used. This is wrong for
-            # cases where linkrev() may refer to a hidden changeset. We need an
-            # API for performing linkrev adjustment that takes this into
-            # account.
-            fctx = repo.filectx(path, fileid=revision.node)
-            d[b'linknode'] = clnode(fctx.introrev())
+            d[b'linknode'] = linknodes[revision.node]
 
         followingmeta = []
         followingdata = []
@@ -1086,23 +1078,34 @@ 
     except FileAccessError as e:
         raise error.WireprotoCommandError(e.msg, e.args)
 
+    clnode = repo.changelog.node
+    linknodes = {}
+
     # Validate requested nodes.
     for node in nodes:
         try:
             store.rev(node)
         except error.LookupError:
             raise error.WireprotoCommandError('unknown file node: %s',
                                               (hex(node),))
 
+        # TODO by creating the filectx against a specific file revision
+        # instead of changeset, linkrev() is always used. This is wrong for
+        # cases where linkrev() may refer to a hidden changeset. But since this
+        # API doesn't know anything about changesets, we're not sure how to
+        # disambiguate the linknode. Perhaps we should delete this API?
+        fctx = repo.filectx(path, fileid=node)
+        linknodes[node] = clnode(fctx.introrev())
+
     revisions = store.emitrevisions(nodes,
                                     revisiondata=b'revision' in fields,
                                     assumehaveparentrevisions=haveparents)
 
     yield {
         b'totalitems': len(nodes),
     }
 
-    for o in emitfilerevisions(repo, path, revisions, fields):
+    for o in emitfilerevisions(repo, path, revisions, linknodes, fields):
         yield o
 
 def filesdatacapabilities(repo, proto):
@@ -1154,12 +1157,14 @@ 
     # changeset.
 
     cl = repo.changelog
+    clnode = cl.node
     outgoing = resolvenodes(repo, revisions)
     filematcher = makefilematcher(repo, pathfilter)
 
     # Figure out what needs to be emitted.
     changedpaths = set()
-    fnodes = collections.defaultdict(set)
+    # path -> {fnode: linknode}
+    fnodes = collections.defaultdict(dict)
 
     for node in outgoing:
         ctx = repo[node]
@@ -1182,7 +1187,7 @@ 
                 linkrev = store.linkrev(rev)
 
                 if linkrev in outgoingclrevs:
-                    fnodes[path].add(store.node(rev))
+                    fnodes[path].setdefault(store.node(rev), clnode(linkrev))
 
     # If ancestors aren't known, we walk the manifests and send all
     # encountered file revisions.
@@ -1192,7 +1197,7 @@ 
 
             for path, fnode in mctx.read().items():
                 if filematcher(path):
-                    fnodes[path].add(fnode)
+                    fnodes[path].setdefault(fnode, node)
 
     yield {
         b'totalpaths': len(fnodes),
@@ -1210,11 +1215,11 @@ 
             b'totalitems': len(filenodes),
         }
 
-        revisions = store.emitrevisions(filenodes,
+        revisions = store.emitrevisions(filenodes.keys(),
                                         revisiondata=b'revision' in fields,
                                         assumehaveparentrevisions=haveparents)
 
-        for o in emitfilerevisions(repo, path, revisions, fields):
+        for o in emitfilerevisions(repo, path, revisions, filenodes, fields):
             yield o
 
 @wireprotocommand(