equal
deleted
inserted
replaced
587 |
587 |
588 # If a revision's full text is that much bigger than a base candidate full |
588 # If a revision's full text is that much bigger than a base candidate full |
589 # text's, it is very unlikely that it will produce a valid delta. We no longer |
589 # text's, it is very unlikely that it will produce a valid delta. We no longer |
590 # consider these candidates. |
590 # consider these candidates. |
591 LIMIT_BASE2TEXT = 500 |
591 LIMIT_BASE2TEXT = 500 |
|
592 |
|
593 ### stage of the search, used for debug and to select and to adjust some logic. |
|
594 # initial stage, next step is unknown |
|
595 _STAGE_UNSPECIFIED = "unspecified" |
|
596 # trying the cached delta |
|
597 _STAGE_CACHED = "cached" |
|
598 # trying delta based on parents |
|
599 _STAGE_PARENTS = "parents" |
|
600 # trying to build a valid snapshot of any level |
|
601 _STAGE_SNAPSHOT = "snapshot" |
|
602 # trying to build a delta based of the previous revision |
|
603 _STAGE_PREV = "prev" |
|
604 # trying to build a full snapshot |
|
605 _STAGE_FULL = "full" |
592 |
606 |
593 |
607 |
594 class _BaseDeltaSearch(abc.ABC): |
608 class _BaseDeltaSearch(abc.ABC): |
595 """perform the search of a good delta for a single revlog revision |
609 """perform the search of a good delta for a single revlog revision |
596 |
610 |
632 snapshot_cache = SnapshotCache() |
646 snapshot_cache = SnapshotCache() |
633 self.snapshot_cache = snapshot_cache |
647 self.snapshot_cache = snapshot_cache |
634 |
648 |
635 self.tested = {nullrev} |
649 self.tested = {nullrev} |
636 |
650 |
|
651 self.current_stage = _STAGE_UNSPECIFIED |
637 self.current_group = None |
652 self.current_group = None |
638 self._init_group() |
653 self._init_group() |
639 |
654 |
640 def is_good_delta_info(self, deltainfo): |
655 def is_good_delta_info(self, deltainfo): |
641 """Returns True if the given delta is good. |
656 """Returns True if the given delta is good. |
788 |
803 |
789 This search variant is to be used in case where we should not store delta. |
804 This search variant is to be used in case where we should not store delta. |
790 """ |
805 """ |
791 |
806 |
792 def _init_group(self): |
807 def _init_group(self): |
793 pass |
808 self.current_stage = _STAGE_FULL |
794 |
809 |
795 def next_group(self, good_delta=None): |
810 def next_group(self, good_delta=None): |
796 pass |
811 pass |
797 |
812 |
798 |
813 |
802 This search variant is to be used when the format does not allow for delta |
817 This search variant is to be used when the format does not allow for delta |
803 against arbitrary bases. |
818 against arbitrary bases. |
804 """ |
819 """ |
805 |
820 |
806 def _init_group(self): |
821 def _init_group(self): |
|
822 self.current_stage = _STAGE_PREV |
807 self.current_group = [self.target_rev - 1] |
823 self.current_group = [self.target_rev - 1] |
808 |
824 |
809 def next_group(self, good_delta=None): |
825 def next_group(self, good_delta=None): |
|
826 self.current_stage = _STAGE_FULL |
810 self.current_group = None |
827 self.current_group = None |
811 |
828 |
812 |
829 |
813 class _DeltaSearch(_BaseDeltaSearch): |
830 class _DeltaSearch(_BaseDeltaSearch): |
814 """Generic delta search variants |
831 """Generic delta search variants |
1024 self.cachedelta is not None |
1041 self.cachedelta is not None |
1025 and self.cachedelta[2] > DELTA_BASE_REUSE_NO |
1042 and self.cachedelta[2] > DELTA_BASE_REUSE_NO |
1026 ): |
1043 ): |
1027 # Assume what we received from the server is a good choice |
1044 # Assume what we received from the server is a good choice |
1028 # build delta will reuse the cache |
1045 # build delta will reuse the cache |
|
1046 self.current_stage = _STAGE_CACHED |
1029 good = yield (self.cachedelta[0],) |
1047 good = yield (self.cachedelta[0],) |
1030 if good is not None: |
1048 if good is not None: |
1031 yield None |
1049 yield None |
1032 return |
1050 return |
1033 groups = self._raw_groups() |
1051 groups = self._raw_groups() |
1037 break |
1055 break |
1038 |
1056 |
1039 # If sparse revlog is enabled, we can try to refine the available |
1057 # If sparse revlog is enabled, we can try to refine the available |
1040 # deltas |
1058 # deltas |
1041 if not self.revlog.delta_config.sparse_revlog: |
1059 if not self.revlog.delta_config.sparse_revlog: |
|
1060 self.current_stage = _STAGE_FULL |
1042 yield None |
1061 yield None |
1043 return |
1062 return |
1044 |
1063 |
1045 # if we have a refinable value, try to refine it |
1064 # if we have a refinable value, try to refine it |
1046 if ( |
1065 if ( |
1047 good is not None |
1066 good is not None |
1048 and good not in (self.p1, self.p2) |
1067 and good not in (self.p1, self.p2) |
1049 and self.revlog.issnapshot(good) |
1068 and self.revlog.issnapshot(good) |
1050 ): |
1069 ): |
|
1070 self.current_stage = _STAGE_SNAPSHOT |
1051 # refine snapshot down |
1071 # refine snapshot down |
1052 previous = None |
1072 previous = None |
1053 while previous != good: |
1073 while previous != good: |
1054 previous = good |
1074 previous = good |
1055 base = self.revlog.deltaparent(good) |
1075 base = self.revlog.deltaparent(good) |
1065 children = tuple( |
1085 children = tuple( |
1066 sorted(c for c in self.snapshot_cache.snapshots[good]) |
1086 sorted(c for c in self.snapshot_cache.snapshots[good]) |
1067 ) |
1087 ) |
1068 good = yield children |
1088 good = yield children |
1069 |
1089 |
|
1090 self.current_stage = _STAGE_FULL |
1070 yield None |
1091 yield None |
1071 |
1092 |
1072 def _raw_groups(self): |
1093 def _raw_groups(self): |
1073 """Provides group of revision to be tested as delta base |
1094 """Provides group of revision to be tested as delta base |
1074 |
1095 |
1082 deltachain = lambda rev: self.revlog._deltachain(rev)[0] |
1103 deltachain = lambda rev: self.revlog._deltachain(rev)[0] |
1083 |
1104 |
1084 # exclude already lazy tested base if any |
1105 # exclude already lazy tested base if any |
1085 parents = [p for p in (self.p1, self.p2) if p != nullrev] |
1106 parents = [p for p in (self.p1, self.p2) if p != nullrev] |
1086 |
1107 |
|
1108 self.current_stage = _STAGE_PARENTS |
1087 if ( |
1109 if ( |
1088 not self.revlog.delta_config.delta_both_parents |
1110 not self.revlog.delta_config.delta_both_parents |
1089 and len(parents) == 2 |
1111 and len(parents) == 2 |
1090 ): |
1112 ): |
1091 parents.sort() |
1113 parents.sort() |
1097 elif len(parents) > 0: |
1119 elif len(parents) > 0: |
1098 # Test all parents (1 or 2), and keep the best candidate |
1120 # Test all parents (1 or 2), and keep the best candidate |
1099 yield parents |
1121 yield parents |
1100 |
1122 |
1101 if sparse and parents: |
1123 if sparse and parents: |
|
1124 self.current_stage = _STAGE_SNAPSHOT |
1102 # See if we can use an existing snapshot in the parent chains to |
1125 # See if we can use an existing snapshot in the parent chains to |
1103 # use as a base for a new intermediate-snapshot |
1126 # use as a base for a new intermediate-snapshot |
1104 # |
1127 # |
1105 # search for snapshot in parents delta chain map: snapshot-level: |
1128 # search for snapshot in parents delta chain map: snapshot-level: |
1106 # snapshot-rev |
1129 # snapshot-rev |
1186 yield tuple(sorted(full)) |
1209 yield tuple(sorted(full)) |
1187 |
1210 |
1188 if not sparse: |
1211 if not sparse: |
1189 # other approach failed try against prev to hopefully save us a |
1212 # other approach failed try against prev to hopefully save us a |
1190 # fulltext. |
1213 # fulltext. |
|
1214 self.current_stage = _STAGE_PREV |
1191 yield (prev,) |
1215 yield (prev,) |
1192 |
1216 |
1193 |
1217 |
1194 class SnapshotCache: |
1218 class SnapshotCache: |
1195 __slots__ = ('snapshots', '_start_rev', '_end_rev') |
1219 __slots__ = ('snapshots', '_start_rev', '_end_rev') |