comparison mercurial/revlog.py @ 43525:845e5b313783

revlog: move the nodemap into the index object (for pure) This make the pure code closer to the C extension one. The ultimate goal is to merge the two into a single object and offer a unified API. This changeset focus on gathering the data on the same object. For now the code for `revlogoldindex` and `BaseIndexObject` index object are quite similar. However, there will be larger divergence later on, so I don't think is worth doing a base case. This work is part of a refactoring to unify the revlog index and the nodemap. This unification prepare the use of a persistent nodemap. Differential Revision: https://phab.mercurial-scm.org/D7313
author Pierre-Yves David <pierre-yves.david@octobus.net>
date Wed, 06 Nov 2019 14:13:19 +0100
parents a7c0c5b5a50f
children e258ad110488
comparison
equal deleted inserted replaced
43524:a7c0c5b5a50f 43525:845e5b313783
203 indexformatv0_pack = indexformatv0.pack 203 indexformatv0_pack = indexformatv0.pack
204 indexformatv0_unpack = indexformatv0.unpack 204 indexformatv0_unpack = indexformatv0.unpack
205 205
206 206
207 class revlogoldindex(list): 207 class revlogoldindex(list):
208 @util.propertycache
209 def nodemap(self):
210 nodemap = revlogutils.NodeMap({nullid: nullrev})
211 for r in range(0, len(self)):
212 n = self[r][7]
213 nodemap[n] = r
214 return nodemap
215
216 def clearcaches(self):
217 self.__dict__.pop('nodemap', None)
218
208 def __getitem__(self, i): 219 def __getitem__(self, i):
209 if i == -1: 220 if i == -1:
210 return (0, 0, 0, -1, -1, -1, -1, nullid) 221 return (0, 0, 0, -1, -1, -1, -1, nullid)
211 return list.__getitem__(self, i) 222 return list.__getitem__(self, i)
212 223
238 ) 249 )
239 index.append(e2) 250 index.append(e2)
240 nodemap[e[6]] = n 251 nodemap[e[6]] = n
241 n += 1 252 n += 1
242 253
243 return revlogoldindex(index), nodemap, None 254 index = revlogoldindex(index)
255 return index, index.nodemap, None
244 256
245 def packentry(self, entry, node, version, rev): 257 def packentry(self, entry, node, version, rev):
246 if gettype(entry[0]): 258 if gettype(entry[0]):
247 raise error.RevlogError( 259 raise error.RevlogError(
248 _(b'index entry flags need revlog version 1') 260 _(b'index entry flags need revlog version 1')
285 self.size = indexformatng.size 297 self.size = indexformatng.size
286 298
287 def parseindex(self, data, inline): 299 def parseindex(self, data, inline):
288 # call the C implementation to parse the index data 300 # call the C implementation to parse the index data
289 index, cache = parsers.parse_index2(data, inline) 301 index, cache = parsers.parse_index2(data, inline)
290 return index, getattr(index, 'nodemap', None), cache 302 return index, index.nodemap, cache
291 303
292 def packentry(self, entry, node, version, rev): 304 def packentry(self, entry, node, version, rev):
293 p = indexformatng_pack(*entry) 305 p = indexformatng_pack(*entry)
294 if rev == 0: 306 if rev == 0:
295 p = versionformat_pack(version) + p[4:] 307 p = versionformat_pack(version) + p[4:]
370 self._chunkcache = (0, b'') 382 self._chunkcache = (0, b'')
371 # How much data to read and cache into the raw revlog data cache. 383 # How much data to read and cache into the raw revlog data cache.
372 self._chunkcachesize = 65536 384 self._chunkcachesize = 65536
373 self._maxchainlen = None 385 self._maxchainlen = None
374 self._deltabothparents = True 386 self._deltabothparents = True
375 self.index = [] 387 self.index = None
376 # Mapping of partial identifiers to full nodes. 388 # Mapping of partial identifiers to full nodes.
377 self._pcache = {} 389 self._pcache = {}
378 # Mapping of revision integer to full node. 390 # Mapping of revision integer to full node.
379 self._nodecache = revlogutils.NodeMap({nullid: nullrev}) 391 self._nodecache = None
380 self._nodepos = None 392 self._nodepos = None
381 self._compengine = b'zlib' 393 self._compengine = b'zlib'
382 self._compengineopts = {} 394 self._compengineopts = {}
383 self._maxdeltachainspan = -1 395 self._maxdeltachainspan = -1
384 self._withsparseread = False 396 self._withsparseread = False
539 except (ValueError, IndexError): 551 except (ValueError, IndexError):
540 raise error.RevlogError( 552 raise error.RevlogError(
541 _(b"index %s is corrupted") % self.indexfile 553 _(b"index %s is corrupted") % self.indexfile
542 ) 554 )
543 self.index, nodemap, self._chunkcache = d 555 self.index, nodemap, self._chunkcache = d
544 if nodemap is not None: 556 self.nodemap = self._nodecache = nodemap
545 self.nodemap = self._nodecache = nodemap
546 if not self._chunkcache: 557 if not self._chunkcache:
547 self._chunkclear() 558 self._chunkclear()
548 # revnum -> (chain-length, sum-delta-length) 559 # revnum -> (chain-length, sum-delta-length)
549 self._chaininfocache = {} 560 self._chaininfocache = {}
550 # revlog header -> revlog compressor 561 # revlog header -> revlog compressor
644 def clearcaches(self): 655 def clearcaches(self):
645 self._revisioncache = None 656 self._revisioncache = None
646 self._chainbasecache.clear() 657 self._chainbasecache.clear()
647 self._chunkcache = (0, b'') 658 self._chunkcache = (0, b'')
648 self._pcache = {} 659 self._pcache = {}
649 660 self.index.clearcaches()
650 try:
651 # If we are using the native C version, you are in a fun case
652 # where self.index, self.nodemap and self._nodecaches is the same
653 # object.
654 self._nodecache.clearcaches()
655 except AttributeError:
656 self._nodecache = revlogutils.NodeMap({nullid: nullrev})
657 self._nodepos = None
658 661
659 def rev(self, node): 662 def rev(self, node):
660 try: 663 try:
661 return self._nodecache[node] 664 return self._nodecache[node]
662 except TypeError: 665 except TypeError:
663 raise 666 raise
664 except error.RevlogError: 667 except error.RevlogError:
665 if not isinstance(self._nodecache, revlogutils.NodeMap): 668 # parsers.c radix tree lookup failed
666 # parsers.c radix tree lookup failed 669 if node == wdirid or node in wdirfilenodeids:
667 if node == wdirid or node in wdirfilenodeids: 670 raise error.WdirUnsupported
668 raise error.WdirUnsupported 671 raise error.LookupError(node, self.indexfile, _(b'no node'))
669 raise error.LookupError(node, self.indexfile, _(b'no node'))
670 else:
671 # pure python cache lookup failed
672 n = self._nodecache
673 i = self.index
674 p = self._nodepos
675 if p is None:
676 p = len(i) - 1
677 else:
678 assert p < len(i)
679 for r in pycompat.xrange(p, -1, -1):
680 v = i[r][7]
681 n[v] = r
682 if v == node:
683 self._nodepos = r - 1
684 return r
685 if node == wdirid or node in wdirfilenodeids:
686 raise error.WdirUnsupported
687 raise error.LookupError(node, self.indexfile, _(b'no node'))
688 672
689 # Accessors for index entries. 673 # Accessors for index entries.
690 674
691 # First tuple entry is 8 bytes. First 6 bytes are offset. Last 2 bytes 675 # First tuple entry is 8 bytes. First 6 bytes are offset. Last 2 bytes
692 # are flags. 676 # are flags.