Mercurial > hg
comparison mercurial/store.py @ 50473:5a2fb64d38b2
store: use specialized class for store entries
We introduce two different classes for revlog and other entries. For now, we
still have multiple entry for the same revlog, but we will work toward grouping
the different file in a single entry in this series.
Having the distinction is a step toward this goal.
author | Pierre-Yves David <pierre-yves.david@octobus.net> |
---|---|
date | Mon, 15 May 2023 08:56:56 +0200 |
parents | 9fdc28e21b68 |
children | c37450a5f1dc |
comparison
equal
deleted
inserted
replaced
50472:9fdc28e21b68 | 50473:5a2fb64d38b2 |
---|---|
452 FILETYPE_FILELOG_OTHER = FILEFLAGS_FILELOG | FILEFLAGS_REVLOG_OTHER | 452 FILETYPE_FILELOG_OTHER = FILEFLAGS_FILELOG | FILEFLAGS_REVLOG_OTHER |
453 FILETYPE_OTHER = FILEFLAGS_OTHER | 453 FILETYPE_OTHER = FILEFLAGS_OTHER |
454 | 454 |
455 | 455 |
456 @attr.s(slots=True) | 456 @attr.s(slots=True) |
457 class StoreEntry: | 457 class BaseStoreEntry: |
458 """An entry in the store | 458 """An entry in the store |
459 | 459 |
460 This is returned by `store.walk` and represent some data in the store.""" | 460 This is returned by `store.walk` and represent some data in the store.""" |
461 | 461 |
462 unencoded_path = attr.ib() | 462 unencoded_path = attr.ib() |
463 is_revlog = attr.ib(default=False) | |
464 revlog_type = attr.ib(default=None) | |
465 is_revlog_main = attr.ib(default=None) | |
466 is_volatile = attr.ib(default=False) | 463 is_volatile = attr.ib(default=False) |
467 file_size = attr.ib(default=None) | 464 file_size = attr.ib(default=None) |
468 | 465 |
469 def files(self): | 466 def files(self): |
470 return [ | 467 return [ |
472 unencoded_path=self.unencoded_path, | 469 unencoded_path=self.unencoded_path, |
473 file_size=self.file_size, | 470 file_size=self.file_size, |
474 is_volatile=self.is_volatile, | 471 is_volatile=self.is_volatile, |
475 ) | 472 ) |
476 ] | 473 ] |
474 | |
475 | |
476 @attr.s(slots=True) | |
477 class SimpleStoreEntry(BaseStoreEntry): | |
478 """A generic entry in the store""" | |
479 | |
480 is_revlog = False | |
481 | |
482 | |
483 @attr.s(slots=True) | |
484 class RevlogStoreEntry(BaseStoreEntry): | |
485 """A revlog entry in the store""" | |
486 | |
487 is_revlog = True | |
488 revlog_type = attr.ib(default=None) | |
489 is_revlog_main = attr.ib(default=None) | |
477 | 490 |
478 | 491 |
479 @attr.s(slots=True) | 492 @attr.s(slots=True) |
480 class StoreFile: | 493 class StoreFile: |
481 """a file matching an entry""" | 494 """a file matching an entry""" |
534 rootstore = manifest.manifestrevlog(repo.nodeconstants, self.vfs) | 547 rootstore = manifest.manifestrevlog(repo.nodeconstants, self.vfs) |
535 return manifest.manifestlog(self.vfs, repo, rootstore, storenarrowmatch) | 548 return manifest.manifestlog(self.vfs, repo, rootstore, storenarrowmatch) |
536 | 549 |
537 def datafiles( | 550 def datafiles( |
538 self, matcher=None, undecodable=None | 551 self, matcher=None, undecodable=None |
539 ) -> Generator[StoreEntry, None, None]: | 552 ) -> Generator[BaseStoreEntry, None, None]: |
540 """Like walk, but excluding the changelog and root manifest. | 553 """Like walk, but excluding the changelog and root manifest. |
541 | 554 |
542 When [undecodable] is None, revlogs names that can't be | 555 When [undecodable] is None, revlogs names that can't be |
543 decoded cause an exception. When it is provided, it should | 556 decoded cause an exception. When it is provided, it should |
544 be a list and the filenames that can't be decoded are added | 557 be a list and the filenames that can't be decoded are added |
545 to it instead. This is very rarely needed.""" | 558 to it instead. This is very rarely needed.""" |
546 files = self._walk(b'data', True) + self._walk(b'meta', True) | 559 files = self._walk(b'data', True) + self._walk(b'meta', True) |
547 for (t, u, s) in files: | 560 for (t, u, s) in files: |
548 if t is not None: | 561 if t is not None: |
549 yield StoreEntry( | 562 yield RevlogStoreEntry( |
550 unencoded_path=u, | 563 unencoded_path=u, |
551 is_revlog=True, | |
552 revlog_type=FILEFLAGS_FILELOG, | 564 revlog_type=FILEFLAGS_FILELOG, |
553 is_revlog_main=bool(t & FILEFLAGS_REVLOG_MAIN), | 565 is_revlog_main=bool(t & FILEFLAGS_REVLOG_MAIN), |
554 is_volatile=bool(t & FILEFLAGS_VOLATILE), | 566 is_volatile=bool(t & FILEFLAGS_VOLATILE), |
555 file_size=s, | 567 file_size=s, |
556 ) | 568 ) |
557 | 569 |
558 def topfiles(self) -> Generator[StoreEntry, None, None]: | 570 def topfiles(self) -> Generator[BaseStoreEntry, None, None]: |
559 # yield manifest before changelog | 571 # yield manifest before changelog |
560 files = reversed(self._walk(b'', False)) | 572 files = reversed(self._walk(b'', False)) |
561 for (t, u, s) in files: | 573 for (t, u, s) in files: |
562 if u.startswith(b'00changelog'): | 574 if u.startswith(b'00changelog'): |
563 revlog_type = FILEFLAGS_CHANGELOG | 575 yield RevlogStoreEntry( |
576 unencoded_path=u, | |
577 revlog_type=FILEFLAGS_CHANGELOG, | |
578 is_revlog_main=bool(t & FILEFLAGS_REVLOG_MAIN), | |
579 is_volatile=bool(t & FILEFLAGS_VOLATILE), | |
580 file_size=s, | |
581 ) | |
564 elif u.startswith(b'00manifest'): | 582 elif u.startswith(b'00manifest'): |
565 revlog_type = FILEFLAGS_MANIFESTLOG | 583 yield RevlogStoreEntry( |
584 unencoded_path=u, | |
585 revlog_type=FILEFLAGS_MANIFESTLOG, | |
586 is_revlog_main=bool(t & FILEFLAGS_REVLOG_MAIN), | |
587 is_volatile=bool(t & FILEFLAGS_VOLATILE), | |
588 file_size=s, | |
589 ) | |
566 else: | 590 else: |
567 revlog_type = None | 591 yield SimpleStoreEntry( |
568 yield StoreEntry( | 592 unencoded_path=u, |
569 unencoded_path=u, | 593 is_volatile=bool(t & FILEFLAGS_VOLATILE), |
570 is_revlog=revlog_type is not None, | 594 file_size=s, |
571 revlog_type=revlog_type, | 595 ) |
572 is_revlog_main=bool(t & FILEFLAGS_REVLOG_MAIN), | 596 |
573 is_volatile=bool(t & FILEFLAGS_VOLATILE), | 597 def walk(self, matcher=None) -> Generator[BaseStoreEntry, None, None]: |
574 file_size=s, | |
575 ) | |
576 | |
577 def walk(self, matcher=None) -> Generator[StoreEntry, None, None]: | |
578 """return files related to data storage (ie: revlogs) | 598 """return files related to data storage (ie: revlogs) |
579 | 599 |
580 yields (file_type, unencoded, size) | 600 yields (file_type, unencoded, size) |
581 | 601 |
582 if a matcher is passed, storage files of only those tracked paths | 602 if a matcher is passed, storage files of only those tracked paths |
627 # However that might change so we should probably add a test and encoding | 647 # However that might change so we should probably add a test and encoding |
628 # decoding for it too. see issue6548 | 648 # decoding for it too. see issue6548 |
629 | 649 |
630 def datafiles( | 650 def datafiles( |
631 self, matcher=None, undecodable=None | 651 self, matcher=None, undecodable=None |
632 ) -> Generator[StoreEntry, None, None]: | 652 ) -> Generator[BaseStoreEntry, None, None]: |
633 for entry in super(encodedstore, self).datafiles(): | 653 for entry in super(encodedstore, self).datafiles(): |
634 try: | 654 try: |
635 f1 = entry.unencoded_path | 655 f1 = entry.unencoded_path |
636 f2 = decodefilename(f1) | 656 f2 = decodefilename(f1) |
637 except KeyError: | 657 except KeyError: |
840 def getsize(self, path): | 860 def getsize(self, path): |
841 return self.rawvfs.stat(path).st_size | 861 return self.rawvfs.stat(path).st_size |
842 | 862 |
843 def datafiles( | 863 def datafiles( |
844 self, matcher=None, undecodable=None | 864 self, matcher=None, undecodable=None |
845 ) -> Generator[StoreEntry, None, None]: | 865 ) -> Generator[BaseStoreEntry, None, None]: |
846 for f in sorted(self.fncache): | 866 for f in sorted(self.fncache): |
847 if not _matchtrackedpath(f, matcher): | 867 if not _matchtrackedpath(f, matcher): |
848 continue | 868 continue |
849 ef = self.encode(f) | 869 ef = self.encode(f) |
850 t = revlog_type(f) | 870 t = revlog_type(f) |
852 # Note: this should not be in the fncache then… | 872 # Note: this should not be in the fncache then… |
853 # | 873 # |
854 # However the fncache might contains such file added by | 874 # However the fncache might contains such file added by |
855 # previous version of Mercurial. | 875 # previous version of Mercurial. |
856 continue | 876 continue |
857 t |= FILEFLAGS_FILELOG | |
858 try: | 877 try: |
859 yield StoreEntry( | 878 yield RevlogStoreEntry( |
860 unencoded_path=f, | 879 unencoded_path=f, |
861 is_revlog=True, | |
862 revlog_type=FILEFLAGS_FILELOG, | 880 revlog_type=FILEFLAGS_FILELOG, |
863 is_revlog_main=bool(t & FILEFLAGS_REVLOG_MAIN), | 881 is_revlog_main=bool(t & FILEFLAGS_REVLOG_MAIN), |
864 is_volatile=bool(t & FILEFLAGS_VOLATILE), | 882 is_volatile=bool(t & FILEFLAGS_VOLATILE), |
865 file_size=self.getsize(ef), | 883 file_size=self.getsize(ef), |
866 ) | 884 ) |