Show More
@@ -521,8 +521,8 b' class revisiondelta(object):' | |||||
521 |
|
521 | |||
522 | class cg1packer(object): |
|
522 | class cg1packer(object): | |
523 | def __init__(self, repo, filematcher, version, allowreorder, |
|
523 | def __init__(self, repo, filematcher, version, allowreorder, | |
524 |
builddeltaheader, manifestsend, |
|
524 | useprevdelta, builddeltaheader, manifestsend, | |
525 | bundlecaps=None): |
|
525 | sendtreemanifests, bundlecaps=None): | |
526 | """Given a source repo, construct a bundler. |
|
526 | """Given a source repo, construct a bundler. | |
527 |
|
527 | |||
528 | filematcher is a matcher that matches on files to include in the |
|
528 | filematcher is a matcher that matches on files to include in the | |
@@ -532,6 +532,9 b' class cg1packer(object):' | |||||
532 | This value is used when ``bundle.reorder`` is ``auto`` or isn't |
|
532 | This value is used when ``bundle.reorder`` is ``auto`` or isn't | |
533 | set. |
|
533 | set. | |
534 |
|
534 | |||
|
535 | useprevdelta controls whether revisions should always delta against | |||
|
536 | the previous revision in the changegroup. | |||
|
537 | ||||
535 | builddeltaheader is a callable that constructs the header for a group |
|
538 | builddeltaheader is a callable that constructs the header for a group | |
536 | delta. |
|
539 | delta. | |
537 |
|
540 | |||
@@ -548,6 +551,7 b' class cg1packer(object):' | |||||
548 | self._filematcher = filematcher |
|
551 | self._filematcher = filematcher | |
549 |
|
552 | |||
550 | self.version = version |
|
553 | self.version = version | |
|
554 | self._useprevdelta = useprevdelta | |||
551 | self._builddeltaheader = builddeltaheader |
|
555 | self._builddeltaheader = builddeltaheader | |
552 | self._manifestsend = manifestsend |
|
556 | self._manifestsend = manifestsend | |
553 | self._sendtreemanifests = sendtreemanifests |
|
557 | self._sendtreemanifests = sendtreemanifests | |
@@ -950,9 +954,51 b' class cg1packer(object):' | |||||
950 | progress.complete() |
|
954 | progress.complete() | |
951 |
|
955 | |||
952 | def deltaparent(self, store, rev, p1, p2, prev): |
|
956 | def deltaparent(self, store, rev, p1, p2, prev): | |
953 | if not store.candelta(prev, rev): |
|
957 | if self._useprevdelta: | |
954 | raise error.ProgrammingError('cg1 should not be used in this case') |
|
958 | if not store.candelta(prev, rev): | |
955 | return prev |
|
959 | raise error.ProgrammingError( | |
|
960 | 'cg1 should not be used in this case') | |||
|
961 | return prev | |||
|
962 | ||||
|
963 | # Narrow ellipses mode. | |||
|
964 | if util.safehasattr(self, 'full_nodes'): | |||
|
965 | # TODO: send better deltas when in narrow mode. | |||
|
966 | # | |||
|
967 | # changegroup.group() loops over revisions to send, | |||
|
968 | # including revisions we'll skip. What this means is that | |||
|
969 | # `prev` will be a potentially useless delta base for all | |||
|
970 | # ellipsis nodes, as the client likely won't have it. In | |||
|
971 | # the future we should do bookkeeping about which nodes | |||
|
972 | # have been sent to the client, and try to be | |||
|
973 | # significantly smarter about delta bases. This is | |||
|
974 | # slightly tricky because this same code has to work for | |||
|
975 | # all revlogs, and we don't have the linkrev/linknode here. | |||
|
976 | return p1 | |||
|
977 | ||||
|
978 | dp = store.deltaparent(rev) | |||
|
979 | if dp == nullrev and store.storedeltachains: | |||
|
980 | # Avoid sending full revisions when delta parent is null. Pick prev | |||
|
981 | # in that case. It's tempting to pick p1 in this case, as p1 will | |||
|
982 | # be smaller in the common case. However, computing a delta against | |||
|
983 | # p1 may require resolving the raw text of p1, which could be | |||
|
984 | # expensive. The revlog caches should have prev cached, meaning | |||
|
985 | # less CPU for changegroup generation. There is likely room to add | |||
|
986 | # a flag and/or config option to control this behavior. | |||
|
987 | base = prev | |||
|
988 | elif dp == nullrev: | |||
|
989 | # revlog is configured to use full snapshot for a reason, | |||
|
990 | # stick to full snapshot. | |||
|
991 | base = nullrev | |||
|
992 | elif dp not in (p1, p2, prev): | |||
|
993 | # Pick prev when we can't be sure remote has the base revision. | |||
|
994 | return prev | |||
|
995 | else: | |||
|
996 | base = dp | |||
|
997 | ||||
|
998 | if base != nullrev and not store.candelta(base, rev): | |||
|
999 | base = nullrev | |||
|
1000 | ||||
|
1001 | return base | |||
956 |
|
1002 | |||
957 | def revchunk(self, store, rev, prev, linknode): |
|
1003 | def revchunk(self, store, rev, prev, linknode): | |
958 | if util.safehasattr(self, 'full_nodes'): |
|
1004 | if util.safehasattr(self, 'full_nodes'): | |
@@ -1125,51 +1171,13 b' class cg1packer(object):' | |||||
1125 | deltachunks=(diffheader, data), |
|
1171 | deltachunks=(diffheader, data), | |
1126 | ) |
|
1172 | ) | |
1127 |
|
1173 | |||
1128 | class cg2packer(cg1packer): |
|
|||
1129 | def deltaparent(self, store, rev, p1, p2, prev): |
|
|||
1130 | # Narrow ellipses mode. |
|
|||
1131 | if util.safehasattr(self, 'full_nodes'): |
|
|||
1132 | # TODO: send better deltas when in narrow mode. |
|
|||
1133 | # |
|
|||
1134 | # changegroup.group() loops over revisions to send, |
|
|||
1135 | # including revisions we'll skip. What this means is that |
|
|||
1136 | # `prev` will be a potentially useless delta base for all |
|
|||
1137 | # ellipsis nodes, as the client likely won't have it. In |
|
|||
1138 | # the future we should do bookkeeping about which nodes |
|
|||
1139 | # have been sent to the client, and try to be |
|
|||
1140 | # significantly smarter about delta bases. This is |
|
|||
1141 | # slightly tricky because this same code has to work for |
|
|||
1142 | # all revlogs, and we don't have the linkrev/linknode here. |
|
|||
1143 | return p1 |
|
|||
1144 |
|
||||
1145 | dp = store.deltaparent(rev) |
|
|||
1146 | if dp == nullrev and store.storedeltachains: |
|
|||
1147 | # Avoid sending full revisions when delta parent is null. Pick prev |
|
|||
1148 | # in that case. It's tempting to pick p1 in this case, as p1 will |
|
|||
1149 | # be smaller in the common case. However, computing a delta against |
|
|||
1150 | # p1 may require resolving the raw text of p1, which could be |
|
|||
1151 | # expensive. The revlog caches should have prev cached, meaning |
|
|||
1152 | # less CPU for changegroup generation. There is likely room to add |
|
|||
1153 | # a flag and/or config option to control this behavior. |
|
|||
1154 | base = prev |
|
|||
1155 | elif dp == nullrev: |
|
|||
1156 | # revlog is configured to use full snapshot for a reason, |
|
|||
1157 | # stick to full snapshot. |
|
|||
1158 | base = nullrev |
|
|||
1159 | elif dp not in (p1, p2, prev): |
|
|||
1160 | # Pick prev when we can't be sure remote has the base revision. |
|
|||
1161 | return prev |
|
|||
1162 | else: |
|
|||
1163 | base = dp |
|
|||
1164 | if base != nullrev and not store.candelta(base, rev): |
|
|||
1165 | base = nullrev |
|
|||
1166 | return base |
|
|||
1167 |
|
||||
1168 | def _makecg1packer(repo, filematcher, bundlecaps): |
|
1174 | def _makecg1packer(repo, filematcher, bundlecaps): | |
1169 | builddeltaheader = lambda d: _CHANGEGROUPV1_DELTA_HEADER.pack( |
|
1175 | builddeltaheader = lambda d: _CHANGEGROUPV1_DELTA_HEADER.pack( | |
1170 | d.node, d.p1node, d.p2node, d.linknode) |
|
1176 | d.node, d.p1node, d.p2node, d.linknode) | |
1171 |
|
1177 | |||
1172 |
return cg1packer(repo, filematcher, b'01', |
|
1178 | return cg1packer(repo, filematcher, b'01', | |
|
1179 | useprevdelta=True, | |||
|
1180 | allowreorder=None, | |||
1173 | builddeltaheader=builddeltaheader, |
|
1181 | builddeltaheader=builddeltaheader, | |
1174 | manifestsend=b'', sendtreemanifests=False, |
|
1182 | manifestsend=b'', sendtreemanifests=False, | |
1175 | bundlecaps=bundlecaps) |
|
1183 | bundlecaps=bundlecaps) | |
@@ -1181,7 +1189,9 b' def _makecg2packer(repo, filematcher, bu' | |||||
1181 | # Since generaldelta is directly supported by cg2, reordering |
|
1189 | # Since generaldelta is directly supported by cg2, reordering | |
1182 | # generally doesn't help, so we disable it by default (treating |
|
1190 | # generally doesn't help, so we disable it by default (treating | |
1183 | # bundle.reorder=auto just like bundle.reorder=False). |
|
1191 | # bundle.reorder=auto just like bundle.reorder=False). | |
1184 |
return cg |
|
1192 | return cg1packer(repo, filematcher, b'02', | |
|
1193 | useprevdelta=False, | |||
|
1194 | allowreorder=False, | |||
1185 | builddeltaheader=builddeltaheader, |
|
1195 | builddeltaheader=builddeltaheader, | |
1186 | manifestsend=b'', sendtreemanifests=False, |
|
1196 | manifestsend=b'', sendtreemanifests=False, | |
1187 | bundlecaps=bundlecaps) |
|
1197 | bundlecaps=bundlecaps) | |
@@ -1190,7 +1200,9 b' def _makecg3packer(repo, filematcher, bu' | |||||
1190 | builddeltaheader = lambda d: _CHANGEGROUPV3_DELTA_HEADER.pack( |
|
1200 | builddeltaheader = lambda d: _CHANGEGROUPV3_DELTA_HEADER.pack( | |
1191 | d.node, d.p1node, d.p2node, d.basenode, d.linknode, d.flags) |
|
1201 | d.node, d.p1node, d.p2node, d.basenode, d.linknode, d.flags) | |
1192 |
|
1202 | |||
1193 |
return cg |
|
1203 | return cg1packer(repo, filematcher, b'03', | |
|
1204 | useprevdelta=False, | |||
|
1205 | allowreorder=False, | |||
1194 | builddeltaheader=builddeltaheader, |
|
1206 | builddeltaheader=builddeltaheader, | |
1195 | manifestsend=closechunk(), sendtreemanifests=True, |
|
1207 | manifestsend=closechunk(), sendtreemanifests=True, | |
1196 | bundlecaps=bundlecaps) |
|
1208 | bundlecaps=bundlecaps) |
General Comments 0
You need to be logged in to leave comments.
Login now