Resolve helper programs and session dirs without FHS paths
systemctl was invoked as /usr/bin/systemctl, and session directories were fixed to /usr/share. Both assume an FHS layout and fail on NixOS. Programs now resolve via PATH; session directories walk XDG_DATA_DIRS with /usr/share as fallback. Behaviour on Arch is unchanged.
This commit is contained in:
+2
-2
@@ -105,7 +105,7 @@ fn run_command(action: &'static str, program: &str, args: &[&str]) -> Result<(),
|
||||
/// agent — the greeter session has none, so without it a denied authorization
|
||||
/// would hang instead of failing fast.
|
||||
pub fn reboot() -> Result<(), PowerError> {
|
||||
run_command("reboot", "/usr/bin/systemctl", &["--no-ask-password", "reboot"])
|
||||
run_command("reboot", "systemctl", &["--no-ask-password", "reboot"])
|
||||
}
|
||||
|
||||
/// Shut down the system via systemctl.
|
||||
@@ -113,7 +113,7 @@ pub fn reboot() -> Result<(), PowerError> {
|
||||
/// `--no-ask-password` for the same reason as [`reboot`] — the agent-less
|
||||
/// greeter session has nothing to answer an authorization challenge.
|
||||
pub fn shutdown() -> Result<(), PowerError> {
|
||||
run_command("shutdown", "/usr/bin/systemctl", &["--no-ask-password", "poweroff"])
|
||||
run_command("shutdown", "systemctl", &["--no-ask-password", "poweroff"])
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
||||
+76
-6
@@ -4,8 +4,34 @@
|
||||
use std::fs;
|
||||
use std::path::{Path, PathBuf};
|
||||
|
||||
const DEFAULT_WAYLAND_DIRS: &[&str] = &["/usr/share/wayland-sessions"];
|
||||
const DEFAULT_XSESSION_DIRS: &[&str] = &["/usr/share/xsessions"];
|
||||
/// Fallback data directory used when XDG_DATA_DIRS is unset or does not
|
||||
/// contain the session directory.
|
||||
const FALLBACK_DATA_DIR: &str = "/usr/share";
|
||||
|
||||
/// Build the search path for a session directory.
|
||||
///
|
||||
/// Walks XDG_DATA_DIRS as specified by the XDG Base Directory spec and
|
||||
/// appends `/usr/share` as a fallback, so setups that place session files
|
||||
/// outside the FHS layout are found as well.
|
||||
fn session_search_dirs(subdir: &str) -> Vec<PathBuf> {
|
||||
session_search_dirs_from(&std::env::var("XDG_DATA_DIRS").unwrap_or_default(), subdir)
|
||||
}
|
||||
|
||||
/// Build the search path from an explicit XDG_DATA_DIRS value.
|
||||
fn session_search_dirs_from(data_dirs: &str, subdir: &str) -> Vec<PathBuf> {
|
||||
let mut dirs: Vec<PathBuf> = data_dirs
|
||||
.split(':')
|
||||
.filter(|s| !s.is_empty())
|
||||
.map(|d| PathBuf::from(d).join(subdir))
|
||||
.collect();
|
||||
|
||||
let fallback = PathBuf::from(FALLBACK_DATA_DIR).join(subdir);
|
||||
if !dirs.contains(&fallback) {
|
||||
dirs.push(fallback);
|
||||
}
|
||||
|
||||
dirs
|
||||
}
|
||||
|
||||
/// Represents an available login session.
|
||||
#[derive(Debug, Clone)]
|
||||
@@ -82,10 +108,8 @@ pub fn get_sessions(
|
||||
wayland_dirs: Option<&[PathBuf]>,
|
||||
xsession_dirs: Option<&[PathBuf]>,
|
||||
) -> Vec<Session> {
|
||||
let default_wayland: Vec<PathBuf> =
|
||||
DEFAULT_WAYLAND_DIRS.iter().map(PathBuf::from).collect();
|
||||
let default_xsession: Vec<PathBuf> =
|
||||
DEFAULT_XSESSION_DIRS.iter().map(PathBuf::from).collect();
|
||||
let default_wayland = session_search_dirs("wayland-sessions");
|
||||
let default_xsession = session_search_dirs("xsessions");
|
||||
|
||||
let wayland = wayland_dirs.unwrap_or(&default_wayland);
|
||||
let xsession = xsession_dirs.unwrap_or(&default_xsession);
|
||||
@@ -129,6 +153,52 @@ mod tests {
|
||||
fs::write(dir.join(name), content).unwrap();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn search_dirs_walk_xdg_data_dirs() {
|
||||
let dirs = session_search_dirs_from(
|
||||
"/run/current-system/sw/share:/usr/local/share",
|
||||
"wayland-sessions",
|
||||
);
|
||||
assert_eq!(
|
||||
dirs,
|
||||
vec![
|
||||
PathBuf::from("/run/current-system/sw/share/wayland-sessions"),
|
||||
PathBuf::from("/usr/local/share/wayland-sessions"),
|
||||
PathBuf::from("/usr/share/wayland-sessions"),
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn search_dirs_fall_back_when_unset() {
|
||||
let dirs = session_search_dirs_from("", "xsessions");
|
||||
assert_eq!(dirs, vec![PathBuf::from("/usr/share/xsessions")]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn search_dirs_do_not_duplicate_fallback() {
|
||||
let dirs = session_search_dirs_from("/usr/share:/opt/share", "wayland-sessions");
|
||||
assert_eq!(
|
||||
dirs,
|
||||
vec![
|
||||
PathBuf::from("/usr/share/wayland-sessions"),
|
||||
PathBuf::from("/opt/share/wayland-sessions"),
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn search_dirs_skip_empty_segments() {
|
||||
let dirs = session_search_dirs_from("::/opt/share:", "wayland-sessions");
|
||||
assert_eq!(
|
||||
dirs,
|
||||
vec![
|
||||
PathBuf::from("/opt/share/wayland-sessions"),
|
||||
PathBuf::from("/usr/share/wayland-sessions"),
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parse_valid_desktop_file() {
|
||||
let dir = tempfile::tempdir().unwrap();
|
||||
|
||||
Reference in New Issue
Block a user