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