use std::env;
use std::ffi::OsString;
use std::process::Command;
const MARKER: &str = "CARGO_GAMMA_SCOPE";
const SYSTEMD_RUN: &str = "systemd-run";
#[derive(Debug, PartialEq, Eq)]
pub(crate) enum Refusal {
AlreadyInScope,
Unavailable,
}
pub(crate) fn relaunched() -> bool {
env::var_os(MARKER).is_some()
}
fn scope_command(exe: OsString, args: Vec<OsString>) -> Command {
let mut command = Command::new(SYSTEMD_RUN);
let _built = command
.arg("--user")
.arg("--scope")
.arg("--property=Delegate=yes")
.arg("--property=MemoryAccounting=yes")
.arg("--quiet")
.arg("--collect")
.arg("--same-dir")
.arg("--")
.arg(exe)
.args(args)
.env(MARKER, "1");
command
}
pub(crate) fn relaunch() -> Result<Option<i32>, Refusal> {
relaunch_unless(relaunched())
}
fn relaunch_unless(marked: bool) -> Result<Option<i32>, Refusal> {
if marked {
return Err(Refusal::AlreadyInScope);
}
let Ok(exe) = env::current_exe() else {
return Err(Refusal::Unavailable);
};
if which(SYSTEMD_RUN).is_none() {
return Err(Refusal::Unavailable);
}
let args: Vec<OsString> = env::args_os().skip(1).collect();
match scope_command(exe.into_os_string(), args).status() {
Err(_cause) => Err(Refusal::Unavailable),
Ok(status) => Ok(Some(status.code().unwrap_or(crate::commands::EXIT_CANNOT_PROCEED))),
}
}
fn which(program: &str) -> Option<std::path::PathBuf> {
let paths = env::var_os("PATH")?;
env::split_paths(&paths)
.map(|directory| directory.join(program))
.find(|candidate| candidate.is_file())
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn the_scope_command_asks_for_a_delegated_cgroup_and_forwards_the_invocation() {
let command = scope_command(
OsString::from("/opt/cargo-gamma"),
vec![OsString::from("gamma"), OsString::from("run")],
);
let args: Vec<_> = command.get_args().map(|arg| arg.to_string_lossy().into_owned()).collect();
assert_eq!(command.get_program(), "systemd-run");
assert!(args.contains(&"--user".to_owned()), "{args:?}");
assert!(args.contains(&"--scope".to_owned()), "{args:?}");
assert!(args.contains(&"--property=Delegate=yes".to_owned()), "{args:?}");
let separator = args.iter().position(|arg| arg == "--").expect("a separator");
assert_eq!(args[separator + 1], "/opt/cargo-gamma");
assert_eq!(args[separator + 2..], ["gamma", "run"]);
}
#[test]
fn the_relaunched_process_is_marked_as_one() {
let command = scope_command(OsString::from("/opt/cargo-gamma"), Vec::new());
let marked = command
.get_envs()
.any(|(name, value)| name == MARKER && value.is_some_and(|value| !value.is_empty()));
assert!(marked, "the marker must be set in the child's environment");
}
#[test]
fn a_process_already_inside_a_scope_refuses_to_relaunch_again() {
assert_eq!(relaunch_unless(true), Err(Refusal::AlreadyInScope));
}
#[test]
#[cfg(not(miri))]
fn an_absent_program_is_not_found_on_the_path() {
assert!(which("cargo-gamma-nonexistent-probe").is_none());
}
}