Show More
@@ -521,7 +521,7 b' class revisiondelta(object):' | |||||
521 |
|
521 | |||
522 | class cgpacker(object): |
|
522 | class cgpacker(object): | |
523 | def __init__(self, repo, filematcher, version, allowreorder, |
|
523 | def __init__(self, repo, filematcher, version, allowreorder, | |
524 |
|
|
524 | deltaparentfn, builddeltaheader, manifestsend, | |
525 | bundlecaps=None, ellipses=False, |
|
525 | bundlecaps=None, ellipses=False, | |
526 | shallow=False, ellipsisroots=None, fullnodes=None): |
|
526 | shallow=False, ellipsisroots=None, fullnodes=None): | |
527 | """Given a source repo, construct a bundler. |
|
527 | """Given a source repo, construct a bundler. | |
@@ -533,8 +533,8 b' class cgpacker(object):' | |||||
533 | This value is used when ``bundle.reorder`` is ``auto`` or isn't |
|
533 | This value is used when ``bundle.reorder`` is ``auto`` or isn't | |
534 | set. |
|
534 | set. | |
535 |
|
535 | |||
536 | useprevdelta controls whether revisions should always delta against |
|
536 | deltaparentfn is a callable that resolves the delta parent for | |
537 | the previous revision in the changegroup. |
|
537 | a specific revision. | |
538 |
|
538 | |||
539 | builddeltaheader is a callable that constructs the header for a group |
|
539 | builddeltaheader is a callable that constructs the header for a group | |
540 | delta. |
|
540 | delta. | |
@@ -559,7 +559,7 b' class cgpacker(object):' | |||||
559 | self._filematcher = filematcher |
|
559 | self._filematcher = filematcher | |
560 |
|
560 | |||
561 | self.version = version |
|
561 | self.version = version | |
562 |
self._ |
|
562 | self._deltaparentfn = deltaparentfn | |
563 | self._builddeltaheader = builddeltaheader |
|
563 | self._builddeltaheader = builddeltaheader | |
564 | self._manifestsend = manifestsend |
|
564 | self._manifestsend = manifestsend | |
565 | self._ellipses = ellipses |
|
565 | self._ellipses = ellipses | |
@@ -969,53 +969,6 b' class cgpacker(object):' | |||||
969 | self._verbosenote(_('%8.i %s\n') % (size, fname)) |
|
969 | self._verbosenote(_('%8.i %s\n') % (size, fname)) | |
970 | progress.complete() |
|
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 | def _revchunk(self, store, rev, prev, linknode): |
|
972 | def _revchunk(self, store, rev, prev, linknode): | |
1020 | if self._ellipses: |
|
973 | if self._ellipses: | |
1021 | fn = self._revisiondeltanarrow |
|
974 | fn = self._revisiondeltanarrow | |
@@ -1037,7 +990,7 b' class cgpacker(object):' | |||||
1037 | def _revisiondeltanormal(self, store, rev, prev, linknode): |
|
990 | def _revisiondeltanormal(self, store, rev, prev, linknode): | |
1038 | node = store.node(rev) |
|
991 | node = store.node(rev) | |
1039 | p1, p2 = store.parentrevs(rev) |
|
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 | prefix = '' |
|
995 | prefix = '' | |
1043 | if store.iscensored(base) or store.iscensored(rev): |
|
996 | if store.iscensored(base) or store.iscensored(rev): | |
@@ -1187,13 +1140,62 b' class cgpacker(object):' | |||||
1187 | deltachunks=(diffheader, data), |
|
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 | def _makecg1packer(repo, filematcher, bundlecaps, ellipses=False, |
|
1192 | def _makecg1packer(repo, filematcher, bundlecaps, ellipses=False, | |
1191 | shallow=False, ellipsisroots=None, fullnodes=None): |
|
1193 | shallow=False, ellipsisroots=None, fullnodes=None): | |
1192 | builddeltaheader = lambda d: _CHANGEGROUPV1_DELTA_HEADER.pack( |
|
1194 | builddeltaheader = lambda d: _CHANGEGROUPV1_DELTA_HEADER.pack( | |
1193 | d.node, d.p1node, d.p2node, d.linknode) |
|
1195 | d.node, d.p1node, d.p2node, d.linknode) | |
1194 |
|
1196 | |||
1195 | return cgpacker(repo, filematcher, b'01', |
|
1197 | return cgpacker(repo, filematcher, b'01', | |
1196 |
|
|
1198 | deltaparentfn=_deltaparentprev, | |
1197 | allowreorder=None, |
|
1199 | allowreorder=None, | |
1198 | builddeltaheader=builddeltaheader, |
|
1200 | builddeltaheader=builddeltaheader, | |
1199 | manifestsend=b'', |
|
1201 | manifestsend=b'', | |
@@ -1212,7 +1214,7 b' def _makecg2packer(repo, filematcher, bu' | |||||
1212 | # generally doesn't help, so we disable it by default (treating |
|
1214 | # generally doesn't help, so we disable it by default (treating | |
1213 | # bundle.reorder=auto just like bundle.reorder=False). |
|
1215 | # bundle.reorder=auto just like bundle.reorder=False). | |
1214 | return cgpacker(repo, filematcher, b'02', |
|
1216 | return cgpacker(repo, filematcher, b'02', | |
1215 |
|
|
1217 | deltaparentfn=_deltaparentgeneraldelta, | |
1216 | allowreorder=False, |
|
1218 | allowreorder=False, | |
1217 | builddeltaheader=builddeltaheader, |
|
1219 | builddeltaheader=builddeltaheader, | |
1218 | manifestsend=b'', |
|
1220 | manifestsend=b'', | |
@@ -1227,8 +1229,11 b' def _makecg3packer(repo, filematcher, bu' | |||||
1227 | builddeltaheader = lambda d: _CHANGEGROUPV3_DELTA_HEADER.pack( |
|
1229 | builddeltaheader = lambda d: _CHANGEGROUPV3_DELTA_HEADER.pack( | |
1228 | d.node, d.p1node, d.p2node, d.basenode, d.linknode, d.flags) |
|
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 | return cgpacker(repo, filematcher, b'03', |
|
1235 | return cgpacker(repo, filematcher, b'03', | |
1231 |
|
|
1236 | deltaparentfn=deltaparentfn, | |
1232 | allowreorder=False, |
|
1237 | allowreorder=False, | |
1233 | builddeltaheader=builddeltaheader, |
|
1238 | builddeltaheader=builddeltaheader, | |
1234 | manifestsend=closechunk(), |
|
1239 | manifestsend=closechunk(), |
General Comments 0
You need to be logged in to leave comments.
Login now