codex-wrangler 1.3.0

Linux/X11/i3 tray switcher for live coding-agent TUI sessions
use std::{
    env, fs,
    io::Write as _,
    os::unix::fs::{DirBuilderExt as _, OpenOptionsExt as _},
    path::{Path, PathBuf},
};

use anyhow::{Context as _, Result};

const APPLICATION: &str = "codex-wrangler";

pub fn path(file: &str) -> Result<PathBuf> {
    path_from(
        file,
        env::var_os("XDG_STATE_HOME").as_deref(),
        env::var_os("HOME").as_deref(),
    )
    .context("neither absolute XDG_STATE_HOME nor HOME is available")
}

pub fn seal(path: &Path, bytes: &[u8]) -> Result<()> {
    let parent = path.parent().context("XDG state path has no parent")?;
    fs::DirBuilder::new()
        .recursive(true)
        .mode(0o700)
        .create(parent)
        .with_context(|| format!("create `{}`", parent.display()))?;
    let name = path
        .file_name()
        .and_then(|name| name.to_str())
        .context("XDG state path has no UTF-8 filename")?;
    let temporary = path.with_file_name(format!(".{name}.tmp"));
    let mut file = fs::OpenOptions::new()
        .create(true)
        .truncate(true)
        .write(true)
        .mode(0o600)
        .open(&temporary)
        .with_context(|| format!("stage `{}`", path.display()))?;
    file.write_all(bytes)
        .with_context(|| format!("write `{}`", path.display()))?;
    file.sync_all()
        .with_context(|| format!("seal `{}`", path.display()))?;
    drop(file);
    fs::rename(&temporary, path).with_context(|| format!("publish `{}`", path.display()))?;
    fs::File::open(parent)
        .and_then(|directory| directory.sync_all())
        .with_context(|| format!("seal `{}`", parent.display()))
}

pub(crate) fn path_from(
    file: &str,
    xdg: Option<&std::ffi::OsStr>,
    home: Option<&std::ffi::OsStr>,
) -> Option<PathBuf> {
    xdg.map(Path::new)
        .filter(|path| path.is_absolute())
        .map(Path::to_path_buf)
        .or_else(|| {
            home.map(Path::new)
                .filter(|path| path.is_absolute())
                .map(|home| home.join(".local/state"))
        })
        .map(|root| root.join(APPLICATION).join(file))
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn relative_xdg_state_is_banished_to_the_absolute_home_default() {
        assert_eq!(
            path_from(
                "window-mode",
                Some("relative".as_ref()),
                Some("/home/keeper".as_ref())
            ),
            Some(PathBuf::from(
                "/home/keeper/.local/state/codex-wrangler/window-mode"
            ))
        );
        assert_eq!(
            path_from(
                "window-mode",
                Some("/vault/state".as_ref()),
                Some("/home/keeper".as_ref())
            ),
            Some(PathBuf::from("/vault/state/codex-wrangler/window-mode"))
        );
    }
}