Mercurial > public > mercurial-scm > hg
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. |