506 mode=b"w", |
506 mode=b"w", |
507 checkambig=self.data_config.check_ambig, |
507 checkambig=self.data_config.check_ambig, |
508 atomictemp=True, |
508 atomictemp=True, |
509 ) |
509 ) |
510 |
510 |
|
511 def get_segment_for_revs(self, startrev, endrev): |
|
512 """Obtain a segment of raw data corresponding to a range of revisions. |
|
513 |
|
514 Accepts the start and end revisions and an optional already-open |
|
515 file handle to be used for reading. If the file handle is read, its |
|
516 seek position will not be preserved. |
|
517 |
|
518 Requests for data may be satisfied by a cache. |
|
519 |
|
520 Returns a 2-tuple of (offset, data) for the requested range of |
|
521 revisions. Offset is the integer offset from the beginning of the |
|
522 revlog and data is a str or buffer of the raw byte data. |
|
523 |
|
524 Callers will need to call ``self.start(rev)`` and ``self.length(rev)`` |
|
525 to determine where each revision's data begins and ends. |
|
526 |
|
527 API: we should consider making this a private part of the InnerRevlog |
|
528 at some point. |
|
529 """ |
|
530 # Inlined self.start(startrev) & self.end(endrev) for perf reasons |
|
531 # (functions are expensive). |
|
532 index = self.index |
|
533 istart = index[startrev] |
|
534 start = int(istart[0] >> 16) |
|
535 if startrev == endrev: |
|
536 end = start + istart[1] |
|
537 else: |
|
538 iend = index[endrev] |
|
539 end = int(iend[0] >> 16) + iend[1] |
|
540 |
|
541 if self.inline: |
|
542 start += (startrev + 1) * self.index.entry_size |
|
543 end += (endrev + 1) * self.index.entry_size |
|
544 length = end - start |
|
545 |
|
546 return start, self._segmentfile.read_chunk(start, length) |
|
547 |
511 |
548 |
512 class revlog: |
549 class revlog: |
513 """ |
550 """ |
514 the underlying revision storage object |
551 the underlying revision storage object |
515 |
552 |
998 header |= self._format_version |
1035 header |= self._format_version |
999 header |= FLAG_INLINE_DATA |
1036 header |= FLAG_INLINE_DATA |
1000 header = self.index.pack_header(header) |
1037 header = self.index.pack_header(header) |
1001 idx = header + idx |
1038 idx = header + idx |
1002 yield idx |
1039 yield idx |
1003 yield self._getsegmentforrevs(rev, rev)[1] |
1040 yield self._inner.get_segment_for_revs(rev, rev)[1] |
1004 |
1041 |
1005 inline_stream = get_stream() |
1042 inline_stream = get_stream() |
1006 next(inline_stream) |
1043 next(inline_stream) |
1007 return [ |
1044 return [ |
1008 (self._indexfile, inline_stream, index_size + data_size), |
1045 (self._indexfile, inline_stream, index_size + data_size), |
2151 returns True if text is different than what is stored. |
2188 returns True if text is different than what is stored. |
2152 """ |
2189 """ |
2153 p1, p2 = self.parents(node) |
2190 p1, p2 = self.parents(node) |
2154 return storageutil.hashrevisionsha1(text, p1, p2) != node |
2191 return storageutil.hashrevisionsha1(text, p1, p2) != node |
2155 |
2192 |
2156 def _getsegmentforrevs(self, startrev, endrev): |
|
2157 """Obtain a segment of raw data corresponding to a range of revisions. |
|
2158 |
|
2159 Accepts the start and end revisions and an optional already-open |
|
2160 file handle to be used for reading. If the file handle is read, its |
|
2161 seek position will not be preserved. |
|
2162 |
|
2163 Requests for data may be satisfied by a cache. |
|
2164 |
|
2165 Returns a 2-tuple of (offset, data) for the requested range of |
|
2166 revisions. Offset is the integer offset from the beginning of the |
|
2167 revlog and data is a str or buffer of the raw byte data. |
|
2168 |
|
2169 Callers will need to call ``self.start(rev)`` and ``self.length(rev)`` |
|
2170 to determine where each revision's data begins and ends. |
|
2171 """ |
|
2172 # Inlined self.start(startrev) & self.end(endrev) for perf reasons |
|
2173 # (functions are expensive). |
|
2174 index = self.index |
|
2175 istart = index[startrev] |
|
2176 start = int(istart[0] >> 16) |
|
2177 if startrev == endrev: |
|
2178 end = start + istart[1] |
|
2179 else: |
|
2180 iend = index[endrev] |
|
2181 end = int(iend[0] >> 16) + iend[1] |
|
2182 |
|
2183 if self._inline: |
|
2184 start += (startrev + 1) * self.index.entry_size |
|
2185 end += (endrev + 1) * self.index.entry_size |
|
2186 length = end - start |
|
2187 |
|
2188 return start, self._inner._segmentfile.read_chunk(start, length) |
|
2189 |
|
2190 def _chunk(self, rev): |
2193 def _chunk(self, rev): |
2191 """Obtain a single decompressed chunk for a revision. |
2194 """Obtain a single decompressed chunk for a revision. |
2192 |
2195 |
2193 Accepts an integer revision and an optional already-open file handle |
2196 Accepts an integer revision and an optional already-open file handle |
2194 to be used for reading. If used, the seek position of the file will not |
2197 to be used for reading. If used, the seek position of the file will not |
2195 be preserved. |
2198 be preserved. |
2196 |
2199 |
2197 Returns a str holding uncompressed data for the requested revision. |
2200 Returns a str holding uncompressed data for the requested revision. |
2198 """ |
2201 """ |
2199 compression_mode = self.index[rev][10] |
2202 compression_mode = self.index[rev][10] |
2200 data = self._getsegmentforrevs(rev, rev)[1] |
2203 data = self._inner.get_segment_for_revs(rev, rev)[1] |
2201 if compression_mode == COMP_MODE_PLAIN: |
2204 if compression_mode == COMP_MODE_PLAIN: |
2202 return data |
2205 return data |
2203 elif compression_mode == COMP_MODE_DEFAULT: |
2206 elif compression_mode == COMP_MODE_DEFAULT: |
2204 return self._decompressor(data) |
2207 return self._decompressor(data) |
2205 elif compression_mode == COMP_MODE_INLINE: |
2208 elif compression_mode == COMP_MODE_INLINE: |
2246 for lastrev in revschunk[::-1]: |
2249 for lastrev in revschunk[::-1]: |
2247 if length(lastrev) != 0: |
2250 if length(lastrev) != 0: |
2248 break |
2251 break |
2249 |
2252 |
2250 try: |
2253 try: |
2251 offset, data = self._getsegmentforrevs(firstrev, lastrev) |
2254 offset, data = self._inner.get_segment_for_revs( |
|
2255 firstrev, |
|
2256 lastrev, |
|
2257 ) |
2252 except OverflowError: |
2258 except OverflowError: |
2253 # issue4215 - we can't cache a run of chunks greater than |
2259 # issue4215 - we can't cache a run of chunks greater than |
2254 # 2G on Windows |
2260 # 2G on Windows |
2255 return [self._chunk(rev) for rev in revschunk] |
2261 return [self._chunk(rev) for rev in revschunk] |
2256 |
2262 |
2614 new_dfh = self._datafp(b'w+') |
2620 new_dfh = self._datafp(b'w+') |
2615 new_dfh.truncate(0) # drop any potentially existing data |
2621 new_dfh.truncate(0) # drop any potentially existing data |
2616 try: |
2622 try: |
2617 with self.reading(): |
2623 with self.reading(): |
2618 for r in self: |
2624 for r in self: |
2619 new_dfh.write(self._getsegmentforrevs(r, r)[1]) |
2625 new_dfh.write(self._inner.get_segment_for_revs(r, r)[1]) |
2620 new_dfh.flush() |
2626 new_dfh.flush() |
2621 |
2627 |
2622 if side_write: |
2628 if side_write: |
2623 self._indexfile = new_index_file_path |
2629 self._indexfile = new_index_file_path |
2624 self._inner.index_file = self._indexfile |
2630 self._inner.index_file = self._indexfile |