Show More
@@ -13,7 +13,6 b' from mercurial import (' | |||||
13 | error, |
|
13 | error, | |
14 | extensions, |
|
14 | extensions, | |
15 | node, |
|
15 | node, | |
16 | pycompat, |
|
|||
17 | util, |
|
16 | util, | |
18 | ) |
|
17 | ) | |
19 |
|
18 | |||
@@ -210,109 +209,3 b' def setup():' | |||||
210 | if clnodes: |
|
209 | if clnodes: | |
211 | repo.hook('outgoing', node=node.hex(clnodes[0]), source=source) |
|
210 | repo.hook('outgoing', node=node.hex(clnodes[0]), source=source) | |
212 | extensions.wrapfunction(changegroup.cg1packer, 'generate', generate) |
|
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 | return prev |
|
802 | return prev | |
803 |
|
803 | |||
804 | def revchunk(self, revlog, rev, prev, linknode): |
|
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 | node = revlog.node(rev) |
|
813 | node = revlog.node(rev) | |
806 | p1, p2 = revlog.parentrevs(rev) |
|
814 | p1, p2 = revlog.parentrevs(rev) | |
807 | base = self.deltaparent(revlog, rev, p1, p2, prev) |
|
815 | base = self.deltaparent(revlog, rev, p1, p2, prev) | |
@@ -831,6 +839,114 b' class cg1packer(object):' | |||||
831 | yield chunkheader(l) |
|
839 | yield chunkheader(l) | |
832 | yield meta |
|
840 | yield meta | |
833 | yield delta |
|
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 | def builddeltaheader(self, node, p1n, p2n, basenode, linknode, flags): |
|
950 | def builddeltaheader(self, node, p1n, p2n, basenode, linknode, flags): | |
835 | # do nothing with basenode, it is implicitly the previous one in HG10 |
|
951 | # do nothing with basenode, it is implicitly the previous one in HG10 | |
836 | # do nothing with flags, it is implicitly 0 for cg1 and cg2 |
|
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