##// END OF EJS Templates
changegroup: pass function to resolve delta parents into constructor...
Gregory Szorc -
r39011:87b737b7 default
parent child Browse files
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 useprevdelta, builddeltaheader, manifestsend,
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._useprevdelta = useprevdelta
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 useprevdelta=True,
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 useprevdelta=False,
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 useprevdelta=False,
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