codex-auth-manager 0.1.1

A deadly simple Codex auth manager.
Documentation
use std::{
    env::current_dir,
    fs,
    path::{Component, Path, PathBuf},
};

use super::Error;

pub const AUTH_FILE: &str = "auth.json";
pub const STORAGE_SUFFIX: &str = ".json";

pub fn absolutize(path: &Path) -> Result<PathBuf, Error> {
    if path.is_absolute() {
        Ok(path.to_path_buf())
    } else {
        Ok(current_dir()
            .map_err(|source| Error::CurrentDir { source })?
            .join(path))
    }
}

pub fn normalize_path(path: &Path) -> PathBuf {
    let mut normalized = PathBuf::new();
    for component in path.components() {
        match component {
            Component::CurDir => {}
            Component::ParentDir => {
                normalized.pop();
            }
            Component::Prefix(_) | Component::RootDir | Component::Normal(_) => {
                normalized.push(component.as_os_str());
            }
        }
    }
    normalized
}

pub fn is_broken_identity_path(path: &Path) -> Result<bool, Error> {
    fs::symlink_metadata(path)
        .map(|metadata| !metadata.file_type().is_file())
        .map_err(|source| Error::Io {
            action: "inspect identity",
            path: path.to_path_buf(),
            source,
        })
}

#[cfg(unix)]
pub fn create_symlink(target: impl AsRef<Path>, link: impl AsRef<Path>) -> std::io::Result<()> {
    std::os::unix::fs::symlink(target, link)
}

#[cfg(windows)]
pub fn create_symlink(target: impl AsRef<Path>, link: impl AsRef<Path>) -> std::io::Result<()> {
    std::os::windows::fs::symlink_file(target, link)
}

pub fn replace_file(from: &Path, to: &Path) -> std::io::Result<()> {
    replace_file_impl(from, to)
}

#[cfg(unix)]
fn replace_file_impl(from: &Path, to: &Path) -> std::io::Result<()> {
    fs::rename(from, to)
}

#[cfg(windows)]
fn replace_file_impl(from: &Path, to: &Path) -> std::io::Result<()> {
    if to.exists() || to.is_symlink() {
        fs::remove_file(to)?;
    }
    fs::rename(from, to)
}