From 6ef35766a139caf51b905e9a2ff65137c34bee08 Mon Sep 17 00:00:00 2001 From: Daniel Girtler Date: Sat, 3 May 2025 20:15:55 +1000 Subject: [PATCH] Fix 3412 - Take optional repositories into account --- archinstall/lib/global_menu.py | 30 ++++++++++- archinstall/lib/installer.py | 4 +- archinstall/lib/interactions/general_conf.py | 9 +++- archinstall/lib/pacman/__init__.py | 4 +- archinstall/lib/pacman/config.py | 56 +++++++++++--------- 5 files changed, 72 insertions(+), 31 deletions(-) diff --git a/archinstall/lib/global_menu.py b/archinstall/lib/global_menu.py index 612ff1dc79..9daae3fcec 100644 --- a/archinstall/lib/global_menu.py +++ b/archinstall/lib/global_menu.py @@ -5,6 +5,7 @@ from archinstall.lib.disk.disk_menu import DiskLayoutConfigurationMenu from archinstall.lib.disk.encryption_menu import DiskEncryptionMenu from archinstall.lib.models.device_model import DiskEncryption, DiskLayoutConfiguration, DiskLayoutType, EncryptionType, FilesystemType, PartitionModification +from archinstall.lib.packages import list_available_packages from archinstall.tui.menu_item import MenuItem, MenuItemGroup from .args import ArchConfig @@ -29,9 +30,11 @@ from .models.locale import LocaleConfiguration from .models.mirrors import MirrorConfiguration from .models.network_configuration import NetworkConfiguration, NicType +from .models.packages import Repository from .models.profile_model import ProfileConfiguration from .models.users import Password, User from .output import FormattedOutput +from .pacman.config import PacmanConfig from .translationhandler import Language, translation_handler from .utils.util import get_password @@ -168,7 +171,7 @@ def _get_menu_options(self) -> list[MenuItem]: ), MenuItem( text=str(_('Additional packages')), - action=ask_additional_packages_to_install, + action=self._select_additional_packages, value=[], preview_action=self._prev_additional_pkgs, key='packages' @@ -536,6 +539,20 @@ def _select_profile(self, current_profile: ProfileConfiguration | None): profile_config = ProfileMenu(preset=current_profile).run() return profile_config + def _select_additional_packages(self, preset: list[str]) -> list[str]: + config: MirrorConfiguration | None = self._item_group.find_by_key('mirror_config').value + + repositories: set[Repository] = set() + if config: + repositories = set(config.optional_repositories) + + packages = ask_additional_packages_to_install( + preset, + repositories=repositories + ) + + return packages + def _create_user_account(self, preset: list[User] | None = None) -> list[User]: preset = [] if preset is None else preset users = ask_for_additional_users(defined_users=preset) @@ -543,6 +560,17 @@ def _create_user_account(self, preset: list[User] | None = None) -> list[User]: def _mirror_configuration(self, preset: MirrorConfiguration | None = None) -> MirrorConfiguration | None: mirror_configuration = MirrorMenu(preset=preset).run() + + if mirror_configuration: + if mirror_configuration.optional_repositories: + # reset the package list cache in case the repository selection has changed + list_available_packages.cache_clear() + + # enable the repositories in the config + pacman_config = PacmanConfig(None) + pacman_config.enable(mirror_configuration.optional_repositories) + pacman_config.apply() + return mirror_configuration def _prev_mirror_config(self, item: MenuItem) -> str | None: diff --git a/archinstall/lib/installer.py b/archinstall/lib/installer.py index 2a0da7284e..6d82b6d8c8 100644 --- a/archinstall/lib/installer.py +++ b/archinstall/lib/installer.py @@ -44,7 +44,7 @@ from .models.users import User from .output import debug, error, info, log, warn from .pacman import Pacman -from .pacman.config import Config +from .pacman.config import PacmanConfig from .plugins import plugins from .storage import storage @@ -847,7 +847,7 @@ def minimal_installation( debug(f'Optional repositories: {optional_repositories}') # This action takes place on the host system as pacstrap copies over package repository lists. - pacman_conf = Config(self.target) + pacman_conf = PacmanConfig(self.target) pacman_conf.enable(optional_repositories) pacman_conf.apply() diff --git a/archinstall/lib/interactions/general_conf.py b/archinstall/lib/interactions/general_conf.py index 6a5d470a88..2dcbad6656 100644 --- a/archinstall/lib/interactions/general_conf.py +++ b/archinstall/lib/interactions/general_conf.py @@ -178,9 +178,14 @@ def ask_additional_packages_to_install( preset: list[str] = [], repositories: set[Repository] = set() ) -> list[str]: - Tui.print(str(_('Loading packages...')), clear_screen=True) - repositories |= {Repository.Core, Repository.Extra} + + respos_text = ', '.join([r.value for r in repositories]) + output = str(_('Repositories: {}')).format(respos_text) + '\n' + + output += str(_('Loading packages...')) + Tui.print(output, clear_screen=True) + packages = list_available_packages(tuple(repositories)) package_groups = PackageGroup.from_available_packages(packages) diff --git a/archinstall/lib/pacman/__init__.py b/archinstall/lib/pacman/__init__.py index 7729cd0697..45eb8284c4 100644 --- a/archinstall/lib/pacman/__init__.py +++ b/archinstall/lib/pacman/__init__.py @@ -7,7 +7,7 @@ from ..general import SysCommand from ..output import error, info, warn from ..plugins import plugins -from .config import Config +from .config import PacmanConfig if TYPE_CHECKING: from archinstall.lib.translationhandler import DeferredTranslation @@ -89,6 +89,6 @@ def strap(self, packages: str | list[str]) -> None: __all__ = [ - 'Config', 'Pacman', + 'PacmanConfig', ] diff --git a/archinstall/lib/pacman/config.py b/archinstall/lib/pacman/config.py index 1f3e6d88d1..6ea75d4e31 100644 --- a/archinstall/lib/pacman/config.py +++ b/archinstall/lib/pacman/config.py @@ -5,10 +5,13 @@ from ..models.packages import Repository -class Config: - def __init__(self, target: Path): - self.path = Path("/etc") / "pacman.conf" - self.chroot_path = target / "etc" / "pacman.conf" +class PacmanConfig: + def __init__(self, target: Path | None): + self._config_path = Path("/etc") / "pacman.conf" + + if target: + self._config_remote_path = target / "etc" / "pacman.conf" + self._repositories: list[Repository] = [] def enable(self, repo: Repository | list[Repository]) -> None: @@ -21,26 +24,31 @@ def apply(self) -> None: if not self._repositories: return - if Repository.Testing in self._repositories: - if Repository.Multilib in self._repositories: - repos_pattern = f'({Repository.Multilib.value}|.+-{Repository.Testing.value})' + repos_to_enable = [] + for repo in self._repositories: + if repo == Repository.Testing: + repos_to_enable.extend(['core-testing', 'extra-testing', 'multilib-testing']) else: - repos_pattern = f'(?!{Repository.Multilib.value}).+-{Repository.Testing.value}' - else: - repos_pattern = Repository.Multilib.value - - pattern = re.compile(rf"^#\s*\[{repos_pattern}\]$") - lines = iter(self.path.read_text().splitlines(keepends=True)) - - with open(self.path, 'w') as f: - for line in lines: - if pattern.match(line): - # Uncomment this line and the next. - f.write(line.lstrip('#')) - f.write(next(lines).lstrip('#')) - else: - f.write(line) + repos_to_enable.append(repo.value) + + content = self._config_path.read_text().splitlines(keepends=True) + + for row, line in enumerate(content): + # Check if this is a commented repository section that needs to be enabled + match = re.match(r'^#\s*\[(.*)\]', line) + + if match and match.group(1) in repos_to_enable: + # uncomment the repository section line, properly removing # and any spaces + content[row] = re.sub(r'^#\s*', '', line) + + # also uncomment the next line (Include statement) if it exists and is commented + if row + 1 < len(content) and content[row + 1].lstrip().startswith('#'): + content[row + 1] = re.sub(r'^#\s*', '', content[row + 1]) + + # Write the modified content back to the file + with open(self._config_path, 'w') as f: + f.writelines(content) def persist(self) -> None: - if self._repositories: - copy2(self.path, self.chroot_path) + if self._repositories and self._config_remote_path: + copy2(self._config_path, self._config_remote_path)