""" SPDX-FileCopyrightText: 2023-2025 PeppermintOS Team (peppermintosteam@proton.me) SPDX-License-Identifier: GPL-3.0-or-later This module provides functions for caching and downloading packages using xbps-install. It loads repository information from a YAML configuration file. Credits: - PeppermintOS Team (peppermintosteam@proton.me) - Development and maintenance of the project. License: This code is distributed under the GNU General Public License version 3 or later (GPL-3.0-or-later). For more details, please refer to the LICENSE file included in the project or visit: https://www.gnu.org/licenses/gpl-3.0.html """ import os import subprocess import shutil import logging import sys base_dir = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) sys.path.insert(0, base_dir) try: from builder.core.bootstrap.yaml_repo_loader import load_repositories_from_yaml from builder.configs import logger_config from builder.core.xbps_commands import xbps_commands from builder.core.bootstrap.paths import paths except ImportError as e: print(f"Error importing necessary modules: {e}. Ensure your environment is set up correctly. Details: {e}") sys.exit(1) logger = logger_config.setup_logger('cache') CACHE_DIR = paths["ISO_CACHE_DIR"] def get_or_download_package(package_name, architecture, yaml_file_path): """ Checks if a package is in the cache for the specified architecture. If not, it downloads the package to the cache using xbps-install. Repository information is loaded from a YAML file. Args: package_name (str): The name of the package to obtain. architecture (str): The target architecture (e.g., 'x86_64'). yaml_file_path (str): The path to the YAML file containing repository information. Returns: bool: True if the package is in the cache (or was downloaded), False on error. """ arch_cache_dir = os.path.join(CACHE_DIR, architecture) os.makedirs(arch_cache_dir, exist_ok=True) host_arch = os.uname().machine xbps_cachedir_env = os.path.join(os.getcwd(), CACHE_DIR, architecture) xbps_host_cachedir_env = os.path.join(os.getcwd(), CACHE_DIR, host_arch) env = os.environ.copy() env["XBPS_CACHEDIR"] = xbps_cachedir_env env["XBPS_HOST_CACHEDIR"] = xbps_host_cachedir_env env["XBPS_ARCH"] = architecture xbps_repository_arg = "" repositories_data = load_repositories_from_yaml(yaml_file_path) for repo in repositories_data.get('repositories', []): if architecture in repo.get('architectures', []): xbps_repository_arg += f"--repository={repo.get('uri')} " download_cmd = [xbps_commands["XBPS_INSTALL_CMD"], "-yn", "-c", xbps_cachedir_env] download_cmd.extend(xbps_repository_arg.split()) download_cmd.append(package_name) def sync_repositories(architecture, yaml_file_path): repositories_data = load_repositories_from_yaml(yaml_file_path) repo_urls = [] for repo in repositories_data.get('repositories', []): if architecture in repo.get('architectures', []): repo_urls.append(repo.get('uri')) if not repo_urls: logger.warning(f"No repositories found for architecture '{architecture}' in the YAML file to synchronize.") return xbps_repo_arg = "" for url in repo_urls: xbps_repo_arg += f"--repository={url} " rootfs_path = paths["ROOTFS"] sync_cmd = [xbps_commands["XBPS_INSTALL_CMD"], "-S", "-y", "-r", rootfs_path] sync_cmd.extend(xbps_repo_arg.split()) env = os.environ.copy() env["XBPS_ARCH"] = architecture try: logger.info(f"Synchronizing repository information for architecture '{architecture}' in rootfs '{rootfs_path}'...") logger.debug(f"Executing command: {' '.join(sync_cmd)}") result = subprocess.run(sync_cmd, env=env, check=True, text=True, capture_output=True) logger.debug(result.stdout) logger.info(f"Repository synchronization for '{architecture}' completed.") except subprocess.CalledProcessError as e: logger.error(f"Error synchronizing repositories for '{architecture}': {e}") if e.stderr: logger.error(f"Stderr from xbps-install: {e.stderr}") except FileNotFoundError: logger.error(f"Error: xbps-install command not found in: {xbps_commands['XBPS_INSTALL_CMD']}")