feat: support user preview configuration and document UI

This commit is contained in:
2026-10-05 19:17:27 +05:30
parent ee6186ed0b
commit de8843471b
10 changed files with 210 additions and 80 deletions

View File

@@ -7,7 +7,7 @@ use std::{
fs::{self, OpenOptions},
io,
os::unix::fs::{MetadataExt, OpenOptionsExt},
path::PathBuf,
path::{Path, PathBuf},
};
use clap::Parser;
@@ -34,8 +34,8 @@ const BUILD_TIME: &str = env!("LATCHD_BUILD_TIME");
)]
struct Cli {
/// Configuration TOML path.
#[arg(short, long, default_value = "/etc/latchd/config.toml")]
config: PathBuf,
#[arg(short, long)]
config: Option<PathBuf>,
/// Optional variable TOML path.
#[arg(short = 'v', long)]
variables: Option<PathBuf>,
@@ -79,17 +79,7 @@ fn run() -> Result<(), Error> {
println!("version={BUILD_VERSION}\ncommit={BUILD_COMMIT}\nepoch={BUILD_TIME}");
return Ok(());
}
let config_path = if cli.config.exists() {
Some(cli.config.as_path())
} else {
if cli.config.as_os_str() != "/etc/latchd/config.toml" {
return Err(Error::Config(format!(
"configuration does not exist: {}",
cli.config.display()
)));
}
None
};
let config_path = resolve_config_path(cli.config.as_deref(), cli.preview)?;
if let Some(path) = cli.variables.as_deref() {
if !path.exists() {
return Err(Error::Config(format!(
@@ -100,7 +90,7 @@ fn run() -> Result<(), Error> {
}
let variables_path = cli.variables.as_deref();
if !cli.preview {
if let Some(path) = config_path {
if let Some(path) = config_path.as_deref() {
config::validate_source(path, "configuration")?;
}
if let Some(path) = variables_path {
@@ -109,7 +99,7 @@ fn run() -> Result<(), Error> {
}
let mut config = Config::default();
if config_path.is_some() || variables_path.is_some() {
config = config::load(config_path, variables_path)?;
config = config::load(config_path.as_deref(), variables_path)?;
}
if let Some(tty) = cli.tty {
if tty == 0 {
@@ -148,7 +138,7 @@ fn run() -> Result<(), Error> {
"already inside a session; use --preview".into(),
));
}
if unsafe { libc::geteuid() } != 0 {
if !running_as_root() {
return Err(Error::Config("latchd must run as root".into()));
}
validate_terminal()?;
@@ -212,6 +202,33 @@ fn run() -> Result<(), Error> {
Ok(())
}
fn resolve_config_path(explicit: Option<&Path>, preview: bool) -> Result<Option<PathBuf>, Error> {
if let Some(path) = explicit {
if path.exists() {
return Ok(Some(path.to_owned()));
}
return Err(Error::Config(format!(
"configuration does not exist: {}",
path.display()
)));
}
let system_path = Path::new(config::SYSTEM_CONFIG_PATH);
if !preview {
return Ok(system_path.exists().then(|| system_path.to_owned()));
}
if let Some(path) = config::user_config_path().filter(|path| path.exists()) {
return Ok(Some(path));
}
Ok(system_path.exists().then(|| system_path.to_owned()))
}
fn running_as_root() -> bool {
// SAFETY: `geteuid` has no pointer arguments or memory preconditions.
unsafe { libc::geteuid() == 0 }
}
fn setup_logging(path: &std::path::Path) -> Result<(), Error> {
const MAX_LOG_BYTES: u64 = 64 * 1024 * 1024;
let parent = path