rho-coding-agent 0.28.1

A lightweight agent harness inspired by Pi
Documentation
use std::{fs, io::Write, path::PathBuf};

pub(super) fn write_atomically(path: &PathBuf, contents: &str) -> anyhow::Result<()> {
    let temp_path = path.with_extension(format!("toml.{}.tmp", uuid::Uuid::new_v4()));
    let mut temp_file = fs::File::create(&temp_path)?;
    set_private_file_permissions(&temp_file)?;
    temp_file.write_all(contents.as_bytes())?;
    temp_file.sync_all()?;
    drop(temp_file);
    replace_file(&temp_path, path)?;
    Ok(())
}

#[cfg(not(windows))]
fn replace_file(temp_path: &PathBuf, path: &PathBuf) -> anyhow::Result<()> {
    fs::rename(temp_path, path)?;
    Ok(())
}

#[cfg(windows)]
fn replace_file(temp_path: &PathBuf, path: &PathBuf) -> anyhow::Result<()> {
    use std::os::windows::ffi::OsStrExt;
    use windows_sys::Win32::Storage::FileSystem::{ReplaceFileW, REPLACEFILE_WRITE_THROUGH};

    if !path.exists() {
        fs::rename(temp_path, path)?;
        return Ok(());
    }
    let replaced = path
        .as_os_str()
        .encode_wide()
        .chain(Some(0))
        .collect::<Vec<_>>();
    let replacement = temp_path
        .as_os_str()
        .encode_wide()
        .chain(Some(0))
        .collect::<Vec<_>>();
    let result = unsafe {
        ReplaceFileW(
            replaced.as_ptr(),
            replacement.as_ptr(),
            std::ptr::null(),
            REPLACEFILE_WRITE_THROUGH,
            std::ptr::null_mut(),
            std::ptr::null_mut(),
        )
    };
    if result == 0 {
        return Err(std::io::Error::last_os_error().into());
    }
    Ok(())
}

#[cfg(unix)]
fn set_private_file_permissions(file: &fs::File) -> anyhow::Result<()> {
    use std::os::unix::fs::PermissionsExt;
    file.set_permissions(fs::Permissions::from_mode(0o600))?;
    Ok(())
}

#[cfg(not(unix))]
fn set_private_file_permissions(_file: &fs::File) -> anyhow::Result<()> {
    Ok(())
}