comparison mercurial/wireprotov2server.py @ 40391:abbd077965c0

wireprotov2: support exposing linknode of file revisions When supporting shallow file storage, clients may fetch file revisions by changeset. But they may not readily know which changeset introduced a specific file revision. The "linknode" is used to record which changeset introduces which file revision. This commit teaches the "filedata" and "filesdata" wire protocol commands to expose the linknode for file revisions. The implementation is likely wrong when hidden changesets are in play, since the linknode may refer to a hidden changeset. We can deal with this problem later. Differential Revision: https://phab.mercurial-scm.org/D5167
author Gregory Szorc <gregory.szorc@gmail.com>
date Fri, 19 Oct 2018 15:38:25 +0200
parents ed55a0077490
children f83cea7f54d7
comparison
equal deleted inserted replaced
40390:7e3b6c4f01a2 40391:abbd077965c0
982 if not len(fl): 982 if not len(fl):
983 raise FileAccessError(path, 'unknown file: %s', (path,)) 983 raise FileAccessError(path, 'unknown file: %s', (path,))
984 984
985 return fl 985 return fl
986 986
987 def emitfilerevisions(revisions, fields): 987 def emitfilerevisions(repo, path, revisions, fields):
988 clnode = repo.changelog.node
989
988 for revision in revisions: 990 for revision in revisions:
989 d = { 991 d = {
990 b'node': revision.node, 992 b'node': revision.node,
991 } 993 }
992 994
993 if b'parents' in fields: 995 if b'parents' in fields:
994 d[b'parents'] = [revision.p1node, revision.p2node] 996 d[b'parents'] = [revision.p1node, revision.p2node]
997
998 if b'linknode' in fields:
999 # TODO by creating the filectx against a specific file revision
1000 # instead of changeset, linkrev() is always used. This is wrong for
1001 # cases where linkrev() may refer to a hidden changeset. We need an
1002 # API for performing linkrev adjustment that takes this into
1003 # account.
1004 fctx = repo.filectx(path, fileid=revision.node)
1005 d[b'linknode'] = clnode(fctx.introrev())
995 1006
996 followingmeta = [] 1007 followingmeta = []
997 followingdata = [] 1008 followingdata = []
998 1009
999 if b'revision' in fields: 1010 if b'revision' in fields:
1050 }, 1061 },
1051 'fields': { 1062 'fields': {
1052 'type': 'set', 1063 'type': 'set',
1053 'default': set, 1064 'default': set,
1054 'example': {b'parents', b'revision'}, 1065 'example': {b'parents', b'revision'},
1055 'validvalues': {b'parents', b'revision'}, 1066 'validvalues': {b'parents', b'revision', b'linknode'},
1056 }, 1067 },
1057 'path': { 1068 'path': {
1058 'type': 'bytes', 1069 'type': 'bytes',
1059 'example': b'foo.txt', 1070 'example': b'foo.txt',
1060 } 1071 }
1089 1100
1090 yield { 1101 yield {
1091 b'totalitems': len(nodes), 1102 b'totalitems': len(nodes),
1092 } 1103 }
1093 1104
1094 for o in emitfilerevisions(revisions, fields): 1105 for o in emitfilerevisions(repo, path, revisions, fields):
1095 yield o 1106 yield o
1096 1107
1097 def filesdatacapabilities(repo, proto): 1108 def filesdatacapabilities(repo, proto):
1098 batchsize = repo.ui.configint( 1109 batchsize = repo.ui.configint(
1099 b'experimental', b'server.filesdata.recommended-batch-size') 1110 b'experimental', b'server.filesdata.recommended-batch-size')
1111 }, 1122 },
1112 'fields': { 1123 'fields': {
1113 'type': 'set', 1124 'type': 'set',
1114 'default': set, 1125 'default': set,
1115 'example': {b'parents', b'revision'}, 1126 'example': {b'parents', b'revision'},
1116 'validvalues': {b'firstchangeset', b'parents', b'revision'}, 1127 'validvalues': {b'firstchangeset', b'linknode', b'parents',
1128 b'revision'},
1117 }, 1129 },
1118 'pathfilter': { 1130 'pathfilter': {
1119 'type': 'dict', 1131 'type': 'dict',
1120 'default': lambda: None, 1132 'default': lambda: None,
1121 'example': {b'include': [b'path:tests']}, 1133 'example': {b'include': [b'path:tests']},
1200 1212
1201 revisions = store.emitrevisions(filenodes, 1213 revisions = store.emitrevisions(filenodes,
1202 revisiondata=b'revision' in fields, 1214 revisiondata=b'revision' in fields,
1203 assumehaveparentrevisions=haveparents) 1215 assumehaveparentrevisions=haveparents)
1204 1216
1205 for o in emitfilerevisions(revisions, fields): 1217 for o in emitfilerevisions(repo, path, revisions, fields):
1206 yield o 1218 yield o
1207 1219
1208 @wireprotocommand( 1220 @wireprotocommand(
1209 'heads', 1221 'heads',
1210 args={ 1222 args={