# Copyright (c) 2020 Egor Tensin # This file is part of the "cmake-common" project. # For details, see https://github.com/egor-tensin/cmake-common # Distributed under the MIT License. import abc from contextlib import contextmanager import logging import os.path import shutil from project.boost.directory import BoostDir from project import utils class Archive: def __init__(self, version, path): self.version = version self.path = path @property def dir_name(self): return self.version.dir_name def unpack(self, dest_dir): path = os.path.join(dest_dir, self.dir_name) if os.path.exists(path): raise RuntimeError(f"Boost directory already exists: {path}") logging.info("Unpacking Boost to: %s", path) shutil.unpack_archive(self.path, dest_dir) return BoostDir(path) class ArchiveStorage(abc.ABC): @abc.abstractmethod def get_archive(self, version): pass @contextmanager @abc.abstractmethod def write_archive(self, version, contents): pass class PermanentStorage(ArchiveStorage): def __init__(self, cache_dir): self._dir = cache_dir def _archive_path(self, version): return os.path.join(self._dir, version.archive_name) def get_archive(self, version): path = self._archive_path(version) if os.path.exists(path): return path return None @contextmanager def write_archive(self, version, contents): path = self._archive_path(version) logging.info("Writing Boost archive: %s", path) if os.path.exists(path): raise RuntimeError(f"cannot download Boost, file already exists: {path}") with open(path, mode="w+b") as dest: dest.write(contents) yield path class TemporaryStorage(ArchiveStorage): def __init__(self, temp_dir): self._dir = temp_dir def get_archive(self, version): return None @contextmanager def write_archive(self, version, contents): tmp = utils.temp_file( prefix=f"boost_{version}_", suffix=version.archive_ext, dir=self._dir ) with tmp as archive_path: with open(archive_path, mode="wb") as fd: fd.write(contents) yield archive_path