From 6e933ac7df2fbdd5918585d9c72026840a09c986 Mon Sep 17 00:00:00 2001 From: Harmen Stoppels Date: Thu, 3 Aug 2023 14:13:13 +0200 Subject: repo cache: use -inf default instead of 0 (#39214) FastPackageChecker.modified_since should use a default number < 0 When the repo cache does not exist, Spack uses mtime 0. This causes the repo cache not to be generated when the repo has mtime 0. Some popular package managers such as spack use 0 mtime normalization for reproducible tarballs. So when installing spack with spack from a buildcache, the repo cache doesn't generate Also add some typehints --- lib/spack/spack/repo.py | 42 +++++++++++++++++--------------------- lib/spack/spack/util/file_cache.py | 10 ++++----- 2 files changed, 24 insertions(+), 28 deletions(-) (limited to 'lib') diff --git a/lib/spack/spack/repo.py b/lib/spack/spack/repo.py index 0b61c913cc..f301f13e8c 100644 --- a/lib/spack/spack/repo.py +++ b/lib/spack/spack/repo.py @@ -24,7 +24,7 @@ import sys import traceback import types import uuid -from typing import Dict, Union +from typing import Any, Dict, List, Union import llnl.util.filesystem as fs import llnl.util.lang @@ -422,7 +422,7 @@ class FastPackageChecker(collections.abc.Mapping): def last_mtime(self): return max(sinfo.st_mtime for sinfo in self._packages_to_stats.values()) - def modified_since(self, since): + def modified_since(self, since: float) -> List[str]: return [name for name, sinfo in self._packages_to_stats.items() if sinfo.st_mtime > since] def __getitem__(self, item): @@ -548,35 +548,34 @@ class RepoIndex: when they're needed. ``Indexers`` should be added to the ``RepoIndex`` using - ``add_index(name, indexer)``, and they should support the interface + ``add_indexer(name, indexer)``, and they should support the interface defined by ``Indexer``, so that the ``RepoIndex`` can read, generate, and update stored indices. - Generated indexes are accessed by name via ``__getitem__()``. + Generated indexes are accessed by name via ``__getitem__()``.""" - """ - - def __init__(self, package_checker, namespace, cache): + def __init__( + self, + package_checker: FastPackageChecker, + namespace: str, + cache: spack.util.file_cache.FileCache, + ): self.checker = package_checker self.packages_path = self.checker.packages_path if sys.platform == "win32": self.packages_path = spack.util.path.convert_to_posix_path(self.packages_path) self.namespace = namespace - self.indexers = {} - self.indexes = {} + self.indexers: Dict[str, Indexer] = {} + self.indexes: Dict[str, Any] = {} self.cache = cache - def add_indexer(self, name, indexer): + def add_indexer(self, name: str, indexer: Indexer): """Add an indexer to the repo index. Arguments: - name (str): name of this indexer - - indexer (object): an object that supports create(), read(), - write(), and get_index() operations - - """ + name: name of this indexer + indexer: object implementing the ``Indexer`` interface""" self.indexers[name] = indexer def __getitem__(self, name): @@ -597,17 +596,15 @@ class RepoIndex: because the main bottleneck here is loading all the packages. It can take tens of seconds to regenerate sequentially, and we'd rather only pay that cost once rather than on several - invocations. - - """ + invocations.""" for name, indexer in self.indexers.items(): self.indexes[name] = self._build_index(name, indexer) - def _build_index(self, name, indexer): + def _build_index(self, name: str, indexer: Indexer): """Determine which packages need an update, and update indexes.""" # Filename of the provider index cache (we assume they're all json) - cache_filename = "{0}/{1}-index.json".format(name, self.namespace) + cache_filename = f"{name}/{self.namespace}-index.json" # Compute which packages needs to be updated in the cache index_mtime = self.cache.mtime(cache_filename) @@ -631,8 +628,7 @@ class RepoIndex: needs_update = self.checker.modified_since(new_index_mtime) for pkg_name in needs_update: - namespaced_name = "%s.%s" % (self.namespace, pkg_name) - indexer.update(namespaced_name) + indexer.update(f"{self.namespace}.{pkg_name}") indexer.write(new) diff --git a/lib/spack/spack/util/file_cache.py b/lib/spack/spack/util/file_cache.py index 9c3b09c216..2b98f29199 100644 --- a/lib/spack/spack/util/file_cache.py +++ b/lib/spack/spack/util/file_cache.py @@ -4,6 +4,7 @@ # SPDX-License-Identifier: (Apache-2.0 OR MIT) import errno +import math import os import shutil @@ -151,18 +152,17 @@ class FileCache: return WriteTransaction(self._get_lock(key), acquire=WriteContextManager) - def mtime(self, key): - """Return modification time of cache file, or 0 if it does not exist. + def mtime(self, key) -> float: + """Return modification time of cache file, or -inf if it does not exist. Time is in units returned by os.stat in the mtime field, which is platform-dependent. """ if not self.init_entry(key): - return 0 + return -math.inf else: - sinfo = os.stat(self.cache_path(key)) - return sinfo.st_mtime + return os.stat(self.cache_path(key)).st_mtime def remove(self, key): file = self.cache_path(key) -- cgit v1.2.3-60-g2f50