Mercurial > public > mercurial-scm > hg
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={ |