##// END OF EJS Templates
changegroup: move revchunk() from narrow...
Gregory Szorc -
r38922:66cf046e default
parent child Browse files
Show More
@@ -13,7 +13,6 b' from mercurial import ('
13 13 error,
14 14 extensions,
15 15 node,
16 pycompat,
17 16 util,
18 17 )
19 18
@@ -210,109 +209,3 b' def setup():'
210 209 if clnodes:
211 210 repo.hook('outgoing', node=node.hex(clnodes[0]), source=source)
212 211 extensions.wrapfunction(changegroup.cg1packer, 'generate', generate)
213
214 def revchunk(orig, self, revlog, rev, prev, linknode):
215 if not util.safehasattr(self, 'full_nodes'):
216 # not sending a narrow changegroup
217 for x in orig(self, revlog, rev, prev, linknode):
218 yield x
219 return
220 # build up some mapping information that's useful later. See
221 # the local() nested function below.
222 if not self.changelog_done:
223 self.clnode_to_rev[linknode] = rev
224 linkrev = rev
225 self.clrev_to_localrev[linkrev] = rev
226 else:
227 linkrev = self.clnode_to_rev[linknode]
228 self.clrev_to_localrev[linkrev] = rev
229 # This is a node to send in full, because the changeset it
230 # corresponds to was a full changeset.
231 if linknode in self.full_nodes:
232 for x in orig(self, revlog, rev, prev, linknode):
233 yield x
234 return
235 # At this point, a node can either be one we should skip or an
236 # ellipsis. If it's not an ellipsis, bail immediately.
237 if linkrev not in self.precomputed_ellipsis:
238 return
239 linkparents = self.precomputed_ellipsis[linkrev]
240 def local(clrev):
241 """Turn a changelog revnum into a local revnum.
242
243 The ellipsis dag is stored as revnums on the changelog,
244 but when we're producing ellipsis entries for
245 non-changelog revlogs, we need to turn those numbers into
246 something local. This does that for us, and during the
247 changelog sending phase will also expand the stored
248 mappings as needed.
249 """
250 if clrev == node.nullrev:
251 return node.nullrev
252 if not self.changelog_done:
253 # If we're doing the changelog, it's possible that we
254 # have a parent that is already on the client, and we
255 # need to store some extra mapping information so that
256 # our contained ellipsis nodes will be able to resolve
257 # their parents.
258 if clrev not in self.clrev_to_localrev:
259 clnode = revlog.node(clrev)
260 self.clnode_to_rev[clnode] = clrev
261 return clrev
262 # Walk the ellipsis-ized changelog breadth-first looking for a
263 # change that has been linked from the current revlog.
264 #
265 # For a flat manifest revlog only a single step should be necessary
266 # as all relevant changelog entries are relevant to the flat
267 # manifest.
268 #
269 # For a filelog or tree manifest dirlog however not every changelog
270 # entry will have been relevant, so we need to skip some changelog
271 # nodes even after ellipsis-izing.
272 walk = [clrev]
273 while walk:
274 p = walk[0]
275 walk = walk[1:]
276 if p in self.clrev_to_localrev:
277 return self.clrev_to_localrev[p]
278 elif p in self.full_nodes:
279 walk.extend([pp for pp in self._repo.changelog.parentrevs(p)
280 if pp != node.nullrev])
281 elif p in self.precomputed_ellipsis:
282 walk.extend([pp for pp in self.precomputed_ellipsis[p]
283 if pp != node.nullrev])
284 else:
285 # In this case, we've got an ellipsis with parents
286 # outside the current bundle (likely an
287 # incremental pull). We "know" that we can use the
288 # value of this same revlog at whatever revision
289 # is pointed to by linknode. "Know" is in scare
290 # quotes because I haven't done enough examination
291 # of edge cases to convince myself this is really
292 # a fact - it works for all the (admittedly
293 # thorough) cases in our testsuite, but I would be
294 # somewhat unsurprised to find a case in the wild
295 # where this breaks down a bit. That said, I don't
296 # know if it would hurt anything.
297 for i in pycompat.xrange(rev, 0, -1):
298 if revlog.linkrev(i) == clrev:
299 return i
300 # We failed to resolve a parent for this node, so
301 # we crash the changegroup construction.
302 raise error.Abort(
303 'unable to resolve parent while packing %r %r'
304 ' for changeset %r' % (revlog.indexfile, rev, clrev))
305 return node.nullrev
306
307 if not linkparents or (
308 revlog.parentrevs(rev) == (node.nullrev, node.nullrev)):
309 p1, p2 = node.nullrev, node.nullrev
310 elif len(linkparents) == 1:
311 p1, = sorted(local(p) for p in linkparents)
312 p2 = node.nullrev
313 else:
314 p1, p2 = sorted(local(p) for p in linkparents)
315 n = revlog.node(rev)
316 yield changegroup.ellipsisdata(
317 self, rev, revlog, p1, p2, revlog.revision(n), linknode)
318 extensions.wrapfunction(changegroup.cg1packer, 'revchunk', revchunk)
@@ -802,6 +802,14 b' class cg1packer(object):'
802 802 return prev
803 803
804 804 def revchunk(self, revlog, rev, prev, linknode):
805 if util.safehasattr(self, 'full_nodes'):
806 fn = self._revchunknarrow
807 else:
808 fn = self._revchunknormal
809
810 return fn(revlog, rev, prev, linknode)
811
812 def _revchunknormal(self, revlog, rev, prev, linknode):
805 813 node = revlog.node(rev)
806 814 p1, p2 = revlog.parentrevs(rev)
807 815 base = self.deltaparent(revlog, rev, p1, p2, prev)
@@ -831,6 +839,114 b' class cg1packer(object):'
831 839 yield chunkheader(l)
832 840 yield meta
833 841 yield delta
842
843 def _revchunknarrow(self, revlog, rev, prev, linknode):
844 # build up some mapping information that's useful later. See
845 # the local() nested function below.
846 if not self.changelog_done:
847 self.clnode_to_rev[linknode] = rev
848 linkrev = rev
849 self.clrev_to_localrev[linkrev] = rev
850 else:
851 linkrev = self.clnode_to_rev[linknode]
852 self.clrev_to_localrev[linkrev] = rev
853
854 # This is a node to send in full, because the changeset it
855 # corresponds to was a full changeset.
856 if linknode in self.full_nodes:
857 for x in self._revchunknormal(revlog, rev, prev, linknode):
858 yield x
859 return
860
861 # At this point, a node can either be one we should skip or an
862 # ellipsis. If it's not an ellipsis, bail immediately.
863 if linkrev not in self.precomputed_ellipsis:
864 return
865
866 linkparents = self.precomputed_ellipsis[linkrev]
867 def local(clrev):
868 """Turn a changelog revnum into a local revnum.
869
870 The ellipsis dag is stored as revnums on the changelog,
871 but when we're producing ellipsis entries for
872 non-changelog revlogs, we need to turn those numbers into
873 something local. This does that for us, and during the
874 changelog sending phase will also expand the stored
875 mappings as needed.
876 """
877 if clrev == nullrev:
878 return nullrev
879
880 if not self.changelog_done:
881 # If we're doing the changelog, it's possible that we
882 # have a parent that is already on the client, and we
883 # need to store some extra mapping information so that
884 # our contained ellipsis nodes will be able to resolve
885 # their parents.
886 if clrev not in self.clrev_to_localrev:
887 clnode = revlog.node(clrev)
888 self.clnode_to_rev[clnode] = clrev
889 return clrev
890
891 # Walk the ellipsis-ized changelog breadth-first looking for a
892 # change that has been linked from the current revlog.
893 #
894 # For a flat manifest revlog only a single step should be necessary
895 # as all relevant changelog entries are relevant to the flat
896 # manifest.
897 #
898 # For a filelog or tree manifest dirlog however not every changelog
899 # entry will have been relevant, so we need to skip some changelog
900 # nodes even after ellipsis-izing.
901 walk = [clrev]
902 while walk:
903 p = walk[0]
904 walk = walk[1:]
905 if p in self.clrev_to_localrev:
906 return self.clrev_to_localrev[p]
907 elif p in self.full_nodes:
908 walk.extend([pp for pp in self._repo.changelog.parentrevs(p)
909 if pp != nullrev])
910 elif p in self.precomputed_ellipsis:
911 walk.extend([pp for pp in self.precomputed_ellipsis[p]
912 if pp != nullrev])
913 else:
914 # In this case, we've got an ellipsis with parents
915 # outside the current bundle (likely an
916 # incremental pull). We "know" that we can use the
917 # value of this same revlog at whatever revision
918 # is pointed to by linknode. "Know" is in scare
919 # quotes because I haven't done enough examination
920 # of edge cases to convince myself this is really
921 # a fact - it works for all the (admittedly
922 # thorough) cases in our testsuite, but I would be
923 # somewhat unsurprised to find a case in the wild
924 # where this breaks down a bit. That said, I don't
925 # know if it would hurt anything.
926 for i in pycompat.xrange(rev, 0, -1):
927 if revlog.linkrev(i) == clrev:
928 return i
929 # We failed to resolve a parent for this node, so
930 # we crash the changegroup construction.
931 raise error.Abort(
932 'unable to resolve parent while packing %r %r'
933 ' for changeset %r' % (revlog.indexfile, rev, clrev))
934
935 return nullrev
936
937 if not linkparents or (
938 revlog.parentrevs(rev) == (nullrev, nullrev)):
939 p1, p2 = nullrev, nullrev
940 elif len(linkparents) == 1:
941 p1, = sorted(local(p) for p in linkparents)
942 p2 = nullrev
943 else:
944 p1, p2 = sorted(local(p) for p in linkparents)
945 n = revlog.node(rev)
946
947 yield ellipsisdata(
948 self, rev, revlog, p1, p2, revlog.revision(n), linknode)
949
834 950 def builddeltaheader(self, node, p1n, p2n, basenode, linknode, flags):
835 951 # do nothing with basenode, it is implicitly the previous one in HG10
836 952 # do nothing with flags, it is implicitly 0 for cg1 and cg2
General Comments 0
You need to be logged in to leave comments. Login now