Show More
@@ -715,14 +715,100 b' class cgpacker(object):' | |||
|
715 | 715 | yield chunk |
|
716 | 716 | |
|
717 | 717 | def generate(self, commonrevs, clnodes, fastpathlinkrev, source): |
|
718 |
|
|
|
718 | """Yield a sequence of changegroup byte chunks.""" | |
|
719 | ||
|
719 | 720 | repo = self._repo |
|
720 | 721 | cl = repo.changelog |
|
721 | 722 | |
|
723 | self._verbosenote(_('uncompressed size of bundle content:\n')) | |
|
724 | size = 0 | |
|
725 | ||
|
726 | clstate, chunks = self._generatechangelog(cl, clnodes) | |
|
727 | for chunk in chunks: | |
|
728 | size += len(chunk) | |
|
729 | yield chunk | |
|
730 | ||
|
731 | self._verbosenote(_('%8.i (changelog)\n') % size) | |
|
732 | ||
|
733 | clrevorder = clstate['clrevorder'] | |
|
734 | mfs = clstate['mfs'] | |
|
735 | changedfiles = clstate['changedfiles'] | |
|
736 | ||
|
737 | # We need to make sure that the linkrev in the changegroup refers to | |
|
738 | # the first changeset that introduced the manifest or file revision. | |
|
739 | # The fastpath is usually safer than the slowpath, because the filelogs | |
|
740 | # are walked in revlog order. | |
|
741 | # | |
|
742 | # When taking the slowpath with reorder=None and the manifest revlog | |
|
743 | # uses generaldelta, the manifest may be walked in the "wrong" order. | |
|
744 | # Without 'clrevorder', we would get an incorrect linkrev (see fix in | |
|
745 | # cc0ff93d0c0c). | |
|
746 | # | |
|
747 | # When taking the fastpath, we are only vulnerable to reordering | |
|
748 | # of the changelog itself. The changelog never uses generaldelta, so | |
|
749 | # it is only reordered when reorder=True. To handle this case, we | |
|
750 | # simply take the slowpath, which already has the 'clrevorder' logic. | |
|
751 | # This was also fixed in cc0ff93d0c0c. | |
|
752 | fastpathlinkrev = fastpathlinkrev and not self._reorder | |
|
753 | # Treemanifests don't work correctly with fastpathlinkrev | |
|
754 | # either, because we don't discover which directory nodes to | |
|
755 | # send along with files. This could probably be fixed. | |
|
756 | fastpathlinkrev = fastpathlinkrev and ( | |
|
757 | 'treemanifest' not in repo.requirements) | |
|
758 | ||
|
759 | fnodes = {} # needed file nodes | |
|
760 | ||
|
761 | for chunk in self.generatemanifests(commonrevs, clrevorder, | |
|
762 | fastpathlinkrev, mfs, fnodes, source): | |
|
763 | yield chunk | |
|
764 | ||
|
765 | if self._ellipses: | |
|
766 | mfdicts = None | |
|
767 | if self._isshallow: | |
|
768 | mfdicts = [(self._repo.manifestlog[n].read(), lr) | |
|
769 | for (n, lr) in mfs.iteritems()] | |
|
770 | ||
|
771 | mfs.clear() | |
|
772 | clrevs = set(cl.rev(x) for x in clnodes) | |
|
773 | ||
|
774 | if not fastpathlinkrev: | |
|
775 | def linknodes(unused, fname): | |
|
776 | return fnodes.get(fname, {}) | |
|
777 | else: | |
|
778 | cln = cl.node | |
|
779 | def linknodes(filerevlog, fname): | |
|
780 | llr = filerevlog.linkrev | |
|
781 | fln = filerevlog.node | |
|
782 | revs = ((r, llr(r)) for r in filerevlog) | |
|
783 | return dict((fln(r), cln(lr)) for r, lr in revs if lr in clrevs) | |
|
784 | ||
|
785 | if self._ellipses: | |
|
786 | # We need to pass the mfdicts variable down into | |
|
787 | # generatefiles(), but more than one command might have | |
|
788 | # wrapped generatefiles so we can't modify the function | |
|
789 | # signature. Instead, we pass the data to ourselves using an | |
|
790 | # instance attribute. I'm sorry. | |
|
791 | self._mfdicts = mfdicts | |
|
792 | ||
|
793 | for chunk in self.generatefiles(changedfiles, linknodes, commonrevs, | |
|
794 | source): | |
|
795 | yield chunk | |
|
796 | ||
|
797 | yield self._close() | |
|
798 | ||
|
799 | if clnodes: | |
|
800 | repo.hook('outgoing', node=hex(clnodes[0]), source=source) | |
|
801 | ||
|
802 | def _generatechangelog(self, cl, nodes): | |
|
803 | """Generate data for changelog chunks. | |
|
804 | ||
|
805 | Returns a 2-tuple of a dict containing state and an iterable of | |
|
806 | byte chunks. The state will not be fully populated until the | |
|
807 | chunk stream has been fully consumed. | |
|
808 | """ | |
|
722 | 809 | clrevorder = {} |
|
723 | 810 | mfs = {} # needed manifests |
|
724 | fnodes = {} # needed file nodes | |
|
725 | mfl = repo.manifestlog | |
|
811 | mfl = self._repo.manifestlog | |
|
726 | 812 | # TODO violates storage abstraction. |
|
727 | 813 | mfrevlog = mfl._revlog |
|
728 | 814 | changedfiles = set() |
@@ -768,75 +854,15 b' class cgpacker(object):' | |||
|
768 | 854 | |
|
769 | 855 | return x |
|
770 | 856 | |
|
771 | self._verbosenote(_('uncompressed size of bundle content:\n')) | |
|
772 | size = 0 | |
|
773 | for chunk in self.group(clnodes, cl, lookupcl, units=_('changesets')): | |
|
774 | size += len(chunk) | |
|
775 | yield chunk | |
|
776 | self._verbosenote(_('%8.i (changelog)\n') % size) | |
|
777 | ||
|
778 | # We need to make sure that the linkrev in the changegroup refers to | |
|
779 | # the first changeset that introduced the manifest or file revision. | |
|
780 | # The fastpath is usually safer than the slowpath, because the filelogs | |
|
781 | # are walked in revlog order. | |
|
782 | # | |
|
783 | # When taking the slowpath with reorder=None and the manifest revlog | |
|
784 | # uses generaldelta, the manifest may be walked in the "wrong" order. | |
|
785 | # Without 'clrevorder', we would get an incorrect linkrev (see fix in | |
|
786 | # cc0ff93d0c0c). | |
|
787 | # | |
|
788 | # When taking the fastpath, we are only vulnerable to reordering | |
|
789 | # of the changelog itself. The changelog never uses generaldelta, so | |
|
790 | # it is only reordered when reorder=True. To handle this case, we | |
|
791 | # simply take the slowpath, which already has the 'clrevorder' logic. | |
|
792 | # This was also fixed in cc0ff93d0c0c. | |
|
793 | fastpathlinkrev = fastpathlinkrev and not self._reorder | |
|
794 | # Treemanifests don't work correctly with fastpathlinkrev | |
|
795 | # either, because we don't discover which directory nodes to | |
|
796 | # send along with files. This could probably be fixed. | |
|
797 | fastpathlinkrev = fastpathlinkrev and ( | |
|
798 | 'treemanifest' not in repo.requirements) | |
|
799 | ||
|
800 | for chunk in self.generatemanifests(commonrevs, clrevorder, | |
|
801 | fastpathlinkrev, mfs, fnodes, source): | |
|
802 | yield chunk | |
|
857 | state = { | |
|
858 | 'clrevorder': clrevorder, | |
|
859 | 'mfs': mfs, | |
|
860 | 'changedfiles': changedfiles, | |
|
861 | } | |
|
803 | 862 | |
|
804 | if self._ellipses: | |
|
805 | mfdicts = None | |
|
806 | if self._isshallow: | |
|
807 | mfdicts = [(self._repo.manifestlog[n].read(), lr) | |
|
808 | for (n, lr) in mfs.iteritems()] | |
|
809 | ||
|
810 | mfs.clear() | |
|
811 | clrevs = set(cl.rev(x) for x in clnodes) | |
|
863 | gen = self.group(nodes, cl, lookupcl, units=_('changesets')) | |
|
812 | 864 | |
|
813 | if not fastpathlinkrev: | |
|
814 | def linknodes(unused, fname): | |
|
815 | return fnodes.get(fname, {}) | |
|
816 | else: | |
|
817 | cln = cl.node | |
|
818 | def linknodes(filerevlog, fname): | |
|
819 | llr = filerevlog.linkrev | |
|
820 | fln = filerevlog.node | |
|
821 | revs = ((r, llr(r)) for r in filerevlog) | |
|
822 | return dict((fln(r), cln(lr)) for r, lr in revs if lr in clrevs) | |
|
823 | ||
|
824 | if self._ellipses: | |
|
825 | # We need to pass the mfdicts variable down into | |
|
826 | # generatefiles(), but more than one command might have | |
|
827 | # wrapped generatefiles so we can't modify the function | |
|
828 | # signature. Instead, we pass the data to ourselves using an | |
|
829 | # instance attribute. I'm sorry. | |
|
830 | self._mfdicts = mfdicts | |
|
831 | ||
|
832 | for chunk in self.generatefiles(changedfiles, linknodes, commonrevs, | |
|
833 | source): | |
|
834 | yield chunk | |
|
835 | ||
|
836 | yield self._close() | |
|
837 | ||
|
838 | if clnodes: | |
|
839 | repo.hook('outgoing', node=hex(clnodes[0]), source=source) | |
|
865 | return state, gen | |
|
840 | 866 | |
|
841 | 867 | def generatemanifests(self, commonrevs, clrevorder, fastpathlinkrev, mfs, |
|
842 | 868 | fnodes, source): |
General Comments 0
You need to be logged in to leave comments.
Login now