comparison mercurial/revlog.py @ 47075:0d8ff1f4ab0c

revlog: add a `entry_binary` method on index The revlog index is already responsible for unpacking the binary entry, it would be simpler to make it responsible for packing them. In practice the C version of the index is already doing this internally. We introduce a "entry_binary" method that return the binary version of an existing revision. The method currently need to also take the revlog header to deal with the "first revision" special case. We will introduce further refactor in a later changeset to split that logic out. Differential Revision: https://phab.mercurial-scm.org/D10508
author Pierre-Yves David <pierre-yves.david@octobus.net>
date Thu, 08 Apr 2021 00:01:11 +0200
parents d55b71393907
children 5e64c93d5f94
comparison
equal deleted inserted replaced
47074:824ee4aaa09b 47075:0d8ff1f4ab0c
266 def __getitem__(self, i): 266 def __getitem__(self, i):
267 if i == -1: 267 if i == -1:
268 return (0, 0, 0, -1, -1, -1, -1, sha1nodeconstants.nullid) 268 return (0, 0, 0, -1, -1, -1, -1, sha1nodeconstants.nullid)
269 return list.__getitem__(self, i) 269 return list.__getitem__(self, i)
270 270
271 def entry_binary(self, rev, header):
272 """return the raw binary string representing a revision"""
273 entry = self[rev]
274 if gettype(entry[0]):
275 raise error.RevlogError(
276 _(b'index entry flags need revlog version 1')
277 )
278 e2 = (
279 getoffset(entry[0]),
280 entry[1],
281 entry[3],
282 entry[4],
283 self[entry[5]][7],
284 self[entry[6]][7],
285 entry[7],
286 )
287 return INDEX_ENTRY_V0.pack(*e2)
288
271 289
272 class revlogoldio(object): 290 class revlogoldio(object):
273 def parseindex(self, data, inline): 291 def parseindex(self, data, inline):
274 s = INDEX_ENTRY_V0.size 292 s = INDEX_ENTRY_V0.size
275 index = [] 293 index = []
296 n += 1 314 n += 1
297 315
298 index = revlogoldindex(index) 316 index = revlogoldindex(index)
299 return index, None 317 return index, None
300 318
301 def packentry(self, entry, node, version, rev):
302 """return the binary representation of an entry
303
304 entry: a tuple containing all the values (see index.__getitem__)
305 node: a callback to convert a revision to nodeid
306 version: the changelog version
307 rev: the revision number
308 """
309 if gettype(entry[0]):
310 raise error.RevlogError(
311 _(b'index entry flags need revlog version 1')
312 )
313 e2 = (
314 getoffset(entry[0]),
315 entry[1],
316 entry[3],
317 entry[4],
318 node(entry[5]),
319 node(entry[6]),
320 entry[7],
321 )
322 return INDEX_ENTRY_V0.pack(*e2)
323
324 319
325 # corresponds to uncompressed length of indexformatng (2 gigs, 4-byte 320 # corresponds to uncompressed length of indexformatng (2 gigs, 4-byte
326 # signed integer) 321 # signed integer)
327 _maxentrysize = 0x7FFFFFFF 322 _maxentrysize = 0x7FFFFFFF
328 323
331 def parseindex(self, data, inline): 326 def parseindex(self, data, inline):
332 # call the C implementation to parse the index data 327 # call the C implementation to parse the index data
333 index, cache = parsers.parse_index2(data, inline) 328 index, cache = parsers.parse_index2(data, inline)
334 return index, cache 329 return index, cache
335 330
336 def packentry(self, entry, node, version, rev):
337 p = INDEX_ENTRY_V1.pack(*entry)
338 if rev == 0:
339 p = INDEX_HEADER.pack(version) + p[4:]
340 return p
341
342 331
343 class revlogv2io(object): 332 class revlogv2io(object):
344 def parseindex(self, data, inline): 333 def parseindex(self, data, inline):
345 index, cache = parsers.parse_index2(data, inline, revlogv2=True) 334 index, cache = parsers.parse_index2(data, inline, revlogv2=True)
346 return index, cache 335 return index, cache
347
348 def packentry(self, entry, node, version, rev):
349 p = INDEX_ENTRY_V2.pack(*entry)
350 if rev == 0:
351 p = INDEX_HEADER.pack(version) + p[4:]
352 return p
353 336
354 337
355 NodemapRevlogIO = None 338 NodemapRevlogIO = None
356 339
357 if util.safehasattr(parsers, 'parse_index_devel_nodemap'): 340 if util.safehasattr(parsers, 'parse_index_devel_nodemap'):
2066 with self._indexfp(b'w') as fp: 2049 with self._indexfp(b'w') as fp:
2067 self.version &= ~FLAG_INLINE_DATA 2050 self.version &= ~FLAG_INLINE_DATA
2068 self._inline = False 2051 self._inline = False
2069 io = self._io 2052 io = self._io
2070 for i in self: 2053 for i in self:
2071 e = io.packentry(self.index[i], self.node, self.version, i) 2054 e = self.index.entry_binary(i, self.version)
2072 fp.write(e) 2055 fp.write(e)
2073 2056
2074 # the temp file replace the real index when we exit the context 2057 # the temp file replace the real index when we exit the context
2075 # manager 2058 # manager
2076 2059
2388 2371
2389 if self.version & 0xFFFF != REVLOGV2: 2372 if self.version & 0xFFFF != REVLOGV2:
2390 e = e[:8] 2373 e = e[:8]
2391 2374
2392 self.index.append(e) 2375 self.index.append(e)
2393 entry = self._io.packentry(e, self.node, self.version, curr) 2376 entry = self.index.entry_binary(curr, self.version)
2394 self._writeentry( 2377 self._writeentry(
2395 transaction, 2378 transaction,
2396 ifh, 2379 ifh,
2397 dfh, 2380 dfh,
2398 entry, 2381 entry,
3241 with self._indexfp(b'w+') as fp: 3224 with self._indexfp(b'w+') as fp:
3242 fp.seek(startrev * self.index.entry_size) 3225 fp.seek(startrev * self.index.entry_size)
3243 for i, entry in enumerate(new_entries): 3226 for i, entry in enumerate(new_entries):
3244 rev = startrev + i 3227 rev = startrev + i
3245 self.index.replace_sidedata_info(rev, entry[8], entry[9]) 3228 self.index.replace_sidedata_info(rev, entry[8], entry[9])
3246 packed = self._io.packentry(entry, self.node, self.version, rev) 3229 packed = self.index.entry_binary(rev, self.version)
3247 fp.write(packed) 3230 fp.write(packed)