unified-agent-api 0.3.5

Agent-agnostic facade and registry for wrapper backends
Documentation
use std::{
    env,
    fs::{self, File, OpenOptions},
    io::ErrorKind,
    path::{Path, PathBuf},
    thread,
    time::Duration,
};

pub(crate) struct TestEnvLockGuard {
    path: PathBuf,
    _file: File,
}

pub(crate) fn test_env_lock() -> TestEnvLockGuard {
    let path = env::temp_dir().join(format!("agent-api-test-env-{}.lock", std::process::id()));

    loop {
        match OpenOptions::new().write(true).create_new(true).open(&path) {
            Ok(file) => {
                return TestEnvLockGuard { path, _file: file };
            }
            Err(err) if err.kind() == ErrorKind::AlreadyExists => {
                thread::sleep(Duration::from_millis(5));
            }
            Err(err) => panic!("test env lock should be acquired: {err}"),
        }
    }
}

impl Drop for TestEnvLockGuard {
    fn drop(&mut self) {
        if let Err(err) = fs::remove_file(&self.path) {
            assert!(
                err.kind() == ErrorKind::NotFound,
                "test env lock should be released: {err}"
            );
        }
    }
}

pub(crate) struct CurrentDirGuard {
    previous: PathBuf,
}

impl CurrentDirGuard {
    pub(crate) fn set(path: &Path) -> Self {
        let previous = env::current_dir().unwrap_or_else(|_| env::temp_dir());
        env::set_current_dir(path).expect("current dir should be set");
        Self { previous }
    }
}

impl Drop for CurrentDirGuard {
    fn drop(&mut self) {
        if env::set_current_dir(&self.previous).is_err() {
            env::set_current_dir(env::temp_dir()).expect("fallback current dir should be restored");
        }
    }
}