334 self.defversion = REVLOG_DEFAULT_VERSION |
334 self.defversion = REVLOG_DEFAULT_VERSION |
335 if hasattr(opener, "defversion"): |
335 if hasattr(opener, "defversion"): |
336 self.defversion = opener.defversion |
336 self.defversion = opener.defversion |
337 if self.defversion & REVLOGNG: |
337 if self.defversion & REVLOGNG: |
338 self.defversion |= REVLOGNGINLINEDATA |
338 self.defversion |= REVLOGNGINLINEDATA |
339 self.load() |
339 self._load() |
340 |
340 |
341 def load(self): |
341 def _load(self): |
342 v = self.defversion |
342 v = self.defversion |
343 try: |
343 try: |
344 f = self.opener(self.indexfile) |
344 f = self.opener(self.indexfile) |
345 i = f.read(4) |
345 i = f.read(4) |
346 f.seek(0) |
346 f.seek(0) |
384 else: |
384 else: |
385 self.indexformat = indexformatng |
385 self.indexformat = indexformatng |
386 shaoffset = ngshaoffset |
386 shaoffset = ngshaoffset |
387 |
387 |
388 if i: |
388 if i: |
389 if (lazyparser.safe_to_use and not self.inlinedata() and |
389 if (lazyparser.safe_to_use and not self._inline() and |
390 st and st.st_size > 10000): |
390 st and st.st_size > 10000): |
391 # big index, let's parse it on demand |
391 # big index, let's parse it on demand |
392 parser = lazyparser(f, st.st_size, self.indexformat, shaoffset) |
392 parser = lazyparser(f, st.st_size, self.indexformat, shaoffset) |
393 self.index = lazyindex(parser) |
393 self.index = lazyindex(parser) |
394 self.nodemap = lazymap(parser) |
394 self.nodemap = lazymap(parser) |
395 else: |
395 else: |
396 self.parseindex(f, st) |
396 self._parseindex(f, st) |
397 if self.version != REVLOGV0: |
397 if self.version != REVLOGV0: |
398 e = list(self.index[0]) |
398 e = list(self.index[0]) |
399 type = gettype(e[0]) |
399 type = gettype(e[0]) |
400 e[0] = offset_type(0, type) |
400 e[0] = offset_type(0, type) |
401 self.index[0] = e |
401 self.index[0] = e |
402 else: |
402 else: |
403 self.nodemap = {nullid: nullrev} |
403 self.nodemap = {nullid: nullrev} |
404 self.index = [] |
404 self.index = [] |
405 |
405 |
406 |
406 def _parseindex(self, fp, st): |
407 def parseindex(self, fp, st): |
|
408 s = struct.calcsize(self.indexformat) |
407 s = struct.calcsize(self.indexformat) |
409 self.index = [] |
408 self.index = [] |
410 self.nodemap = {nullid: nullrev} |
409 self.nodemap = {nullid: nullrev} |
411 inline = self.inlinedata() |
410 inline = self._inline() |
412 n = 0 |
411 n = 0 |
413 leftover = None |
412 leftover = None |
414 while True: |
413 while True: |
415 if st: |
414 if st: |
416 data = fp.read(65536) |
415 data = fp.read(65536) |
417 else: |
416 else: |
418 # hack for httprangereader, it doesn't do partial reads well |
417 # hack for httprangereader, it doesn't do partial reads well |
419 data = fp.read() |
418 data = fp.read() |
420 if not data: |
419 if not data: |
421 break |
420 break |
422 if n == 0 and self.inlinedata(): |
421 if n == 0 and self._inline(): |
423 # cache the first chunk |
422 # cache the first chunk |
424 self.chunkcache = (0, data) |
423 self.chunkcache = (0, data) |
425 if leftover: |
424 if leftover: |
426 data = leftover + data |
425 data = leftover + data |
427 leftover = None |
426 leftover = None |
447 break |
446 break |
448 if not st: |
447 if not st: |
449 break |
448 break |
450 |
449 |
451 |
450 |
452 def loadindex(self, start, end): |
451 def _loadindex(self, start, end): |
453 """load a block of indexes all at once from the lazy parser""" |
452 """load a block of indexes all at once from the lazy parser""" |
454 if isinstance(self.index, lazyindex): |
453 if isinstance(self.index, lazyindex): |
455 self.index.p.loadindex(start, end) |
454 self.index.p.loadindex(start, end) |
456 |
455 |
457 def loadindexmap(self): |
456 def _loadindexmap(self): |
458 """loads both the map and the index from the lazy parser""" |
457 """loads both the map and the index from the lazy parser""" |
459 if isinstance(self.index, lazyindex): |
458 if isinstance(self.index, lazyindex): |
460 p = self.index.p |
459 p = self.index.p |
461 p.loadindex() |
460 p.loadindex() |
462 self.nodemap = p.map |
461 self.nodemap = p.map |
463 |
462 |
464 def loadmap(self): |
463 def _loadmap(self): |
465 """loads the map from the lazy parser""" |
464 """loads the map from the lazy parser""" |
466 if isinstance(self.nodemap, lazymap): |
465 if isinstance(self.nodemap, lazymap): |
467 self.nodemap.p.loadmap() |
466 self.nodemap.p.loadmap() |
468 self.nodemap = self.nodemap.p.map |
467 self.nodemap = self.nodemap.p.map |
469 |
468 |
470 def inlinedata(self): return self.version & REVLOGNGINLINEDATA |
469 def _inline(self): return self.version & REVLOGNGINLINEDATA |
|
470 |
471 def tip(self): return self.node(len(self.index) - 1) |
471 def tip(self): return self.node(len(self.index) - 1) |
472 def count(self): return len(self.index) |
472 def count(self): return len(self.index) |
473 def node(self, rev): |
473 def node(self, rev): |
474 return rev == nullrev and nullid or self.index[rev][-1] |
474 return rev == nullrev and nullid or self.index[rev][-1] |
475 def rev(self, node): |
475 def rev(self, node): |
839 """apply a list of patches to a string""" |
839 """apply a list of patches to a string""" |
840 return mdiff.patches(t, pl) |
840 return mdiff.patches(t, pl) |
841 |
841 |
842 def chunk(self, rev, df=None, cachelen=4096): |
842 def chunk(self, rev, df=None, cachelen=4096): |
843 start, length = self.start(rev), self.length(rev) |
843 start, length = self.start(rev), self.length(rev) |
844 inline = self.inlinedata() |
844 inline = self._inline() |
845 if inline: |
845 if inline: |
846 start += (rev + 1) * struct.calcsize(self.indexformat) |
846 start += (rev + 1) * struct.calcsize(self.indexformat) |
847 end = start + length |
847 end = start + length |
848 def loadcache(df): |
848 def loadcache(df): |
849 cache_length = max(cachelen, length) # 4k |
849 cache_length = max(cachelen, length) # 4k |
897 # look up what we need to read |
897 # look up what we need to read |
898 text = None |
898 text = None |
899 rev = self.rev(node) |
899 rev = self.rev(node) |
900 base = self.base(rev) |
900 base = self.base(rev) |
901 |
901 |
902 if self.inlinedata(): |
902 if self._inline(): |
903 # we probably have the whole chunk cached |
903 # we probably have the whole chunk cached |
904 df = None |
904 df = None |
905 else: |
905 else: |
906 df = self.opener(self.datafile) |
906 df = self.opener(self.datafile) |
907 |
907 |
908 # do we have useful data cached? |
908 # do we have useful data cached? |
909 if self.cache and self.cache[1] >= base and self.cache[1] < rev: |
909 if self.cache and self.cache[1] >= base and self.cache[1] < rev: |
910 base = self.cache[1] |
910 base = self.cache[1] |
911 text = self.cache[2] |
911 text = self.cache[2] |
912 self.loadindex(base, rev + 1) |
912 self._loadindex(base, rev + 1) |
913 else: |
913 else: |
914 self.loadindex(base, rev + 1) |
914 self._loadindex(base, rev + 1) |
915 text = self.chunk(base, df=df) |
915 text = self.chunk(base, df=df) |
916 |
916 |
917 bins = [] |
917 bins = [] |
918 for r in xrange(base + 1, rev + 1): |
918 for r in xrange(base + 1, rev + 1): |
919 bins.append(self.chunk(r, df=df)) |
919 bins.append(self.chunk(r, df=df)) |
927 |
927 |
928 self.cache = (node, rev, text) |
928 self.cache = (node, rev, text) |
929 return text |
929 return text |
930 |
930 |
931 def checkinlinesize(self, tr, fp=None): |
931 def checkinlinesize(self, tr, fp=None): |
932 if not self.inlinedata(): |
932 if not self._inline(): |
933 return |
933 return |
934 if not fp: |
934 if not fp: |
935 fp = self.opener(self.indexfile, 'r') |
935 fp = self.opener(self.indexfile, 'r') |
936 fp.seek(0, 2) |
936 fp.seek(0, 2) |
937 size = fp.tell() |
937 size = fp.tell() |
984 transaction - the transaction object used for rollback |
984 transaction - the transaction object used for rollback |
985 link - the linkrev data to add |
985 link - the linkrev data to add |
986 p1, p2 - the parent nodeids of the revision |
986 p1, p2 - the parent nodeids of the revision |
987 d - an optional precomputed delta |
987 d - an optional precomputed delta |
988 """ |
988 """ |
989 if not self.inlinedata(): |
989 if not self._inline(): |
990 dfh = self.opener(self.datafile, "a") |
990 dfh = self.opener(self.datafile, "a") |
991 else: |
991 else: |
992 dfh = None |
992 dfh = None |
993 ifh = self.opener(self.indexfile, "a+") |
993 ifh = self.opener(self.indexfile, "a+") |
994 return self._addrevision(text, transaction, link, p1, p2, d, ifh, dfh) |
994 return self._addrevision(text, transaction, link, p1, p2, d, ifh, dfh) |
1038 |
1038 |
1039 self.index.append(e) |
1039 self.index.append(e) |
1040 self.nodemap[node] = n |
1040 self.nodemap[node] = n |
1041 entry = struct.pack(self.indexformat, *e) |
1041 entry = struct.pack(self.indexformat, *e) |
1042 |
1042 |
1043 if not self.inlinedata(): |
1043 if not self._inline(): |
1044 transaction.add(self.datafile, offset) |
1044 transaction.add(self.datafile, offset) |
1045 transaction.add(self.indexfile, n * len(entry)) |
1045 transaction.add(self.indexfile, n * len(entry)) |
1046 if data[0]: |
1046 if data[0]: |
1047 dfh.write(data[0]) |
1047 dfh.write(data[0]) |
1048 dfh.write(data[1]) |
1048 dfh.write(data[1]) |
1133 end = self.end(t) |
1133 end = self.end(t) |
1134 |
1134 |
1135 ifh = self.opener(self.indexfile, "a+") |
1135 ifh = self.opener(self.indexfile, "a+") |
1136 ifh.seek(0, 2) |
1136 ifh.seek(0, 2) |
1137 transaction.add(self.indexfile, ifh.tell(), self.count()) |
1137 transaction.add(self.indexfile, ifh.tell(), self.count()) |
1138 if self.inlinedata(): |
1138 if self._inline(): |
1139 dfh = None |
1139 dfh = None |
1140 else: |
1140 else: |
1141 transaction.add(self.datafile, end) |
1141 transaction.add(self.datafile, end) |
1142 dfh = self.opener(self.datafile, "a") |
1142 dfh = self.opener(self.datafile, "a") |
1143 |
1143 |
1182 ifh.flush() |
1182 ifh.flush() |
1183 text = self.revision(chain) |
1183 text = self.revision(chain) |
1184 text = self.patches(text, [delta]) |
1184 text = self.patches(text, [delta]) |
1185 chk = self._addrevision(text, transaction, link, p1, p2, None, |
1185 chk = self._addrevision(text, transaction, link, p1, p2, None, |
1186 ifh, dfh) |
1186 ifh, dfh) |
1187 if not dfh and not self.inlinedata(): |
1187 if not dfh and not self._inline(): |
1188 # addrevision switched from inline to conventional |
1188 # addrevision switched from inline to conventional |
1189 # reopen the index |
1189 # reopen the index |
1190 dfh = self.opener(self.datafile, "a") |
1190 dfh = self.opener(self.datafile, "a") |
1191 ifh = self.opener(self.indexfile, "a") |
1191 ifh = self.opener(self.indexfile, "a") |
1192 if chk != node: |
1192 if chk != node: |
1198 else: |
1198 else: |
1199 e = (offset_type(end, 0), len(cdelta), textlen, base, |
1199 e = (offset_type(end, 0), len(cdelta), textlen, base, |
1200 link, self.rev(p1), self.rev(p2), node) |
1200 link, self.rev(p1), self.rev(p2), node) |
1201 self.index.append(e) |
1201 self.index.append(e) |
1202 self.nodemap[node] = r |
1202 self.nodemap[node] = r |
1203 if self.inlinedata(): |
1203 if self._inline(): |
1204 ifh.write(struct.pack(self.indexformat, *e)) |
1204 ifh.write(struct.pack(self.indexformat, *e)) |
1205 ifh.write(cdelta) |
1205 ifh.write(cdelta) |
1206 self.checkinlinesize(transaction, ifh) |
1206 self.checkinlinesize(transaction, ifh) |
1207 if not self.inlinedata(): |
1207 if not self._inline(): |
1208 dfh = self.opener(self.datafile, "a") |
1208 dfh = self.opener(self.datafile, "a") |
1209 ifh = self.opener(self.indexfile, "a") |
1209 ifh = self.opener(self.indexfile, "a") |
1210 else: |
1210 else: |
1211 dfh.write(cdelta) |
1211 dfh.write(cdelta) |
1212 ifh.write(struct.pack(self.indexformat, *e)) |
1212 ifh.write(struct.pack(self.indexformat, *e)) |
1221 def strip(self, rev, minlink): |
1221 def strip(self, rev, minlink): |
1222 if self.count() == 0 or rev >= self.count(): |
1222 if self.count() == 0 or rev >= self.count(): |
1223 return |
1223 return |
1224 |
1224 |
1225 if isinstance(self.index, lazyindex): |
1225 if isinstance(self.index, lazyindex): |
1226 self.loadindexmap() |
1226 self._loadindexmap() |
1227 |
1227 |
1228 # When stripping away a revision, we need to make sure it |
1228 # When stripping away a revision, we need to make sure it |
1229 # does not actually belong to an older changeset. |
1229 # does not actually belong to an older changeset. |
1230 # The minlink parameter defines the oldest revision |
1230 # The minlink parameter defines the oldest revision |
1231 # we're allowed to strip away. |
1231 # we're allowed to strip away. |
1234 if rev >= self.count(): |
1234 if rev >= self.count(): |
1235 return |
1235 return |
1236 |
1236 |
1237 # first truncate the files on disk |
1237 # first truncate the files on disk |
1238 end = self.start(rev) |
1238 end = self.start(rev) |
1239 if not self.inlinedata(): |
1239 if not self._inline(): |
1240 df = self.opener(self.datafile, "a") |
1240 df = self.opener(self.datafile, "a") |
1241 df.truncate(end) |
1241 df.truncate(end) |
1242 end = rev * struct.calcsize(self.indexformat) |
1242 end = rev * struct.calcsize(self.indexformat) |
1243 else: |
1243 else: |
1244 end += rev * struct.calcsize(self.indexformat) |
1244 end += rev * struct.calcsize(self.indexformat) |