use std::path::Path;
use anyhow::Result;
use crate::systemd;
use super::paths::quadlet_dir;
fn write_custom_units(
name: &str,
sdir: &Path,
socket_content: &str,
host_service_content: &str,
dbus_proxy_content: Option<&str>,
compositor_service_content: Option<&str>,
) -> Result<()> {
std::fs::create_dir_all(sdir)?;
std::fs::write(sdir.join(format!("{name}.socket")), socket_content)?;
std::fs::write(
sdir.join(format!("{name}-host.service")),
host_service_content,
)?;
if let Some(proxy) = dbus_proxy_content {
std::fs::write(sdir.join(format!("{name}-proxy.service")), proxy)?;
}
if let Some(comp) = compositor_service_content {
std::fs::write(sdir.join(format!("{name}-compositor.service")), comp)?;
}
write_clean_stop_dropin(name, sdir)?;
Ok(())
}
fn write_clean_stop_dropin(name: &str, sdir: &Path) -> Result<()> {
let dir = sdir.join(format!("{name}.service.d"));
std::fs::create_dir_all(&dir)?;
std::fs::write(
dir.join("99-podbox-clean-stop.conf"),
"[Service]\nSuccessExitStatus=0 143 SIGTERM SIGINT\n",
)?;
Ok(())
}
pub(crate) fn finalize_units(
name: &str,
sdir: &Path,
socket_content: &str,
host_service_content: &str,
dbus_proxy_content: Option<&str>,
compositor_service_content: Option<&str>,
use_wayland_proxy: bool,
) -> Result<()> {
write_custom_units(
name,
sdir,
socket_content,
host_service_content,
dbus_proxy_content,
compositor_service_content,
)?;
println!("Systemd units installed to {}", sdir.display());
systemd::daemon_reload()?;
systemd::reset_failed(name)?;
systemd::stop_socket_and_host(name)?;
if use_wayland_proxy {
systemd::stop_compositor(name)?;
}
systemd::enable_now_socket(name)?;
Ok(())
}
pub(crate) fn podman_quadlet_install_files(
name: &str,
container_content: &str,
build_content: Option<&str>,
) -> Result<()> {
let tmp = std::env::temp_dir().join(format!("podbox-install-{name}"));
let _ = std::fs::remove_dir_all(&tmp);
std::fs::create_dir_all(&tmp)?;
let container_path = tmp.join(format!("{name}.container"));
std::fs::write(&container_path, container_content)?;
let mut args: Vec<std::ffi::OsString> = vec![
"quadlet".into(),
"install".into(),
"--replace".into(),
container_path.into(),
];
if let Some(bc) = build_content {
let build_path = tmp.join(format!("{name}.build"));
std::fs::write(&build_path, bc)?;
args.push(build_path.into());
}
let output = crate::process::run_piped("podman", &args)?;
let _ = std::fs::remove_dir_all(&tmp);
if !output.status.success() {
let stderr = String::from_utf8_lossy(&output.stderr);
anyhow::bail!("podman quadlet install failed: {stderr}");
}
println!("Quadlet files installed via podman quadlet install.");
Ok(())
}
pub(crate) fn podman_quadlet_install_application(
name: &str,
container_content: &str,
build_content: Option<&str>,
) -> Result<()> {
let tmp = std::env::temp_dir().join(format!("podbox-install-{name}"));
let _ = std::fs::remove_dir_all(&tmp);
std::fs::create_dir_all(&tmp)?;
std::fs::write(tmp.join(format!("{name}.container")), container_content)?;
if let Some(bc) = build_content {
std::fs::write(tmp.join(format!("{name}.build")), bc)?;
}
let args: Vec<std::ffi::OsString> = vec![
"quadlet".into(),
"install".into(),
"--replace".into(),
"--application".into(),
name.into(),
tmp.clone().into(),
];
let output = crate::process::run_piped("podman", &args)?;
let _ = std::fs::remove_dir_all(&tmp);
if !output.status.success() {
let stderr = String::from_utf8_lossy(&output.stderr);
anyhow::bail!("podman quadlet install --application failed: {stderr}");
}
println!("Quadlet files installed via podman quadlet install --application {name}.");
Ok(())
}
pub(crate) fn remove_flat_units(name: &str) {
let qdir = quadlet_dir();
for ext in ["container", "build"] {
let path = qdir.join(format!("{name}.{ext}"));
if !path.exists() {
continue;
}
let args: Vec<std::ffi::OsString> = vec![
"quadlet".into(),
"rm".into(),
format!("{name}.{ext}").into(),
];
let _ = crate::process::run_piped("podman", &args);
let _ = std::fs::remove_file(&path);
}
}
pub(crate) fn remove_application_dir(name: &str) {
let app_dir = quadlet_dir().join(name);
if app_dir.is_dir() {
let _ = std::fs::remove_dir_all(&app_dir);
}
}