libplasmoid-updater 0.2.0

Library for updating KDE Plasma 6 components from the KDE Store. Meant for use in topgrade.
Documentation
// SPDX-License-Identifier: GPL-3.0-or-later

use std::process::Command;

use crate::{
    types::{AvailableUpdate, ComponentType, InstalledComponent},
    {Error, Result},
};

fn get_user_id() -> String {
    std::env::var("UID").unwrap_or_else(|_| nix::unistd::Uid::current().as_raw().to_string())
}

/// Restarts the plasmashell service via systemd.
pub(crate) fn restart_plasmashell() -> Result<()> {
    let mut cmd = Command::new("systemctl");
    cmd.args(["--user", "restart", "plasma-plasmashell.service"]);

    let uid = get_user_id();

    if std::env::var("DBUS_SESSION_BUS_ADDRESS").is_err() {
        cmd.env(
            "DBUS_SESSION_BUS_ADDRESS",
            format!("unix:path=/run/user/{uid}/bus"),
        );
    }

    if std::env::var("XDG_RUNTIME_DIR").is_err() {
        cmd.env("XDG_RUNTIME_DIR", format!("/run/user/{uid}"));
    }

    let status = cmd
        .status()
        .map_err(|e| Error::restart(format!("failed to run systemctl: {e}")))?;

    if !status.success() {
        return Err(Error::restart(format!(
            "systemctl exited with status {status}"
        )));
    }

    Ok(())
}

/// Returns `true` if the component type requires a plasmashell restart after updating.
fn requires_plasmashell_restart(component: &InstalledComponent) -> bool {
    matches!(
        component.component_type,
        ComponentType::PlasmaWidget
            | ComponentType::PlasmaStyle
            | ComponentType::GlobalTheme
            | ComponentType::SplashScreen
            | ComponentType::KWinSwitcher
    )
}

/// Returns `true` if any of the updates require a plasmashell restart.
pub(crate) fn any_requires_restart(updates: &[&AvailableUpdate]) -> bool {
    updates
        .iter()
        .any(|u| requires_plasmashell_restart(&u.installed))
}