127 lines
4.7 KiB
Rust
127 lines
4.7 KiB
Rust
//! Tauri-Befehle, die die Oberfläche aufruft.
|
|
|
|
use std::collections::HashMap;
|
|
use std::sync::Arc;
|
|
use std::time::Duration;
|
|
|
|
use tauri::State;
|
|
|
|
use crate::error::{AppError, AppResult};
|
|
use crate::managers::winget::WingetManager;
|
|
use crate::managers::PackageManager;
|
|
use crate::models::{ManagerId, ManagerInfo, Package, PackageDetails, Source};
|
|
use crate::process;
|
|
|
|
/// Registrierte Paketmanager.
|
|
pub struct Registry {
|
|
managers: HashMap<ManagerId, Arc<dyn PackageManager>>,
|
|
}
|
|
|
|
impl Registry {
|
|
/// Erstellt die Registry mit allen verfügbaren Implementierungen.
|
|
pub fn new() -> Self {
|
|
let mut managers: HashMap<ManagerId, Arc<dyn PackageManager>> = HashMap::new();
|
|
managers.insert(ManagerId::Winget, Arc::new(WingetManager::new()));
|
|
Self { managers }
|
|
}
|
|
|
|
fn get(&self, id: ManagerId) -> AppResult<Arc<dyn PackageManager>> {
|
|
self.managers
|
|
.get(&id)
|
|
.cloned()
|
|
.ok_or_else(|| AppError::Command("Dieser Paketmanager wird noch nicht unterstützt.".to_owned()))
|
|
}
|
|
|
|
async fn detect_all(&self) -> Vec<ManagerInfo> {
|
|
let mut infos = Vec::new();
|
|
for manager in self.managers.values() {
|
|
infos.push(manager.detect().await);
|
|
}
|
|
infos
|
|
}
|
|
}
|
|
|
|
impl Default for Registry {
|
|
fn default() -> Self {
|
|
Self::new()
|
|
}
|
|
}
|
|
|
|
fn logged<T>(what: &str, result: AppResult<T>) -> AppResult<T> {
|
|
if let Err(err) = &result {
|
|
tracing::error!(%err, "{what} fehlgeschlagen");
|
|
}
|
|
result
|
|
}
|
|
|
|
/// Erkennt alle Paketmanager (Pfad, Version, Zusatzkomponenten).
|
|
#[tauri::command]
|
|
pub async fn detect_managers(registry: State<'_, Registry>) -> AppResult<Vec<ManagerInfo>> {
|
|
Ok(registry.detect_all().await)
|
|
}
|
|
|
|
/// Sucht Pakete.
|
|
#[tauri::command]
|
|
pub async fn search_packages(registry: State<'_, Registry>, manager: ManagerId, query: String) -> AppResult<Vec<Package>> {
|
|
let query = query.trim().to_owned();
|
|
if query.is_empty() {
|
|
return Ok(Vec::new());
|
|
}
|
|
logged("Paketsuche", registry.get(manager)?.search(&query).await)
|
|
}
|
|
|
|
/// Listet installierte Pakete.
|
|
#[tauri::command]
|
|
pub async fn list_installed(registry: State<'_, Registry>, manager: ManagerId) -> AppResult<Vec<Package>> {
|
|
logged("Liste der installierten Pakete", registry.get(manager)?.list_installed().await)
|
|
}
|
|
|
|
/// Listet verfügbare Aktualisierungen.
|
|
#[tauri::command]
|
|
pub async fn list_updates(registry: State<'_, Registry>, manager: ManagerId) -> AppResult<Vec<Package>> {
|
|
logged("Suche nach Aktualisierungen", registry.get(manager)?.list_updates().await)
|
|
}
|
|
|
|
/// Lädt Paketdetails.
|
|
#[tauri::command]
|
|
pub async fn get_package_details(registry: State<'_, Registry>, package: Package) -> AppResult<PackageDetails> {
|
|
logged("Paketdetails", registry.get(package.manager)?.get_details(&package).await)
|
|
}
|
|
|
|
/// Listet die Quellen eines Managers.
|
|
#[tauri::command]
|
|
pub async fn list_sources(registry: State<'_, Registry>, manager: ManagerId) -> AppResult<Vec<Source>> {
|
|
logged("Quellenliste", registry.get(manager)?.list_sources().await)
|
|
}
|
|
|
|
async fn run_powershell(script: &str, timeout: Duration) -> AppResult<()> {
|
|
let shell = which::which("powershell")
|
|
.map_err(|_| AppError::ManagerMissing("Windows PowerShell".to_owned()))?;
|
|
let out = process::run(&shell, &["-NoLogo", "-NoProfile", "-NonInteractive", "-Command", script], timeout).await?;
|
|
if out.code == Some(0) {
|
|
Ok(())
|
|
} else {
|
|
let detail = out.stderr.lines().find(|l| !l.trim().is_empty()).unwrap_or("unbekannter Fehler");
|
|
Err(AppError::Command(format!("Die Installation ist fehlgeschlagen: {detail}")))
|
|
}
|
|
}
|
|
|
|
/// Installiert das PowerShell-Modul `Microsoft.WinGet.Client` für den aktuellen Benutzer.
|
|
#[tauri::command]
|
|
pub async fn install_winget_module(registry: State<'_, Registry>) -> AppResult<Vec<ManagerInfo>> {
|
|
let script = "$ProgressPreference='SilentlyContinue'; $ErrorActionPreference='Stop'; \
|
|
Install-PackageProvider -Name NuGet -MinimumVersion 2.8.5.201 -Scope CurrentUser -Force | Out-Null; \
|
|
Install-Module -Name Microsoft.WinGet.Client -Scope CurrentUser -Repository PSGallery -Force";
|
|
logged("Modulinstallation", run_powershell(script, Duration::from_secs(300)).await)?;
|
|
Ok(registry.detect_all().await)
|
|
}
|
|
|
|
/// Registriert bzw. installiert den „App-Installer“ (enthält WinGet).
|
|
#[tauri::command]
|
|
pub async fn install_app_installer(registry: State<'_, Registry>) -> AppResult<Vec<ManagerInfo>> {
|
|
let script = "$ProgressPreference='SilentlyContinue'; $ErrorActionPreference='Stop'; \
|
|
Add-AppxPackage -RegisterByFamilyName -MainPackage Microsoft.DesktopAppInstaller_8wekyb3d8bbwe";
|
|
logged("Installation des App-Installers", run_powershell(script, Duration::from_secs(300)).await)?;
|
|
Ok(registry.detect_all().await)
|
|
}
|