Files
CachyOS-updater/lib/package_manager.py

91 lines
2.4 KiB
Python

import subprocess
import logging
from dataclasses import dataclass, field
from pathlib import Path
from typing import Optional
logger = logging.getLogger(__name__)
PACMAN_LOCK = Path("/var/lib/pacman/db.lck")
@dataclass
class Package:
name: str
old_version: str
new_version: str
@dataclass
class InstallResult:
success: bool
installed: list = field(default_factory=list)
failed: list = field(default_factory=list)
error: Optional[str] = None
def is_pacman_locked() -> bool:
return PACMAN_LOCK.exists()
def check_updates() -> list[Package]:
"""Vérifie les mises à jour disponibles via checkupdates (sans droits root)."""
result = subprocess.run(
["checkupdates"],
capture_output=True, text=True, timeout=120
)
packages = []
for line in result.stdout.strip().splitlines():
parts = line.split()
# Format attendu : "nom ancienne_version -> nouvelle_version"
if len(parts) >= 4 and parts[2] == "->":
packages.append(Package(
name=parts[0],
old_version=parts[1],
new_version=parts[3],
))
return packages
def download_packages(names: list[str]) -> bool:
"""Télécharge les paquets dans le cache sans les installer."""
if not names:
return True
result = subprocess.run(
["pacman", "-Syw", "--noconfirm", "--noprogressbar"] + names,
capture_output=True, text=True, timeout=600
)
if result.returncode != 0:
logger.error(f"Téléchargement échoué : {result.stderr[-500:]}")
return False
return True
def sync_db() -> bool:
"""Synchronise la base de données des paquets."""
result = subprocess.run(
["pacman", "-Sy", "--noconfirm"],
capture_output=True, text=True, timeout=120
)
return result.returncode == 0
def install_packages(names: list[str]) -> InstallResult:
"""Installe des paquets spécifiques depuis le cache."""
if not names:
return InstallResult(success=True)
result = subprocess.run(
["pacman", "-S", "--noconfirm", "--needed", "--noprogressbar"] + names,
capture_output=True, text=True, timeout=600
)
if result.returncode == 0:
return InstallResult(success=True, installed=names)
else:
return InstallResult(
success=False,
failed=names,
error=result.stderr[-800:],
)