Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 7 additions & 4 deletions archinstall/lib/args.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
from archinstall.lib.models.mirrors import MirrorConfiguration
from archinstall.lib.models.network import NetworkConfiguration
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
Expand Down Expand Up @@ -73,7 +74,7 @@ class ArchConfig:
kernels: list[str] = field(default_factory=lambda: ['linux'])
ntp: bool = True
packages: list[str] = field(default_factory=list)
parallel_downloads: int = 0
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)
Expand Down Expand Up @@ -104,7 +105,7 @@ def safe_config(self) -> dict[str, Any]:
'kernels': self.kernels,
'ntp': self.ntp,
'packages': self.packages,
'parallel_downloads': self.parallel_downloads,
'pacman_config': self.pacman_config.json(),
'swap': self.swap,
'timezone': self.timezone,
'services': self.services,
Expand Down Expand Up @@ -209,8 +210,10 @@ def from_config(cls, args_config: dict[str, Any], args: Arguments) -> Self:
if packages := args_config.get('packages', []):
arch_config.packages = packages

if parallel_downloads := args_config.get('parallel_downloads', 0):
arch_config.parallel_downloads = parallel_downloads
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:
Expand Down
2 changes: 0 additions & 2 deletions archinstall/lib/general/__init__.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
from archinstall.lib.general.general_menu import (
add_number_of_parallel_downloads,
select_archinstall_language,
select_hostname,
select_ntp,
Expand All @@ -8,7 +7,6 @@
from archinstall.lib.general.system_menu import select_driver, select_kernel, select_swap

__all__ = [
'add_number_of_parallel_downloads',
'select_archinstall_language',
'select_driver',
'select_hostname',
Expand Down
50 changes: 0 additions & 50 deletions archinstall/lib/general/general_menu.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
from archinstall.lib.locale.utils import list_timezones
from archinstall.lib.menu.helpers import Confirmation, Input, Selection
from archinstall.lib.output import warn
from archinstall.lib.pathnames import PACMAN_CONF
from archinstall.lib.translationhandler import Language, tr
from archinstall.tui.ui.menu_item import MenuItem, MenuItemGroup
from archinstall.tui.ui.result import ResultType
Expand Down Expand Up @@ -126,55 +125,6 @@ async def select_archinstall_language(languages: list[Language], preset: Languag
raise ValueError('Language selection not handled')


async def add_number_of_parallel_downloads(preset: int = 1) -> int | None:
max_recommended = 5

header = tr('This option enables the number of parallel downloads that can occur during package downloads') + '\n'
header += tr(' - Maximum recommended value : {} ( Allows {} parallel downloads at a time )').format(max_recommended, max_recommended) + '\n\n'
header += tr('Enter the number of parallel downloads to be enabled')

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()

downloads = 1

match result.type_:
case ResultType.Skip:
return preset
case ResultType.Reset:
return downloads
case ResultType.Selection:
downloads = int(result.get_value())

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 = {downloads}\n')
else:
fwrite.write(f'{line}\n')

return downloads


async def select_post_installation(elapsed_time: float | None = None) -> PostInstallationAction:
header = 'Installation completed'
if elapsed_time is not None:
Expand Down
32 changes: 22 additions & 10 deletions archinstall/lib/global_menu.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
from archinstall.lib.bootloader.bootloader_menu import BootloaderMenu
from archinstall.lib.configuration import save_config
from archinstall.lib.disk.disk_menu import DiskLayoutConfigurationMenu
from archinstall.lib.general.general_menu import add_number_of_parallel_downloads, select_hostname, select_ntp, select_timezone
from archinstall.lib.general.general_menu import select_hostname, select_ntp, select_timezone
from archinstall.lib.general.system_menu import select_kernel, select_swap
from archinstall.lib.hardware import SysInfo
from archinstall.lib.locale.locale_menu import LocaleMenu
Expand All @@ -22,11 +22,13 @@
from archinstall.lib.models.mirrors import MirrorConfiguration
from archinstall.lib.models.network import NetworkConfiguration, 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.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.ui.components import tui
from archinstall.tui.ui.menu_item import MenuItem, MenuItemGroup
Expand All @@ -38,11 +40,13 @@ def __init__(
arch_config: ArchConfig,
mirror_list_handler: MirrorListHandler | None = None,
skip_boot: bool = False,
advanced: bool = False,
title: str | None = None,
) -> None:
self._arch_config = arch_config
self._mirror_list_handler = mirror_list_handler
self._skip_boot = skip_boot
self._advanced = advanced
self._uefi = SysInfo.has_uefi()
menu_options = self._get_menu_options()

Expand Down Expand Up @@ -138,11 +142,11 @@ def _get_menu_options(self) -> list[MenuItem]:
key='network_config',
),
MenuItem(
text=tr('Parallel Downloads'),
action=add_number_of_parallel_downloads,
value=1,
preview_action=self._prev_parallel_dw,
key='parallel_downloads',
text=tr('Pacman'),
action=self._pacman_configuration,
value=PacmanConfiguration.default(),
preview_action=self._prev_pacman_config,
key='pacman_config',
),
MenuItem(
text=tr('Additional packages'),
Expand Down Expand Up @@ -413,10 +417,18 @@ def _prev_hostname(self, item: MenuItem) -> str | None:
return f'{tr("Hostname")}: {item.value}'
return None

def _prev_parallel_dw(self, item: MenuItem) -> str | None:
if item.value is not None:
return f'{tr("Parallel Downloads")}: {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:
Expand Down
5 changes: 5 additions & 0 deletions archinstall/lib/installer.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@
from archinstall.lib.models.mirrors import MirrorConfiguration
from archinstall.lib.models.network import Nic
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
Expand Down Expand Up @@ -886,6 +887,7 @@ def minimal_installation(
mkinitcpio: bool = True,
hostname: str | None = None,
locale_config: LocaleConfiguration | None = LocaleConfiguration.default(),
pacman_config: PacmanConfiguration | None = None,
) -> None:
if self._disk_config.lvm_config:
lvm = 'lvm2'
Expand Down Expand Up @@ -932,6 +934,9 @@ def minimal_installation(

pacman_conf.persist()

if pacman_config:
pacman_conf.configure(pacman_config)

# Periodic TRIM may improve the performance and longevity of SSDs whilst
# having no adverse effect on other devices. Most distributions enable
# periodic TRIM by default.
Expand Down
42 changes: 42 additions & 0 deletions archinstall/lib/models/pacman.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
from dataclasses import dataclass
from typing import Self, TypedDict

from archinstall.lib.translationhandler import tr


class PacmanConfigSerialization(TypedDict):
parallel_downloads: int
color: bool


@dataclass
class PacmanConfiguration:
parallel_downloads: int = 5
color: bool = True

@classmethod
def default(cls) -> Self:
return cls()

def json(self) -> PacmanConfigSerialization:
return {
'parallel_downloads': self.parallel_downloads,
'color': self.color,
}

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
21 changes: 20 additions & 1 deletion archinstall/lib/pacman/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
from pathlib import Path

from archinstall.lib.models.packages import Repository
from archinstall.lib.models.pacman import PacmanConfiguration
from archinstall.lib.pathnames import PACMAN_CONF


Expand Down Expand Up @@ -50,5 +51,23 @@ def apply(self) -> None:
f.writelines(content)

def persist(self) -> None:
if self._repositories and self._config_remote_path:
if self._config_remote_path:
PACMAN_CONF.copy(self._config_remote_path, preserve_metadata=True)

def configure(self, pacman_config: PacmanConfiguration) -> None:
"""Apply PacmanConfiguration (Color, ParallelDownloads) to the target system's pacman.conf."""
if not self._config_remote_path or not self._config_remote_path.exists():
return

content = self._config_remote_path.read_text().splitlines()
result = []

for line in content:
if re.match(r'^#?\s*ParallelDownloads', line):
result.append(f'ParallelDownloads = {pacman_config.parallel_downloads}')
elif re.match(r'^#?\s*Color\s*$', line):
result.append('Color' if pacman_config.color else '#Color')
else:
result.append(line)

self._config_remote_path.write_text('\n'.join(result) + '\n')
Loading
Loading