mercurial/wireprotov2server.py
changeset 40924 08cfa77d7288
parent 40923 3ed77780f4a6
child 41216 5cc5a5561c3f
equal deleted inserted replaced
40923:3ed77780f4a6 40924:08cfa77d7288
  1154     # is a race between a client making a push that obsoletes a changeset and
  1154     # is a race between a client making a push that obsoletes a changeset and
  1155     # another client fetching files data for that changeset. If a client has a
  1155     # another client fetching files data for that changeset. If a client has a
  1156     # changeset, it should probably be allowed to access files data for that
  1156     # changeset, it should probably be allowed to access files data for that
  1157     # changeset.
  1157     # changeset.
  1158 
  1158 
  1159     cl = repo.changelog
       
  1160     clnode = cl.node
       
  1161     outgoing = resolvenodes(repo, revisions)
  1159     outgoing = resolvenodes(repo, revisions)
  1162     filematcher = makefilematcher(repo, pathfilter)
  1160     filematcher = makefilematcher(repo, pathfilter)
  1163 
  1161 
  1164     # Figure out what needs to be emitted.
       
  1165     changedpaths = set()
       
  1166     # path -> {fnode: linknode}
  1162     # path -> {fnode: linknode}
  1167     fnodes = collections.defaultdict(dict)
  1163     fnodes = collections.defaultdict(dict)
  1168 
  1164 
       
  1165     # We collect the set of relevant file revisions by iterating the changeset
       
  1166     # revisions and either walking the set of files recorded in the changeset
       
  1167     # or by walking the manifest at that revision. There is probably room for a
       
  1168     # storage-level API to request this data, as it can be expensive to compute
       
  1169     # and would benefit from caching or alternate storage from what revlogs
       
  1170     # provide.
  1169     for node in outgoing:
  1171     for node in outgoing:
  1170         ctx = repo[node]
  1172         ctx = repo[node]
  1171         changedpaths.update(ctx.files())
  1173         mctx = ctx.manifestctx()
  1172 
  1174         md = mctx.read()
  1173     changedpaths = sorted(p for p in changedpaths if filematcher(p))
  1175 
  1174 
  1176         if haveparents:
  1175     # If ancestors are known, we send file revisions having a linkrev in the
  1177             checkpaths = ctx.files()
  1176     # outgoing set of changeset revisions.
  1178         else:
  1177     if haveparents:
  1179             checkpaths = md.keys()
  1178         outgoingclrevs = set(cl.rev(n) for n in outgoing)
  1180 
  1179 
  1181         for path in checkpaths:
  1180         for path in changedpaths:
  1182             fnode = md[path]
  1181             try:
  1183 
  1182                 store = getfilestore(repo, proto, path)
  1184             if path in fnodes and fnode in fnodes[path]:
  1183             except FileAccessError as e:
  1185                 continue
  1184                 raise error.WireprotoCommandError(e.msg, e.args)
  1186 
  1185 
  1187             if not filematcher(path):
  1186             for rev in store:
  1188                 continue
  1187                 linkrev = store.linkrev(rev)
  1189 
  1188 
  1190             fnodes[path].setdefault(fnode, node)
  1189                 if linkrev in outgoingclrevs:
       
  1190                     fnodes[path].setdefault(store.node(rev), clnode(linkrev))
       
  1191 
       
  1192     # If ancestors aren't known, we walk the manifests and send all
       
  1193     # encountered file revisions.
       
  1194     else:
       
  1195         for node in outgoing:
       
  1196             mctx = repo[node].manifestctx()
       
  1197 
       
  1198             for path, fnode in mctx.read().items():
       
  1199                 if filematcher(path):
       
  1200                     fnodes[path].setdefault(fnode, node)
       
  1201 
  1191 
  1202     yield {
  1192     yield {
  1203         b'totalpaths': len(fnodes),
  1193         b'totalpaths': len(fnodes),
  1204         b'totalitems': sum(len(v) for v in fnodes.values())
  1194         b'totalitems': sum(len(v) for v in fnodes.values())
  1205     }
  1195     }