Source code for craft_parts.sources.cache

# -*- Mode:Python; indent-tabs-mode:nil; tab-width:4 -*-
#
# Copyright 2016-2021 Canonical Ltd.
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License version 3 as published by the Free Software Foundation.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
# Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.

"""Cache base and file cache."""

import logging
import shutil
from pathlib import Path
from typing import Optional

logger = logging.getLogger(__name__)


[docs]class FileCache: """Cache files based on the supplied key.""" def __init__(self, cache_dir: Path, *, namespace: str = "files") -> None: """Create a FileCache under namespace. :param str namespace: The namespace for the cache (default is "files"). """ self.file_cache = Path(cache_dir, namespace)
[docs] def cache(self, *, filename: str, key: str) -> Optional[Path]: """Cache a file revision with hash in XDG cache, unless it already exists. :param filename: The path to the file to cache. :param key: The key to cache the file under. :return: The path to the cached file, or None if the file was not cached. """ cached_file_path = self.file_cache / key cached_file_path.parent.mkdir(parents=True, exist_ok=True) try: if not cached_file_path.is_file(): shutil.copyfile(filename, cached_file_path) except OSError: logger.warning("Unable to cache file %s.", cached_file_path) return None return cached_file_path
[docs] def get(self, *, key: str) -> Optional[Path]: """Get the filepath which matches the hash calculated with algorithm. :param key: The key used to cache the file. :return: The path to cached file, or None if the file is not cached. """ cached_file_path = self.file_cache / key if cached_file_path.is_file(): logger.debug("Cache hit for key %s", key) return cached_file_path return None
[docs] def clean(self) -> None: """Remove all files from the cache namespace.""" shutil.rmtree(self.file_cache)