builder_peppermint_void/builder/core/bootstrap/bootstrap.py
2025-04-27 18:55:44 +00:00

136 lines
6.1 KiB
Python

# builder/core/bootstrap.py (Apenas Construção de Argumentos)
import os
import logging
import platform
import sys
# shutil não é necessário neste ficheiro com esta estratégia
# base_dir e sys.path.insert são geralmente feitos no script principal
# from builder.core.bootstrap.paths import paths # Não é necessário importar paths aqui
try:
from builder.configs import logger_config
# from builder.core.command_runner import run_command # Não precisamos de run_command neste ficheiro com esta estratégia
except ImportError as e:
# Usar print ou logger básico se logger_config falhar
try:
basic_logger = logging.getLogger(__name__)
logging.basicConfig(level=logging.ERROR) # Configurar um logger básico para erro
basic_logger.error(f"Error importing necessary modules for bootstrap helper: {e}. Ensure your environment is set up correctly.")
except Exception:
print(f"Error importing necessary modules for bootstrap helper: {e}. Ensure your environment is set up correctly.")
sys.exit(1)
# Configurar logger para este módulo
try:
logger = logger_config.setup_logger('bootstrap')
except NameError:
# Fallback logger se logger_config não estiver disponível
logging.basicConfig(level=logging.INFO) # Nível INFO por padrão para este helper
logger = logging.getLogger('bootstrap')
def filter_repositories_by_architecture(repositories_data, target_architecture):
"""
Filters the list of repositories to include only those supporting the target architecture.
Args:
repositories_data (list): A list of repository dictionaries,
each potentially having an 'architectures' key.
target_architecture (str): The target architecture (e.g., 'aarch64', 'i686', 'x86_64').
Returns:
list: A list of '-R <uri>' strings for the relevant repositories.
"""
filtered_repo_args = []
if not isinstance(repositories_data, list):
logger.error("repositories_data must be a list.")
return []
for repo in repositories_data:
if not isinstance(repo, dict):
logger.warning(f"Repository entry is not a dictionary: {repo}. Skipping.")
continue
if 'uri' in repo and ('architectures' not in repo or target_architecture in repo['architectures']):
filtered_repo_args.extend(["-R", repo['uri']])
logger.debug(f"Including repository {repo.get('uri')} for architecture {target_architecture}")
else:
if 'uri' not in repo:
logger.warning(f"Repository entry missing 'uri' key: {repo}. Skipping.")
else:
logger.debug(f"Excluding repository {repo.get('uri')} for architecture {target_architecture}")
return filtered_repo_args
def construct_xbps_install_args(env_name, paths, target_architecture, repositories_data, all_bootstrap_packages):
"""
Constructs the xbps-install command arguments for a specific environment.
Args:
env_name (str): The name of the environment ('rootfs', 'pep-host', 'pep-target').
paths (dict): Dictionary of build paths.
target_architecture (str): The target architecture for the bootstrap.
repositories_data (list): List of repository dictionaries from YAML config.
Expected structure: [{'name': '...', 'uri': '...', 'architectures': [...]}, ...]
all_bootstrap_packages (dict): Dictionary containing package lists for
different environments and architectures.
Expected structure: {'env_name': {'arch': ['pkg1', ...]}}
Returns:
list: A list of strings representing the xbps-install command arguments.
Returns an empty list if no packages are defined or path is missing.
Raises:
ValueError: If no repositories found for the target architecture.
KeyError: If target directory path is not found in paths.
"""
logger.info(f"=> Constructing xbps-install arguments for {env_name.upper()} ({target_architecture})...")
target_directory_path = None
if env_name == "rootfs":
target_directory_path = paths.get("ROOTFS")
elif env_name == "pep-host":
target_directory_path = paths.get("PEPHOSTDIR")
elif env_name == "pep-target":
target_directory_path = paths.get("PEPTARGETDIR")
else:
logger.error(f"Unknown bootstrap environment: {env_name}")
raise ValueError(f"Unknown bootstrap environment: {env_name}")
if not target_directory_path:
logger.error(f"Path for environment '{env_name}' not found in paths dictionary.")
raise KeyError(f"Path for environment '{env_name}' not found.")
packages_to_install = all_bootstrap_packages.get(env_name, {}).get(target_architecture, [])
if not packages_to_install:
logger.warning(f"No packages defined for {env_name} on architecture {target_architecture}. Skipping command construction.")
return [] # Return empty list if no packages
filtered_repo_args = filter_repositories_by_architecture(repositories_data, target_architecture)
if not filtered_repo_args:
logger.error(f"No repositories found supporting target architecture: {target_architecture}. Cannot construct command for {env_name}.")
raise ValueError(f"No repositories found for architecture {target_architecture}")
# Get the XBPS cache directory for the target architecture (on the host)
host_cachedir = os.path.join(os.getcwd(), "xbps_package_cache", target_architecture)
os.makedirs(host_cachedir, exist_ok=True)
logger.debug(f"Using XBPS cache directory (on host): {host_cachedir}")
# Construct the xbps-install command arguments
# This command will be run directly on the host, targeting the specified directory (-r)
xbps_command_args = [
"-S", "-y",
] + filtered_repo_args + [
"-r", target_directory_path, # Install to the target directory (path on host)
"-c", host_cachedir, # XBPS cache directory (path on host)
] + packages_to_install
logger.info(f"Constructed arguments for {env_name}: {xbps_command_args}")
return xbps_command_args