Move Pacman out of init (#4150)

* Move pacman out of init

* Update archinstall/lib/pacman/pacman.py

Co-authored-by: codefiles <11915375+codefiles@users.noreply.github.com>

* Update archinstall/lib/pacman/pacman.py

Co-authored-by: codefiles <11915375+codefiles@users.noreply.github.com>

---------

Co-authored-by: codefiles <11915375+codefiles@users.noreply.github.com>
This commit is contained in:
Daniel Girtler 2026-01-27 12:34:48 +11:00 committed by GitHub
parent 28f7aec2af
commit 2421e538a8
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 87 additions and 94 deletions

View File

@ -49,8 +49,8 @@ from .models.mirrors import MirrorConfiguration
from .models.network import Nic
from .models.users import User
from .output import debug, error, info, log, logger, warn
from .pacman import Pacman
from .pacman.config import PacmanConfig
from .pacman.pacman import Pacman
from .plugins import plugins
# Any package that the Installer() is responsible for (optional and the default ones)

View File

@ -14,7 +14,7 @@ from urllib.request import urlopen
from .exceptions import DownloadTimeout, SysCallError
from .output import debug, error, info
from .pacman import Pacman
from .pacman.pacman import Pacman
class DownloadTimer:

View File

@ -3,7 +3,7 @@ from functools import lru_cache
from ..exceptions import SysCallError
from ..models.packages import AvailablePackage, LocalPackage, Repository
from ..output import debug
from ..pacman import Pacman
from ..pacman.pacman import Pacman
# TODO: This shouldn't be living in here but there are too many

View File

@ -1,90 +0,0 @@
import sys
import time
from collections.abc import Callable
from pathlib import Path
from archinstall.lib.translationhandler import tr
from ..exceptions import RequirementError
from ..general import SysCommand
from ..output import error, info, warn
from ..plugins import plugins
from .config import PacmanConfig
class Pacman:
def __init__(self, target: Path, silent: bool = False):
self.synced = False
self.silent = silent
self.target = target
@staticmethod
def run(args: str, default_cmd: str = 'pacman') -> SysCommand:
"""
A centralized function to call `pacman` from.
It also protects us from colliding with other running pacman sessions (if used locally).
The grace period is set to 10 minutes before exiting hard if another pacman instance is running.
"""
pacman_db_lock = Path('/var/lib/pacman/db.lck')
if pacman_db_lock.exists():
warn(tr('Pacman is already running, waiting maximum 10 minutes for it to terminate.'))
started = time.time()
while pacman_db_lock.exists():
time.sleep(0.25)
if time.time() - started > (60 * 10):
error(tr('Pre-existing pacman lock never exited. Please clean up any existing pacman sessions before using archinstall.'))
sys.exit(1)
return SysCommand(f'{default_cmd} {args}')
def ask(self, error_message: str, bail_message: str, func: Callable, *args, **kwargs) -> None: # type: ignore[no-untyped-def, type-arg]
while True:
try:
func(*args, **kwargs)
break
except Exception as err:
error(f'{error_message}: {err}')
if not self.silent and input('Would you like to re-try this download? (Y/n): ').lower().strip() in 'y':
continue
raise RequirementError(f'{bail_message}: {err}')
def sync(self) -> None:
if self.synced:
return
self.ask(
'Could not sync a new package database',
'Could not sync mirrors',
self.run,
'-Syy',
default_cmd='pacman',
)
self.synced = True
def strap(self, packages: str | list[str]) -> None:
self.sync()
if isinstance(packages, str):
packages = [packages]
for plugin in plugins.values():
if hasattr(plugin, 'on_pacstrap'):
if result := plugin.on_pacstrap(packages):
packages = result
info(f'Installing packages: {packages}')
self.ask(
'Could not strap in packages',
'Pacstrap failed. See /var/log/archinstall/install.log or above message for error details',
SysCommand,
f'pacstrap -C /etc/pacman.conf -K {self.target} {" ".join(packages)} --noconfirm --needed',
peek_output=True,
)
__all__ = [
'Pacman',
'PacmanConfig',
]

View File

@ -0,0 +1,83 @@
import sys
import time
from collections.abc import Callable
from pathlib import Path
from archinstall.lib.translationhandler import tr
from ..exceptions import RequirementError
from ..general import SysCommand
from ..output import error, info, warn
from ..plugins import plugins
class Pacman:
def __init__(self, target: Path, silent: bool = False):
self.synced = False
self.silent = silent
self.target = target
@staticmethod
def run(args: str, default_cmd: str = 'pacman') -> SysCommand:
"""
A centralized function to call `pacman` from.
It also protects us from colliding with other running pacman sessions (if used locally).
The grace period is set to 10 minutes before exiting hard if another pacman instance is running.
"""
pacman_db_lock = Path('/var/lib/pacman/db.lck')
if pacman_db_lock.exists():
warn(tr('Pacman is already running, waiting maximum 10 minutes for it to terminate.'))
started = time.time()
while pacman_db_lock.exists():
time.sleep(0.25)
if time.time() - started > (60 * 10):
error(tr('Pre-existing pacman lock never exited. Please clean up any existing pacman sessions before using archinstall.'))
sys.exit(1)
return SysCommand(f'{default_cmd} {args}')
def ask(self, error_message: str, bail_message: str, func: Callable, *args, **kwargs) -> None: # type: ignore[no-untyped-def, type-arg]
while True:
try:
func(*args, **kwargs)
break
except Exception as err:
error(f'{error_message}: {err}')
if not self.silent and input('Would you like to re-try this download? (Y/n): ').lower().strip() in 'y':
continue
raise RequirementError(f'{bail_message}: {err}')
def sync(self) -> None:
if self.synced:
return
self.ask(
'Could not sync a new package database',
'Could not sync mirrors',
self.run,
'-Syy',
default_cmd='pacman',
)
self.synced = True
def strap(self, packages: str | list[str]) -> None:
self.sync()
if isinstance(packages, str):
packages = [packages]
for plugin in plugins.values():
if hasattr(plugin, 'on_pacstrap'):
if result := plugin.on_pacstrap(packages):
packages = result
info(f'Installing packages: {packages}')
self.ask(
'Could not strap in packages',
'Pacstrap failed. See /var/log/archinstall/install.log or above message for error details',
SysCommand,
f'pacstrap -C /etc/pacman.conf -K {self.target} {" ".join(packages)} --noconfirm --needed',
peek_output=True,
)

View File

@ -16,7 +16,7 @@ from archinstall.lib.packages.packages import check_version_upgrade
from .lib.hardware import SysInfo
from .lib.output import debug, error, info, warn
from .lib.pacman import Pacman
from .lib.pacman.pacman import Pacman
from .lib.translationhandler import tr