Mercurial > public > mercurial-scm > hg
diff mercurial/store.py @ 50468:521fec115dad
store: use a StoreEntry object instead of tuple for store files
We want to make the store return more semantic information instead of a stream
of file path. To achieve this, we start with adding a simple object that hold
the same information as the tuple it replace, and do a simple update to the
user code to fetch and use the same information.
From there, we will be able to iteratively upgrade the codebase toward better
objects.
author | Pierre-Yves David <pierre-yves.david@octobus.net> |
---|---|
date | Mon, 15 May 2023 08:56:23 +0200 |
parents | 53af67c70af0 |
children | 9fdc28e21b68 |
line wrap: on
line diff
--- a/mercurial/store.py Mon May 15 08:56:08 2023 +0200 +++ b/mercurial/store.py Mon May 15 08:56:23 2023 +0200 @@ -10,9 +10,11 @@ import os import re import stat +from typing import Generator from .i18n import _ from .pycompat import getattr +from .thirdparty import attr from .node import hex from . import ( changelog, @@ -451,6 +453,20 @@ FILETYPE_OTHER = FILEFLAGS_OTHER +@attr.s(slots=True) +class StoreEntry: + """An entry in the store + + This is returned by `store.walk` and represent some data in the store.""" + + unencoded_path = attr.ib() + is_revlog = attr.ib(default=False) + revlog_type = attr.ib(default=None) + is_revlog_main = attr.ib(default=None) + is_volatile = attr.ib(default=False) + file_size = attr.ib(default=None) + + class basicstore: '''base class for local repository stores''' @@ -500,7 +516,9 @@ rootstore = manifest.manifestrevlog(repo.nodeconstants, self.vfs) return manifest.manifestlog(self.vfs, repo, rootstore, storenarrowmatch) - def datafiles(self, matcher=None, undecodable=None): + def datafiles( + self, matcher=None, undecodable=None + ) -> Generator[StoreEntry, None, None]: """Like walk, but excluding the changelog and root manifest. When [undecodable] is None, revlogs names that can't be @@ -510,20 +528,35 @@ files = self._walk(b'data', True) + self._walk(b'meta', True) for (t, u, s) in files: if t is not None: - yield (FILEFLAGS_FILELOG | t, u, s) + yield StoreEntry( + unencoded_path=u, + is_revlog=True, + revlog_type=FILEFLAGS_FILELOG, + is_revlog_main=bool(t & FILEFLAGS_REVLOG_MAIN), + is_volatile=bool(t & FILEFLAGS_VOLATILE), + file_size=s, + ) - def topfiles(self): + def topfiles(self) -> Generator[StoreEntry, None, None]: # yield manifest before changelog files = reversed(self._walk(b'', False)) for (t, u, s) in files: if u.startswith(b'00changelog'): - yield (FILEFLAGS_CHANGELOG | t, u, s) + revlog_type = FILEFLAGS_CHANGELOG elif u.startswith(b'00manifest'): - yield (FILEFLAGS_MANIFESTLOG | t, u, s) + revlog_type = FILEFLAGS_MANIFESTLOG else: - yield (FILETYPE_OTHER | t, u, s) + revlog_type = None + yield StoreEntry( + unencoded_path=u, + is_revlog=revlog_type is not None, + revlog_type=revlog_type, + is_revlog_main=bool(t & FILEFLAGS_REVLOG_MAIN), + is_volatile=bool(t & FILEFLAGS_VOLATILE), + file_size=s, + ) - def walk(self, matcher=None): + def walk(self, matcher=None) -> Generator[StoreEntry, None, None]: """return files related to data storage (ie: revlogs) yields (file_type, unencoded, size) @@ -576,9 +609,12 @@ # However that might change so we should probably add a test and encoding # decoding for it too. see issue6548 - def datafiles(self, matcher=None, undecodable=None): - for t, f1, size in super(encodedstore, self).datafiles(): + def datafiles( + self, matcher=None, undecodable=None + ) -> Generator[StoreEntry, None, None]: + for entry in super(encodedstore, self).datafiles(): try: + f1 = entry.unencoded_path f2 = decodefilename(f1) except KeyError: if undecodable is None: @@ -589,7 +625,8 @@ continue if not _matchtrackedpath(f2, matcher): continue - yield t, f2, size + entry.unencoded_path = f2 + yield entry def join(self, f): return self.path + b'/' + encodefilename(f) @@ -785,7 +822,9 @@ def getsize(self, path): return self.rawvfs.stat(path).st_size - def datafiles(self, matcher=None, undecodable=None): + def datafiles( + self, matcher=None, undecodable=None + ) -> Generator[StoreEntry, None, None]: for f in sorted(self.fncache): if not _matchtrackedpath(f, matcher): continue @@ -799,7 +838,14 @@ continue t |= FILEFLAGS_FILELOG try: - yield t, f, self.getsize(ef) + yield StoreEntry( + unencoded_path=f, + is_revlog=True, + revlog_type=FILEFLAGS_FILELOG, + is_revlog_main=bool(t & FILEFLAGS_REVLOG_MAIN), + is_volatile=bool(t & FILEFLAGS_VOLATILE), + file_size=self.getsize(ef), + ) except FileNotFoundError: pass