Show More
@@ -521,7 +521,7 b' class revisiondelta(object):' | |||
|
521 | 521 | |
|
522 | 522 | class cgpacker(object): |
|
523 | 523 | def __init__(self, repo, filematcher, version, allowreorder, |
|
524 |
|
|
|
524 | deltaparentfn, builddeltaheader, manifestsend, | |
|
525 | 525 | bundlecaps=None, ellipses=False, |
|
526 | 526 | shallow=False, ellipsisroots=None, fullnodes=None): |
|
527 | 527 | """Given a source repo, construct a bundler. |
@@ -533,8 +533,8 b' class cgpacker(object):' | |||
|
533 | 533 | This value is used when ``bundle.reorder`` is ``auto`` or isn't |
|
534 | 534 | set. |
|
535 | 535 | |
|
536 | useprevdelta controls whether revisions should always delta against | |
|
537 | the previous revision in the changegroup. | |
|
536 | deltaparentfn is a callable that resolves the delta parent for | |
|
537 | a specific revision. | |
|
538 | 538 | |
|
539 | 539 | builddeltaheader is a callable that constructs the header for a group |
|
540 | 540 | delta. |
@@ -559,7 +559,7 b' class cgpacker(object):' | |||
|
559 | 559 | self._filematcher = filematcher |
|
560 | 560 | |
|
561 | 561 | self.version = version |
|
562 |
self._ |
|
|
562 | self._deltaparentfn = deltaparentfn | |
|
563 | 563 | self._builddeltaheader = builddeltaheader |
|
564 | 564 | self._manifestsend = manifestsend |
|
565 | 565 | self._ellipses = ellipses |
@@ -969,53 +969,6 b' class cgpacker(object):' | |||
|
969 | 969 | self._verbosenote(_('%8.i %s\n') % (size, fname)) |
|
970 | 970 | progress.complete() |
|
971 | 971 | |
|
972 | def _deltaparent(self, store, rev, p1, p2, prev): | |
|
973 | if self._useprevdelta: | |
|
974 | if not store.candelta(prev, rev): | |
|
975 | raise error.ProgrammingError( | |
|
976 | 'cg1 should not be used in this case') | |
|
977 | return prev | |
|
978 | ||
|
979 | # Narrow ellipses mode. | |
|
980 | if self._ellipses: | |
|
981 | # TODO: send better deltas when in narrow mode. | |
|
982 | # | |
|
983 | # changegroup.group() loops over revisions to send, | |
|
984 | # including revisions we'll skip. What this means is that | |
|
985 | # `prev` will be a potentially useless delta base for all | |
|
986 | # ellipsis nodes, as the client likely won't have it. In | |
|
987 | # the future we should do bookkeeping about which nodes | |
|
988 | # have been sent to the client, and try to be | |
|
989 | # significantly smarter about delta bases. This is | |
|
990 | # slightly tricky because this same code has to work for | |
|
991 | # all revlogs, and we don't have the linkrev/linknode here. | |
|
992 | return p1 | |
|
993 | ||
|
994 | dp = store.deltaparent(rev) | |
|
995 | if dp == nullrev and store.storedeltachains: | |
|
996 | # Avoid sending full revisions when delta parent is null. Pick prev | |
|
997 | # in that case. It's tempting to pick p1 in this case, as p1 will | |
|
998 | # be smaller in the common case. However, computing a delta against | |
|
999 | # p1 may require resolving the raw text of p1, which could be | |
|
1000 | # expensive. The revlog caches should have prev cached, meaning | |
|
1001 | # less CPU for changegroup generation. There is likely room to add | |
|
1002 | # a flag and/or config option to control this behavior. | |
|
1003 | base = prev | |
|
1004 | elif dp == nullrev: | |
|
1005 | # revlog is configured to use full snapshot for a reason, | |
|
1006 | # stick to full snapshot. | |
|
1007 | base = nullrev | |
|
1008 | elif dp not in (p1, p2, prev): | |
|
1009 | # Pick prev when we can't be sure remote has the base revision. | |
|
1010 | return prev | |
|
1011 | else: | |
|
1012 | base = dp | |
|
1013 | ||
|
1014 | if base != nullrev and not store.candelta(base, rev): | |
|
1015 | base = nullrev | |
|
1016 | ||
|
1017 | return base | |
|
1018 | ||
|
1019 | 972 | def _revchunk(self, store, rev, prev, linknode): |
|
1020 | 973 | if self._ellipses: |
|
1021 | 974 | fn = self._revisiondeltanarrow |
@@ -1037,7 +990,7 b' class cgpacker(object):' | |||
|
1037 | 990 | def _revisiondeltanormal(self, store, rev, prev, linknode): |
|
1038 | 991 | node = store.node(rev) |
|
1039 | 992 | p1, p2 = store.parentrevs(rev) |
|
1040 | base = self._deltaparent(store, rev, p1, p2, prev) | |
|
993 | base = self._deltaparentfn(store, rev, p1, p2, prev) | |
|
1041 | 994 | |
|
1042 | 995 | prefix = '' |
|
1043 | 996 | if store.iscensored(base) or store.iscensored(rev): |
@@ -1187,13 +1140,62 b' class cgpacker(object):' | |||
|
1187 | 1140 | deltachunks=(diffheader, data), |
|
1188 | 1141 | ) |
|
1189 | 1142 | |
|
1143 | def _deltaparentprev(store, rev, p1, p2, prev): | |
|
1144 | """Resolve a delta parent to the previous revision. | |
|
1145 | ||
|
1146 | Used for version 1 changegroups, which don't support generaldelta. | |
|
1147 | """ | |
|
1148 | return prev | |
|
1149 | ||
|
1150 | def _deltaparentgeneraldelta(store, rev, p1, p2, prev): | |
|
1151 | """Resolve a delta parent when general deltas are supported.""" | |
|
1152 | dp = store.deltaparent(rev) | |
|
1153 | if dp == nullrev and store.storedeltachains: | |
|
1154 | # Avoid sending full revisions when delta parent is null. Pick prev | |
|
1155 | # in that case. It's tempting to pick p1 in this case, as p1 will | |
|
1156 | # be smaller in the common case. However, computing a delta against | |
|
1157 | # p1 may require resolving the raw text of p1, which could be | |
|
1158 | # expensive. The revlog caches should have prev cached, meaning | |
|
1159 | # less CPU for changegroup generation. There is likely room to add | |
|
1160 | # a flag and/or config option to control this behavior. | |
|
1161 | base = prev | |
|
1162 | elif dp == nullrev: | |
|
1163 | # revlog is configured to use full snapshot for a reason, | |
|
1164 | # stick to full snapshot. | |
|
1165 | base = nullrev | |
|
1166 | elif dp not in (p1, p2, prev): | |
|
1167 | # Pick prev when we can't be sure remote has the base revision. | |
|
1168 | return prev | |
|
1169 | else: | |
|
1170 | base = dp | |
|
1171 | ||
|
1172 | if base != nullrev and not store.candelta(base, rev): | |
|
1173 | base = nullrev | |
|
1174 | ||
|
1175 | return base | |
|
1176 | ||
|
1177 | def _deltaparentellipses(store, rev, p1, p2, prev): | |
|
1178 | """Resolve a delta parent when in ellipses mode.""" | |
|
1179 | # TODO: send better deltas when in narrow mode. | |
|
1180 | # | |
|
1181 | # changegroup.group() loops over revisions to send, | |
|
1182 | # including revisions we'll skip. What this means is that | |
|
1183 | # `prev` will be a potentially useless delta base for all | |
|
1184 | # ellipsis nodes, as the client likely won't have it. In | |
|
1185 | # the future we should do bookkeeping about which nodes | |
|
1186 | # have been sent to the client, and try to be | |
|
1187 | # significantly smarter about delta bases. This is | |
|
1188 | # slightly tricky because this same code has to work for | |
|
1189 | # all revlogs, and we don't have the linkrev/linknode here. | |
|
1190 | return p1 | |
|
1191 | ||
|
1190 | 1192 | def _makecg1packer(repo, filematcher, bundlecaps, ellipses=False, |
|
1191 | 1193 | shallow=False, ellipsisroots=None, fullnodes=None): |
|
1192 | 1194 | builddeltaheader = lambda d: _CHANGEGROUPV1_DELTA_HEADER.pack( |
|
1193 | 1195 | d.node, d.p1node, d.p2node, d.linknode) |
|
1194 | 1196 | |
|
1195 | 1197 | return cgpacker(repo, filematcher, b'01', |
|
1196 |
|
|
|
1198 | deltaparentfn=_deltaparentprev, | |
|
1197 | 1199 | allowreorder=None, |
|
1198 | 1200 | builddeltaheader=builddeltaheader, |
|
1199 | 1201 | manifestsend=b'', |
@@ -1212,7 +1214,7 b' def _makecg2packer(repo, filematcher, bu' | |||
|
1212 | 1214 | # generally doesn't help, so we disable it by default (treating |
|
1213 | 1215 | # bundle.reorder=auto just like bundle.reorder=False). |
|
1214 | 1216 | return cgpacker(repo, filematcher, b'02', |
|
1215 |
|
|
|
1217 | deltaparentfn=_deltaparentgeneraldelta, | |
|
1216 | 1218 | allowreorder=False, |
|
1217 | 1219 | builddeltaheader=builddeltaheader, |
|
1218 | 1220 | manifestsend=b'', |
@@ -1227,8 +1229,11 b' def _makecg3packer(repo, filematcher, bu' | |||
|
1227 | 1229 | builddeltaheader = lambda d: _CHANGEGROUPV3_DELTA_HEADER.pack( |
|
1228 | 1230 | d.node, d.p1node, d.p2node, d.basenode, d.linknode, d.flags) |
|
1229 | 1231 | |
|
1232 | deltaparentfn = (_deltaparentellipses if ellipses | |
|
1233 | else _deltaparentgeneraldelta) | |
|
1234 | ||
|
1230 | 1235 | return cgpacker(repo, filematcher, b'03', |
|
1231 |
|
|
|
1236 | deltaparentfn=deltaparentfn, | |
|
1232 | 1237 | allowreorder=False, |
|
1233 | 1238 | builddeltaheader=builddeltaheader, |
|
1234 | 1239 | manifestsend=closechunk(), |
General Comments 0
You need to be logged in to leave comments.
Login now