##// END OF EJS Templates
revlog: introduce v2 format...
Raphaël Gomès -
r47438:91348577 default
parent child Browse files
Show More
@@ -233,10 +233,61 b' class InlinedIndexObject(BaseIndexObject'
233 return self._offsets[i]
233 return self._offsets[i]
234
234
235
235
236 def parse_index2(data, inline):
236 def parse_index2(data, inline, revlogv2=False):
237 if not inline:
237 if not inline:
238 return IndexObject(data), None
238 cls = IndexObject2 if revlogv2 else IndexObject
239 return InlinedIndexObject(data, inline), (0, data)
239 return cls(data), None
240 cls = InlinedIndexObject2 if revlogv2 else InlinedIndexObject
241 return cls(data, inline), (0, data)
242
243
244 class Index2Mixin(object):
245 # 6 bytes: offset
246 # 2 bytes: flags
247 # 4 bytes: compressed length
248 # 4 bytes: uncompressed length
249 # 4 bytes: base rev
250 # 4 bytes: link rev
251 # 4 bytes: parent 1 rev
252 # 4 bytes: parent 2 rev
253 # 32 bytes: nodeid
254 # 8 bytes: sidedata offset
255 # 4 bytes: sidedata compressed length
256 # 20 bytes: Padding to align to 96 bytes (see RevlogV2Plan wiki page)
257 index_format = b">Qiiiiii20s12xQi20x"
258 index_size = struct.calcsize(index_format)
259 assert index_size == 96, index_size
260 null_item = (0, 0, 0, -1, -1, -1, -1, nullid, 0, 0)
261
262
263 class IndexObject2(Index2Mixin, IndexObject):
264 pass
265
266
267 class InlinedIndexObject2(Index2Mixin, InlinedIndexObject):
268 def _inline_scan(self, lgt):
269 sidedata_length_pos = 72
270 off = 0
271 if lgt is not None:
272 self._offsets = [0] * lgt
273 count = 0
274 while off <= len(self._data) - self.index_size:
275 start = off + self.big_int_size
276 (data_size,) = struct.unpack(
277 b'>i',
278 self._data[start : start + self.int_size],
279 )
280 start = off + sidedata_length_pos
281 (side_data_size,) = struct.unpack(
282 b'>i', self._data[start : start + self.int_size]
283 )
284 if lgt is not None:
285 self._offsets[count] = off
286 count += 1
287 off += self.index_size + data_size + side_data_size
288 if off != len(self._data):
289 raise ValueError(b"corrupted data")
290 return count
240
291
241
292
242 def parse_index_devel_nodemap(data, inline):
293 def parse_index_devel_nodemap(data, inline):
@@ -30,7 +30,7 b" REVLOGV1_REQUIREMENT = b'revlogv1'"
30
30
31 # Increment the sub-version when the revlog v2 format changes to lock out old
31 # Increment the sub-version when the revlog v2 format changes to lock out old
32 # clients.
32 # clients.
33 REVLOGV2_REQUIREMENT = b'exp-revlogv2.1'
33 REVLOGV2_REQUIREMENT = b'exp-revlogv2.2'
34
34
35 # A repository with the sparserevlog feature will have delta chains that
35 # A repository with the sparserevlog feature will have delta chains that
36 # can spread over a larger span. Sparse reading cuts these large spans into
36 # can spread over a larger span. Sparse reading cuts these large spans into
@@ -83,6 +83,7 b' from .utils import ('
83 storageutil,
83 storageutil,
84 stringutil,
84 stringutil,
85 )
85 )
86 from .pure import parsers as pureparsers
86
87
87 # blanked usage of all the name to prevent pyflakes constraints
88 # blanked usage of all the name to prevent pyflakes constraints
88 # We need these name available in the module for extensions.
89 # We need these name available in the module for extensions.
@@ -364,6 +365,25 b' class revlogio(object):'
364 return p
365 return p
365
366
366
367
368 indexformatv2 = struct.Struct(pureparsers.Index2Mixin.index_format)
369 indexformatv2_pack = indexformatv2.pack
370
371
372 class revlogv2io(object):
373 def __init__(self):
374 self.size = indexformatv2.size
375
376 def parseindex(self, data, inline):
377 index, cache = parsers.parse_index2(data, inline, revlogv2=True)
378 return index, cache
379
380 def packentry(self, entry, node, version, rev):
381 p = indexformatv2_pack(*entry)
382 if rev == 0:
383 p = versionformat_pack(version) + p[4:]
384 return p
385
386
367 NodemapRevlogIO = None
387 NodemapRevlogIO = None
368
388
369 if util.safehasattr(parsers, 'parse_index_devel_nodemap'):
389 if util.safehasattr(parsers, 'parse_index_devel_nodemap'):
@@ -650,6 +670,8 b' class revlog(object):'
650 self._io = revlogio()
670 self._io = revlogio()
651 if self.version == REVLOGV0:
671 if self.version == REVLOGV0:
652 self._io = revlogoldio()
672 self._io = revlogoldio()
673 elif fmt == REVLOGV2:
674 self._io = revlogv2io()
653 elif devel_nodemap:
675 elif devel_nodemap:
654 self._io = NodemapRevlogIO()
676 self._io = NodemapRevlogIO()
655 elif use_rust_index:
677 elif use_rust_index:
@@ -2337,7 +2359,13 b' class revlog(object):'
2337 p1r,
2359 p1r,
2338 p2r,
2360 p2r,
2339 node,
2361 node,
2362 0,
2363 0,
2340 )
2364 )
2365
2366 if self.version & 0xFFFF != REVLOGV2:
2367 e = e[:8]
2368
2341 self.index.append(e)
2369 self.index.append(e)
2342
2370
2343 entry = self._io.packentry(e, self.node, self.version, curr)
2371 entry = self._io.packentry(e, self.node, self.version, curr)
@@ -15,7 +15,6 b' from ..interfaces import repository'
15 REVLOGV0 = 0
15 REVLOGV0 = 0
16 REVLOGV1 = 1
16 REVLOGV1 = 1
17 # Dummy value until file format is finalized.
17 # Dummy value until file format is finalized.
18 # Reminder: change the bounds check in revlog.__init__ when this is changed.
19 REVLOGV2 = 0xDEAD
18 REVLOGV2 = 0xDEAD
20 # Shared across v1 and v2.
19 # Shared across v1 and v2.
21 FLAG_INLINE_DATA = 1 << 16
20 FLAG_INLINE_DATA = 1 << 16
@@ -117,8 +117,8 b' data_non_inlined = ('
117 )
117 )
118
118
119
119
120 def parse_index2(data, inline):
120 def parse_index2(data, inline, revlogv2=False):
121 index, chunkcache = parsers.parse_index2(data, inline)
121 index, chunkcache = parsers.parse_index2(data, inline, revlogv2=revlogv2)
122 return list(index), chunkcache
122 return list(index), chunkcache
123
123
124
124
@@ -22,7 +22,7 b' Can create and open repo with revlog v2 '
22 $ cd empty-repo
22 $ cd empty-repo
23 $ cat .hg/requires
23 $ cat .hg/requires
24 dotencode
24 dotencode
25 exp-revlogv2.1
25 exp-revlogv2.2
26 fncache
26 fncache
27 sparserevlog
27 sparserevlog
28 store
28 store
@@ -22,10 +22,10 b' Unknown flags on revlog version 1 are re'
22 Unknown version is rejected
22 Unknown version is rejected
23
23
24 >>> with open('.hg/store/00changelog.i', 'wb') as fh:
24 >>> with open('.hg/store/00changelog.i', 'wb') as fh:
25 ... fh.write(b'\x00\x00\x00\x02') and None
25 ... fh.write(b'\x00\x00\xbe\xef') and None
26
26
27 $ hg log
27 $ hg log
28 abort: unknown version (2) in revlog 00changelog.i
28 abort: unknown version (48879) in revlog 00changelog.i
29 [50]
29 [50]
30
30
31 $ cd ..
31 $ cd ..
General Comments 0
You need to be logged in to leave comments. Login now