refactor menu and config to be more logical

This commit is contained in:
H4L0 2026-05-12 13:32:04 +02:00
parent 7fc33c2507
commit 6c9eab9a26
18 changed files with 187 additions and 286 deletions

View File

@ -21,11 +21,10 @@ from archinstall.lib.models.bootloader import Bootloader, BootloaderConfiguratio
from archinstall.lib.models.config import SubConfig
from archinstall.lib.models.device import DiskEncryption, DiskLayoutConfiguration
from archinstall.lib.models.locale import LocaleConfiguration
from archinstall.lib.models.mirrors import MirrorConfiguration
from archinstall.lib.models.mirrors import PacmanConfiguration
from archinstall.lib.models.network import NetworkConfiguration
from archinstall.lib.models.package_types import DEFAULT_KERNEL
from archinstall.lib.models.packages import Repository
from archinstall.lib.models.pacman import PacmanConfiguration
from archinstall.lib.models.profile import ProfileConfiguration
from archinstall.lib.models.users import Password, User, UserSerialization
from archinstall.lib.output import debug, error, logger, warn
@ -66,7 +65,6 @@ class ArchConfigType(StrEnum):
ARCHINSTALL_LANGUAGE = 'archinstall_language'
DISK_CONFIG = 'disk_config'
PROFILE_CONFIG = 'profile_config'
MIRROR_CONFIG = 'mirror_config'
NETWORK_CONFIG = 'network_config'
BOOTLOADER_CONFIG = 'bootloader_config'
APP_CONFIG = 'app_config'
@ -98,8 +96,6 @@ class ArchConfigType(StrEnum):
return tr('Disk configuration')
case ArchConfigType.PROFILE_CONFIG:
return tr('Profile')
case ArchConfigType.MIRROR_CONFIG:
return tr('Mirrors and repositories')
case ArchConfigType.NETWORK_CONFIG:
return tr('Network')
case ArchConfigType.BOOTLOADER_CONFIG:
@ -123,7 +119,7 @@ class ArchConfigType(StrEnum):
case ArchConfigType.PACKAGES:
return tr('Additional packages')
case ArchConfigType.PACMAN_CONFIG:
return tr('Pacman')
return tr('Pacman configuration')
case ArchConfigType.CUSTOM_COMMANDS:
return tr('Custom commands')
case ArchConfigType.USERS:
@ -142,7 +138,7 @@ class ArchConfig:
archinstall_language: Language = field(default_factory=lambda: translation_handler.get_language_by_abbr('en'))
disk_config: DiskLayoutConfiguration | None = None
profile_config: ProfileConfiguration | None = None
mirror_config: MirrorConfiguration | None = None
pacman_config: PacmanConfiguration | None = None
network_config: NetworkConfiguration | None = None
bootloader_config: BootloaderConfiguration | None = None
app_config: ApplicationConfiguration | None = None
@ -152,7 +148,6 @@ class ArchConfig:
kernels: list[str] = field(default_factory=lambda: [DEFAULT_KERNEL.value])
ntp: bool = True
packages: list[str] = field(default_factory=list)
pacman_config: PacmanConfiguration = field(default_factory=PacmanConfiguration.default)
timezone: str = 'UTC'
services: list[str] = field(default_factory=list)
custom_commands: list[str] = field(default_factory=list)
@ -203,12 +198,10 @@ class ArchConfig:
}
def sub_cfg(self) -> dict[ArchConfigType, SubConfig]:
cfg: dict[ArchConfigType, SubConfig] = {
ArchConfigType.PACMAN_CONFIG: self.pacman_config,
}
cfg: dict[ArchConfigType, SubConfig] = {}
if self.mirror_config:
cfg[ArchConfigType.MIRROR_CONFIG] = self.mirror_config
if self.pacman_config:
cfg[ArchConfigType.PACMAN_CONFIG] = self.pacman_config
if self.bootloader_config:
cfg[ArchConfigType.BOOTLOADER_CONFIG] = self.bootloader_config
@ -271,16 +264,21 @@ class ArchConfig:
if profile_config := args_config.get('profile_config', None):
arch_config.profile_config = ProfileConfiguration.parse_arg(profile_config)
if mirror_config := args_config.get('mirror_config', None):
if pacman_config := args_config.get('pacman_config', None):
backwards_compatible_repo = []
if additional_repositories := args_config.get('additional-repositories', []):
backwards_compatible_repo = [Repository(r) for r in additional_repositories]
arch_config.mirror_config = MirrorConfiguration.parse_args(
mirror_config,
arch_config.pacman_config = PacmanConfiguration.parse_args(
pacman_config,
backwards_compatible_repo,
)
if parallel_downloads := args_config.get('parallel_downloads', 0):
if arch_config.pacman_config is None:
arch_config.pacman_config = PacmanConfiguration()
arch_config.pacman_config.parallel_downloads = int(parallel_downloads)
if net_config := args_config.get('network_config', None):
arch_config.network_config = NetworkConfiguration.parse_arg(net_config)
@ -315,11 +313,6 @@ class ArchConfig:
if packages := args_config.get('packages', []):
arch_config.packages = packages
if pacman_config := args_config.get('pacman_config', None):
arch_config.pacman_config = PacmanConfiguration.parse_arg(pacman_config)
elif parallel_downloads := args_config.get('parallel_downloads', 0):
arch_config.pacman_config = PacmanConfiguration(parallel_downloads=int(parallel_downloads))
swap_arg = args_config.get('swap')
if swap_arg is not None:
arch_config.swap = ZramConfiguration.parse_arg(swap_arg)

View File

@ -14,23 +14,21 @@ from archinstall.lib.hardware import SysInfo
from archinstall.lib.locale.locale_menu import LocaleMenu
from archinstall.lib.menu.abstract_menu import AbstractMenu, SpecialMenuKey
from archinstall.lib.mirror.mirror_handler import MirrorListHandler
from archinstall.lib.mirror.mirror_menu import MirrorMenu
from archinstall.lib.mirror.mirror_menu import PacmanMenu
from archinstall.lib.models.application import ApplicationConfiguration, ZramConfiguration
from archinstall.lib.models.authentication import AuthenticationConfiguration
from archinstall.lib.models.bootloader import Bootloader, BootloaderConfiguration
from archinstall.lib.models.device import DiskLayoutConfiguration, DiskLayoutType, PartitionModification
from archinstall.lib.models.locale import LocaleConfiguration
from archinstall.lib.models.mirrors import MirrorConfiguration
from archinstall.lib.models.mirrors import PacmanConfiguration
from archinstall.lib.models.network import NetworkConfiguration, NicType
from archinstall.lib.models.package_types import DEFAULT_KERNEL
from archinstall.lib.models.packages import Repository
from archinstall.lib.models.pacman import PacmanConfiguration
from archinstall.lib.models.profile import ProfileConfiguration
from archinstall.lib.network.network_menu import select_network
from archinstall.lib.output import FormattedOutput
from archinstall.lib.packages.packages import list_available_packages, select_additional_packages
from archinstall.lib.pacman.config import PacmanConfig
from archinstall.lib.pacman.pacman_menu import PacmanMenu
from archinstall.lib.translationhandler import Language, tr, translation_handler
from archinstall.tui.components import tui
from archinstall.tui.menu_item import MenuItem, MenuItemGroup
@ -76,10 +74,10 @@ class GlobalMenu(AbstractMenu[None]):
key='locale_config',
),
MenuItem(
text=tr('Mirrors and repositories'),
action=self._mirror_configuration,
preview_action=self._prev_mirror_config,
key='mirror_config',
text=tr('Pacman configuration'),
action=self._pacman_configuration,
preview_action=self._prev_pacman_config,
key='pacman_config',
),
MenuItem(
text=tr('Disk configuration'),
@ -143,13 +141,6 @@ class GlobalMenu(AbstractMenu[None]):
preview_action=self._prev_network_config,
key='network_config',
),
MenuItem(
text=tr('Pacman'),
action=self._pacman_configuration,
value=PacmanConfiguration.default(),
preview_action=self._prev_pacman_config,
key='pacman_config',
),
MenuItem(
text=tr('Additional packages'),
action=self._select_additional_packages,
@ -419,19 +410,6 @@ class GlobalMenu(AbstractMenu[None]):
return f'{tr("Hostname")}: {item.value}'
return None
async def _pacman_configuration(self, preset: PacmanConfiguration) -> PacmanConfiguration | None:
return await PacmanMenu(preset, advanced=self._advanced).show()
def _prev_pacman_config(self, item: MenuItem) -> str | None:
if not item.value:
return None
config: PacmanConfiguration = item.value
output = ''
if self._advanced:
output += '{}: {}\n'.format(tr('Parallel Downloads'), config.parallel_downloads)
output += '{}: {}'.format(tr('Color'), config.color)
return output
def _prev_kernel(self, item: MenuItem) -> str | None:
if item.value:
kernel = ', '.join(item.value)
@ -555,7 +533,7 @@ class GlobalMenu(AbstractMenu[None]):
return profile_config
async def _select_additional_packages(self, preset: list[str]) -> list[str]:
config: MirrorConfiguration | None = self._item_group.find_by_key('mirror_config').value
config: PacmanConfiguration | None = self._item_group.find_by_key('pacman_config').value
repositories: set[Repository] = set()
if config:
@ -568,51 +546,54 @@ class GlobalMenu(AbstractMenu[None]):
return packages
async def _mirror_configuration(self, preset: MirrorConfiguration | None = None) -> MirrorConfiguration | None:
async def _pacman_configuration(self, preset: PacmanConfiguration | None = None) -> PacmanConfiguration | None:
if self._mirror_list_handler is None:
self._mirror_list_handler = MirrorListHandler()
mirror_configuration = await MirrorMenu(self._mirror_list_handler, preset=preset).run()
pacman_configuration = await PacmanMenu(self._mirror_list_handler, preset=preset).run()
if mirror_configuration and mirror_configuration.optional_repositories:
if pacman_configuration and pacman_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.enable(pacman_configuration.optional_repositories)
pacman_config.apply()
return mirror_configuration
return pacman_configuration
def _prev_mirror_config(self, item: MenuItem) -> str | None:
def _prev_pacman_config(self, item: MenuItem) -> str | None:
if not item.value:
return None
mirror_config: MirrorConfiguration = item.value
pacman_config: PacmanConfiguration = item.value
output = ''
if mirror_config.mirror_regions:
if pacman_config.mirror_regions:
title = tr('Selected mirror regions')
divider = '-' * len(title)
regions = mirror_config.region_names
regions = pacman_config.region_names
output += f'{title}\n{divider}\n{regions}\n\n'
if mirror_config.custom_servers:
if pacman_config.custom_servers:
title = tr('Custom servers')
divider = '-' * len(title)
servers = mirror_config.custom_server_urls
servers = pacman_config.custom_server_urls
output += f'{title}\n{divider}\n{servers}\n\n'
if mirror_config.optional_repositories:
if pacman_config.optional_repositories:
title = tr('Optional repositories')
divider = '-' * len(title)
repos = ', '.join(r.value for r in mirror_config.optional_repositories)
repos = ', '.join(r.value for r in pacman_config.optional_repositories)
output += f'{title}\n{divider}\n{repos}\n\n'
if mirror_config.custom_repositories:
if pacman_config.custom_repositories:
title = tr('Custom repositories')
table = FormattedOutput.as_table(mirror_config.custom_repositories)
output += f'{title}:\n\n{table}'
table = FormattedOutput.as_table(pacman_config.custom_repositories)
output += f'{title}:\n\n{table}\n\n'
output += '{}: {}\n'.format(tr('Parallel Downloads'), pacman_config.parallel_downloads)
output += '{}: {}'.format(tr('Color'), pacman_config.color)
return output.strip()

View File

@ -46,11 +46,10 @@ from archinstall.lib.models.device import (
Unit,
)
from archinstall.lib.models.locale import LocaleConfiguration
from archinstall.lib.models.mirrors import MirrorConfiguration
from archinstall.lib.models.mirrors import PacmanConfiguration
from archinstall.lib.models.network import Nic
from archinstall.lib.models.package_types import DEFAULT_KERNEL, Kernel
from archinstall.lib.models.packages import Repository
from archinstall.lib.models.pacman import PacmanConfiguration
from archinstall.lib.models.users import User
from archinstall.lib.output import debug, error, info, log, logger, warn
from archinstall.lib.packages.packages import installed_package
@ -553,14 +552,14 @@ class Installer:
def set_mirrors(
self,
mirror_list_handler: MirrorListHandler,
mirror_config: MirrorConfiguration,
pacman_config: PacmanConfiguration,
on_target: bool = False,
) -> None:
"""
Set the mirror configuration for the installation.
:param mirror_config: The mirror configuration to use.
:type mirror_config: MirrorConfiguration
:param pacman_config: The mirror configuration to use.
:type pacman_config: PacmanConfiguration
:on_target: Whether to set the mirrors on the target system or the live system.
:param on_target: bool
@ -569,29 +568,29 @@ class Installer:
for plugin in plugins.values():
if hasattr(plugin, 'on_mirrors'):
if result := plugin.on_mirrors(mirror_config):
mirror_config = result
if result := plugin.on_mirrors(pacman_config):
pacman_config = result
if on_target:
mirrorlist_config = self.target / MIRRORLIST.relative_to_root()
pacman_config = self.target / PACMAN_CONF.relative_to_root()
pacman_conf_path = self.target / PACMAN_CONF.relative_to_root()
else:
mirrorlist_config = MIRRORLIST
pacman_config = PACMAN_CONF
pacman_conf_path = PACMAN_CONF
repositories_config = mirror_config.repositories_config()
repositories_config = pacman_config.repositories_config()
if repositories_config:
debug(f'Pacman config: {repositories_config}')
with open(pacman_config, 'a') as fp:
with open(pacman_conf_path, 'a') as fp:
fp.write(repositories_config)
regions_config = mirror_config.regions_config(mirror_list_handler, speed_sort=True)
regions_config = pacman_config.regions_config(mirror_list_handler, speed_sort=True)
if regions_config:
debug(f'Mirrorlist:\n{regions_config}')
mirrorlist_config.write_text(regions_config)
custom_servers = mirror_config.custom_servers_config()
custom_servers = pacman_config.custom_servers_config()
if custom_servers:
debug(f'Custom servers:\n{custom_servers}')

View File

@ -1,19 +1,20 @@
from typing import override
from archinstall.lib.menu.abstract_menu import AbstractSubMenu
from archinstall.lib.menu.helpers import Input, Loading, Selection
from archinstall.lib.menu.helpers import Confirmation, Input, Loading, Selection
from archinstall.lib.menu.list_manager import ListManager
from archinstall.lib.mirror.mirror_handler import MirrorListHandler
from archinstall.lib.models.mirrors import (
CustomRepository,
CustomServer,
MirrorConfiguration,
MirrorRegion,
PacmanConfiguration,
SignCheck,
SignOption,
)
from archinstall.lib.models.packages import Repository
from archinstall.lib.output import FormattedOutput
from archinstall.lib.pathnames import PACMAN_CONF
from archinstall.lib.translationhandler import tr
from archinstall.tui.menu_item import MenuItem, MenuItemGroup
from archinstall.tui.result import ResultType
@ -201,16 +202,16 @@ class CustomMirrorServersList(ListManager[CustomServer]):
return None
class MirrorMenu(AbstractSubMenu[MirrorConfiguration]):
class PacmanMenu(AbstractSubMenu[PacmanConfiguration]):
def __init__(
self,
mirror_list_handler: MirrorListHandler,
preset: MirrorConfiguration | None = None,
preset: PacmanConfiguration | None = None,
):
if preset:
self._mirror_config = preset
self._pacman_config = preset
else:
self._mirror_config = MirrorConfiguration()
self._pacman_config = PacmanConfiguration()
self._mirror_list_handler = mirror_list_handler
@ -219,7 +220,7 @@ class MirrorMenu(AbstractSubMenu[MirrorConfiguration]):
super().__init__(
self._item_group,
config=self._mirror_config,
config=self._pacman_config,
allow_reset=True,
)
@ -228,14 +229,14 @@ class MirrorMenu(AbstractSubMenu[MirrorConfiguration]):
MenuItem(
text=tr('Select regions'),
action=lambda x: select_mirror_regions(self._mirror_list_handler, x),
value=self._mirror_config.mirror_regions,
value=self._pacman_config.mirror_regions,
preview_action=self._prev_regions,
key='mirror_regions',
),
MenuItem(
text=tr('Add custom servers'),
action=add_custom_mirror_servers,
value=self._mirror_config.custom_servers,
value=self._pacman_config.custom_servers,
preview_action=self._prev_custom_servers,
key='custom_servers',
),
@ -249,10 +250,24 @@ class MirrorMenu(AbstractSubMenu[MirrorConfiguration]):
MenuItem(
text=tr('Add custom repository'),
action=select_custom_mirror,
value=self._mirror_config.custom_repositories,
value=self._pacman_config.custom_repositories,
preview_action=self._prev_custom_mirror,
key='custom_repositories',
),
MenuItem(
text=tr('Parallel Downloads'),
action=select_parallel_downloads,
value=self._pacman_config.parallel_downloads,
preview_action=lambda item: str(item.get_value()),
key='parallel_downloads',
),
MenuItem(
text=tr('Color'),
action=select_color,
value=self._pacman_config.color,
preview_action=lambda item: str(item.get_value()),
key='color',
),
]
def _prev_regions(self, item: MenuItem) -> str:
@ -293,8 +308,73 @@ class MirrorMenu(AbstractSubMenu[MirrorConfiguration]):
return output.strip()
@override
async def show(self) -> MirrorConfiguration | None:
return await super().show()
async def show(self) -> PacmanConfiguration | None:
config = await super().show()
if config is not None:
_apply_to_live(config.parallel_downloads)
return config
def _apply_to_live(parallel_downloads: int) -> None:
"""Apply ParallelDownloads to live system pacman.conf for faster installation."""
with PACMAN_CONF.open() as f:
pacman_conf = f.read().split('\n')
with PACMAN_CONF.open('w') as fwrite:
for line in pacman_conf:
if 'ParallelDownloads' in line:
fwrite.write(f'ParallelDownloads = {parallel_downloads}\n')
else:
fwrite.write(f'{line}\n')
async def select_parallel_downloads(preset: int = 5) -> int | None:
max_recommended = 10
header = tr('Enter the number of parallel downloads (1-{})').format(max_recommended)
def validator(s: str) -> str | None:
try:
value = int(s)
if 1 <= value <= max_recommended:
return None
return tr('Value must be between 1 and {}').format(max_recommended)
except Exception:
return tr('Please enter a valid number')
result = await Input(
header=header,
allow_skip=True,
allow_reset=True,
validator_callback=validator,
default_value=str(preset),
).show()
match result.type_:
case ResultType.Skip:
return preset
case ResultType.Reset:
return 5
case ResultType.Selection:
return int(result.get_value())
async def select_color(preset: bool = True) -> bool | None:
result = await Confirmation(
header=tr('Enable colored output for pacman'),
preset=preset,
allow_skip=True,
).show()
match result.type_:
case ResultType.Skip:
return preset
case ResultType.Reset:
return True
case ResultType.Selection:
return result.get_value()
async def select_mirror_regions(

View File

@ -27,7 +27,7 @@ from archinstall.lib.models.device import (
_DeviceInfo,
)
from archinstall.lib.models.locale import LocaleConfiguration
from archinstall.lib.models.mirrors import CustomRepository, MirrorConfiguration, MirrorRegion
from archinstall.lib.models.mirrors import CustomRepository, MirrorRegion, PacmanConfiguration
from archinstall.lib.models.network import NetworkConfiguration, Nic, NicType
from archinstall.lib.models.packages import LocalPackage, PackageSearch, PackageSearchResult, Repository
from archinstall.lib.models.profile import ProfileConfiguration
@ -56,7 +56,6 @@ __all__ = [
'LvmLayoutType',
'LvmVolume',
'LvmVolumeGroup',
'MirrorConfiguration',
'MirrorRegion',
'ModificationStatus',
'NetworkConfiguration',
@ -64,6 +63,7 @@ __all__ = [
'NicType',
'PackageSearch',
'PackageSearchResult',
'PacmanConfiguration',
'PartitionFlag',
'PartitionModification',
'PartitionTable',

View File

@ -230,19 +230,23 @@ class CustomServer:
return configs
class _MirrorConfigurationSerialization(TypedDict):
class _PacmanConfigurationSerialization(TypedDict):
mirror_regions: dict[str, list[str]]
custom_servers: list[CustomServer]
optional_repositories: list[str]
custom_repositories: list[_CustomRepositorySerialization]
parallel_downloads: int
color: bool
@dataclass
class MirrorConfiguration(SubConfig):
class PacmanConfiguration(SubConfig):
mirror_regions: list[MirrorRegion] = field(default_factory=list)
custom_servers: list[CustomServer] = field(default_factory=list)
optional_repositories: list[Repository] = field(default_factory=list)
custom_repositories: list[CustomRepository] = field(default_factory=list)
parallel_downloads: int = 5
color: bool = True
@property
def region_names(self) -> str:
@ -253,7 +257,7 @@ class MirrorConfiguration(SubConfig):
return '\n'.join(s.url for s in self.custom_servers)
@override
def json(self) -> _MirrorConfigurationSerialization:
def json(self) -> _PacmanConfigurationSerialization:
regions = {}
for m in self.mirror_regions:
regions.update(m.json())
@ -263,6 +267,8 @@ class MirrorConfiguration(SubConfig):
'custom_servers': self.custom_servers,
'optional_repositories': [r.value for r in self.optional_repositories],
'custom_repositories': [c.json() for c in self.custom_repositories],
'parallel_downloads': self.parallel_downloads,
'color': self.color,
}
@override
@ -281,6 +287,11 @@ class MirrorConfiguration(SubConfig):
if self.custom_repositories:
out.append(tr('Custom repositories set up'))
out.append(tr('Parallel downloads: {}').format(self.parallel_downloads))
if self.color:
out.append(tr('Color enabled'))
return out
def custom_servers_config(self) -> str:
@ -353,4 +364,9 @@ class MirrorConfiguration(SubConfig):
if r not in config.optional_repositories:
config.optional_repositories.append(r)
if 'parallel_downloads' in args:
config.parallel_downloads = int(args['parallel_downloads'])
if 'color' in args:
config.color = bool(args['color'])
return config

View File

@ -1,50 +0,0 @@
from dataclasses import dataclass
from typing import Self, TypedDict, override
from archinstall.lib.models.config import SubConfig
from archinstall.lib.translationhandler import tr
class PacmanConfigSerialization(TypedDict):
parallel_downloads: int
color: bool
@dataclass
class PacmanConfiguration(SubConfig):
parallel_downloads: int = 5
color: bool = True
@classmethod
def default(cls) -> Self:
return cls()
@override
def json(self) -> PacmanConfigSerialization:
return {
'parallel_downloads': self.parallel_downloads,
'color': self.color,
}
@override
def summary(self) -> str | None:
if self.color:
return tr('Color enabled')
return None
def preview(self) -> str:
color_str = str(self.color)
output = '{}: {}\n'.format(tr('Parallel Downloads'), self.parallel_downloads)
output += '{}: {}'.format(tr('Color'), color_str)
return output
@classmethod
def parse_arg(cls, args: PacmanConfigSerialization) -> Self:
config = cls.default()
if 'parallel_downloads' in args:
config.parallel_downloads = int(args['parallel_downloads'])
if 'color' in args:
config.color = bool(args['color'])
return config

View File

@ -1,8 +1,8 @@
import re
from pathlib import Path
from archinstall.lib.models.mirrors import PacmanConfiguration
from archinstall.lib.models.packages import Repository
from archinstall.lib.models.pacman import PacmanConfiguration
from archinstall.lib.pathnames import PACMAN_CONF

View File

@ -1,117 +0,0 @@
from typing import override
from archinstall.lib.menu.abstract_menu import AbstractSubMenu
from archinstall.lib.menu.helpers import Confirmation, Input
from archinstall.lib.models.pacman import PacmanConfiguration
from archinstall.lib.pathnames import PACMAN_CONF
from archinstall.lib.translationhandler import tr
from archinstall.tui.menu_item import MenuItem, MenuItemGroup
from archinstall.tui.result import ResultType
class PacmanMenu(AbstractSubMenu[PacmanConfiguration]):
def __init__(
self,
pacman_conf: PacmanConfiguration,
advanced: bool = False,
):
self._pacman_conf = pacman_conf
self._advanced = advanced
menu_options = self._define_menu_options()
self._item_group = MenuItemGroup(menu_options, sort_items=False, checkmarks=True)
super().__init__(
self._item_group,
config=self._pacman_conf,
allow_reset=True,
)
def _define_menu_options(self) -> list[MenuItem]:
return [
MenuItem(
text=tr('Parallel Downloads'),
action=select_parallel_downloads,
value=self._pacman_conf.parallel_downloads,
preview_action=lambda item: str(item.get_value()),
key='parallel_downloads',
enabled=self._advanced,
),
MenuItem(
text=tr('Color'),
action=select_color,
value=self._pacman_conf.color,
preview_action=lambda item: str(item.get_value()),
key='color',
),
]
@override
async def show(self) -> PacmanConfiguration | None:
config = await super().show()
if config is None:
return PacmanConfiguration.default()
_apply_to_live(config.parallel_downloads)
return config
def _apply_to_live(parallel_downloads: int) -> None:
"""Apply ParallelDownloads to live system pacman.conf for faster installation."""
with PACMAN_CONF.open() as f:
pacman_conf = f.read().split('\n')
with PACMAN_CONF.open('w') as fwrite:
for line in pacman_conf:
if 'ParallelDownloads' in line:
fwrite.write(f'ParallelDownloads = {parallel_downloads}\n')
else:
fwrite.write(f'{line}\n')
async def select_parallel_downloads(preset: int = 5) -> int | None:
max_recommended = 10
header = tr('Enter the number of parallel downloads (1-{})').format(max_recommended)
def validator(s: str) -> str | None:
try:
value = int(s)
if 1 <= value <= max_recommended:
return None
return tr('Value must be between 1 and {}').format(max_recommended)
except Exception:
return tr('Please enter a valid number')
result = await Input(
header=header,
allow_skip=True,
allow_reset=True,
validator_callback=validator,
default_value=str(preset),
).show()
match result.type_:
case ResultType.Skip:
return preset
case ResultType.Reset:
return 5
case ResultType.Selection:
return int(result.get_value())
async def select_color(preset: bool = True) -> bool | None:
result = await Confirmation(
header=tr('Enable colored output for pacman'),
preset=preset,
allow_skip=True,
).show()
match result.type_:
case ResultType.Skip:
return preset
case ResultType.Reset:
return True
case ResultType.Selection:
return result.get_value()

View File

@ -73,7 +73,7 @@ def perform_installation(
disk_config = config.disk_config
run_mkinitcpio = not config.bootloader_config or not config.bootloader_config.uki
locale_config = config.locale_config
optional_repositories = config.mirror_config.optional_repositories if config.mirror_config else []
optional_repositories = config.pacman_config.optional_repositories if config.pacman_config else []
mountpoint = disk_config.mountpoint if disk_config.mountpoint else mountpoint
with Installer(
@ -97,8 +97,8 @@ def perform_installation(
# generate encryption key files for the mounted luks devices
installation.generate_key_files()
if mirror_config := config.mirror_config:
installation.set_mirrors(mirror_list_handler, mirror_config, on_target=False)
if pacman_config := config.pacman_config:
installation.set_mirrors(mirror_list_handler, pacman_config, on_target=False)
installation.minimal_installation(
optional_repositories=optional_repositories,
@ -108,8 +108,8 @@ def perform_installation(
pacman_config=config.pacman_config,
)
if mirror_config := config.mirror_config:
installation.set_mirrors(mirror_list_handler, mirror_config, on_target=True)
if pacman_config := config.pacman_config:
installation.set_mirrors(mirror_list_handler, pacman_config, on_target=True)
if config.swap and config.swap.enabled:
installation.setup_swap(algo=config.swap.algorithm)

View File

@ -10,7 +10,7 @@ hostname,``str``,A string defining your machines hostname on the network *(defau
kernels,[ `linux <https://wiki.archlinux.org/title/Kernel#Officially_supported_kernels>`_!, `linux-hardened <https://wiki.archlinux.org/title/Kernel#Officially_supported_kernels>`_!, `linux-lts <https://wiki.archlinux.org/title/Kernel#Officially_supported_kernels>`_!, `linux-rt <https://wiki.archlinux.org/title/Kernel#Officially_supported_kernels>`_!, `linux-rt-lts <https://wiki.archlinux.org/title/Kernel#Officially_supported_kernels>`_!, `linux-zen <https://wiki.archlinux.org/title/Kernel#Officially_supported_kernels>`_ ],Defines which kernels should be installed and setup in the boot loader options,Yes
custom_commands,*Read more under* :ref:`custom commands`,Custom commands that will be run post-install chrooted inside the installed system,No
locale_config,{kb_layout: `lang <https://wiki.archlinux.org/title/Linux_console/Keyboard_configuration>`__!, sys_enc: `Character encoding <https://wiki.archlinux.org/title/Locale>`_!, sys_lang: `locale <https://wiki.archlinux.org/title/Locale>`_},Defines the keyboard key map!, system encoding and system locale,No
mirror_config,{custom_mirrors: [ https://... ]!, mirror_regions: { "Worldwide": [ "https://geo.mirror.pkgbuild.com/$repo/os/$arch" ] } },Sets various mirrors *(defaults to ISO's ``/etc/pacman.d/mirrors`` if not defined)*,No
pacman_config,{custom_mirrors: [ https://... ]!, mirror_regions: { "Worldwide": [ "https://geo.mirror.pkgbuild.com/$repo/os/$arch" ] } },Sets various mirrors *(defaults to ISO's ``/etc/pacman.d/mirrors`` if not defined)*,No
network_config,*`see options under Network Configuration`*,Sets which type of *(if any)* network configuration should be used,No
no_pkg_lookups,``true``!, ``false``,Disabled package checking against https://archlinux.org/packages/,No
ntp,``true``!, ``false``,enables or disables `NTP <https://wiki.archlinux.org/title/Network_Time_Protocol_daemon>`_ during installation,No

Can't render this file because it has a wrong number of fields in line 2.

View File

@ -192,7 +192,7 @@ The contents of :code:`https://domain.lan/config.json`:
"sys_enc": "UTF-8",
"sys_lang": "en_US"
},
"mirror_config": {
"pacman_config": {
"custom_servers": [
{
"url": "https://mymirror.com/$repo/os/$arch"

View File

@ -91,7 +91,7 @@
"sys_enc": "UTF-8",
"sys_lang": "en_US"
},
"mirror_config": {
"pacman_config": {
"custom_servers": [
{
"url": "https://mymirror.com/$repo/os/$arch"

View File

@ -29,8 +29,8 @@ def deprecated_creds_config() -> Path:
@pytest.fixture(scope='session')
def deprecated_mirror_config() -> Path:
return Path(__file__).parent / 'data' / 'test_deprecated_mirror_config.json'
def deprecated_pacman_config() -> Path:
return Path(__file__).parent / 'data' / 'test_deprecated_pacman_config.json'
@pytest.fixture(scope='session')

View File

@ -138,7 +138,7 @@
"sys_enc": "UTF-8",
"sys_lang": "en_US"
},
"mirror_config": {
"pacman_config": {
"custom_servers": [
{
"url": "https://mymirror.com/$repo/os/$arch"

View File

@ -1,6 +1,6 @@
{
"additional-repositories": ["testing"],
"mirror_config": {
"pacman_config": {
"custom_mirrors": [
{
"name": "my_mirror",

View File

@ -19,10 +19,9 @@ from archinstall.lib.models.authentication import AuthenticationConfiguration, U
from archinstall.lib.models.bootloader import Bootloader, BootloaderConfiguration
from archinstall.lib.models.device import DiskLayoutConfiguration, DiskLayoutType
from archinstall.lib.models.locale import LocaleConfiguration
from archinstall.lib.models.mirrors import CustomRepository, CustomServer, MirrorConfiguration, MirrorRegion, SignCheck, SignOption
from archinstall.lib.models.mirrors import CustomRepository, CustomServer, MirrorRegion, PacmanConfiguration, SignCheck, SignOption
from archinstall.lib.models.network import NetworkConfiguration, Nic, NicType
from archinstall.lib.models.packages import Repository
from archinstall.lib.models.pacman import PacmanConfiguration
from archinstall.lib.models.profile import ProfileConfiguration
from archinstall.lib.models.users import Password, User
from archinstall.lib.profile.profiles_handler import profile_handler
@ -193,7 +192,7 @@ def test_config_file_parsing(
gfx_driver=GfxDriver.AllOpenSource,
greeter=GreeterType.Lightdm,
),
mirror_config=MirrorConfiguration(
pacman_config=PacmanConfiguration(
mirror_regions=[
MirrorRegion(
name='Australia',
@ -210,6 +209,7 @@ def test_config_file_parsing(
sign_option=SignOption.TrustAll,
),
],
parallel_downloads=66,
),
network_config=NetworkConfiguration(
type=NicType.MANUAL,
@ -235,7 +235,6 @@ def test_config_file_parsing(
kernels=['linux-zen'],
ntp=True,
packages=['firefox'],
pacman_config=PacmanConfiguration(parallel_downloads=66),
swap=ZramConfiguration(enabled=False),
timezone='UTC',
services=['service_1', 'service_2'],
@ -243,23 +242,23 @@ def test_config_file_parsing(
)
def test_deprecated_mirror_config_parsing(
def test_deprecated_pacman_config_parsing(
monkeypatch: MonkeyPatch,
deprecated_mirror_config: Path,
deprecated_pacman_config: Path,
) -> None:
monkeypatch.setattr(
'sys.argv',
[
'archinstall',
'--config',
str(deprecated_mirror_config),
str(deprecated_pacman_config),
],
)
handler = ArchConfigHandler()
arch_config = handler.config
assert arch_config.mirror_config == MirrorConfiguration(
assert arch_config.pacman_config == PacmanConfiguration(
mirror_regions=[
MirrorRegion(
name='Australia',

View File

@ -38,10 +38,10 @@ def test_user_config_roundtrip(
result['disk_config']['device_modifications'] = expected['disk_config']['device_modifications']
assert json.dumps(
result['mirror_config'],
result['pacman_config'],
sort_keys=True,
) == json.dumps(
expected['mirror_config'],
expected['pacman_config'],
sort_keys=True,
)