Files
CachyOS-updater/lib/aur_manager.py

111 lines
3.5 KiB
Python

"""Gestion des mises à jour AUR.
Les paquets AUR sont toujours installés immédiatement (jamais reportés à
l'extinction) car le build requiert un utilisateur actif et un accès réseau.
"""
import logging
import os
import pwd
import shutil
import subprocess
from pathlib import Path
from package_manager import Package, InstallResult
logger = logging.getLogger(__name__)
_AUR_HELPERS = ["paru", "yay"]
def detect_aur_helper() -> str | None:
for helper in _AUR_HELPERS:
if shutil.which(helper):
return helper
return None
def detect_active_user() -> str | None:
"""Retourne le nom de l'utilisateur avec une session graphique active."""
try:
result = subprocess.run(
["loginctl", "list-sessions", "--no-legend"],
capture_output=True, text=True, timeout=5,
)
for line in result.stdout.strip().splitlines():
parts = line.split()
if len(parts) < 3:
continue
session_id, _, user = parts[0], parts[1], parts[2]
if user == "root":
continue
session_type = subprocess.run(
["loginctl", "show-session", session_id, "-p", "Type", "--value"],
capture_output=True, text=True, timeout=3,
).stdout.strip()
if session_type in ("x11", "wayland", "mir"):
return user
except Exception as e:
logger.debug(f"Impossible de détecter l'utilisateur actif : {e}")
return None
def _user_env(user: str) -> dict:
pw = pwd.getpwnam(user)
return {
"HOME": pw.pw_dir,
"USER": user,
"LOGNAME": user,
"XDG_RUNTIME_DIR": f"/run/user/{pw.pw_uid}",
"PATH": "/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
}
def check_aur_updates(user: str, helper: str) -> list[Package]:
"""Liste les mises à jour AUR disponibles sans rien installer."""
try:
result = subprocess.run(
["sudo", "-u", user, "-H", helper, "-Qua", "--color", "never"],
capture_output=True, text=True, timeout=120,
env=_user_env(user),
)
packages = []
for line in result.stdout.strip().splitlines():
parts = line.split()
if len(parts) >= 4 and parts[2] == "->":
packages.append(Package(
name=parts[0],
old_version=parts[1],
new_version=parts[3],
))
return packages
except Exception as e:
logger.error(f"Échec de la vérification AUR : {e}")
return []
def install_aur_packages(user: str, helper: str, names: list[str]) -> InstallResult:
"""Installe des paquets AUR spécifiques en tant qu'utilisateur actif."""
if not names:
return InstallResult(success=True)
try:
result = subprocess.run(
[
"sudo", "-u", user, "-H",
helper, "-S", "--noconfirm", "--noprogressbar",
"--color", "never",
] + names,
capture_output=True, text=True, timeout=900,
env=_user_env(user),
)
if result.returncode == 0:
return InstallResult(success=True, installed=names)
return InstallResult(
success=False,
failed=names,
error=result.stderr[-800:],
)
except Exception as e:
logger.exception(f"Erreur lors de l'installation AUR : {e}")
return InstallResult(success=False, failed=names, error=str(e))