rpk 0.2.2

A lightweight, cross-platform cli package manager.
use std::{
    fs,
    io,
    os::unix::{self},
    path::Path,
};

use anyhow::Result;
use serde::Deserialize;
use tracing::trace;

pub fn symlink_force(src: impl AsRef<Path>, dst: impl AsRef<Path>) -> anyhow::Result<()> {
    let src = src.as_ref();
    let dst = dst.as_ref();

    if let Err(e) = fs::remove_file(dst) {
        if e.kind() != io::ErrorKind::NotFound {
            return Err(e.into());
        }
    }

    unix::fs::symlink(src, dst).map_err(Into::into)
}

pub fn mkdir_p(dir: impl AsRef<Path>) -> anyhow::Result<()> {
    trace!("creating directory: {:?}", dir.as_ref());
    match fs::create_dir_all(dir) {
        Ok(()) => Ok(()),
        Err(e) if e.kind() == io::ErrorKind::AlreadyExists => Ok(()),
        Err(e) => Err(e.into()),
    }
}

pub fn load_toml<T>(path: impl AsRef<Path>) -> Result<T>
where
    T: for<'de> Deserialize<'de>,
{
    let buf = fs::read_to_string(path)?;
    let config = toml::from_str(&buf)?;
    Ok(config)
}

pub fn remove_file_if_exists(path: impl AsRef<Path>) -> Result<()> {
    match fs::remove_file(path) {
        Err(e) if e.kind() != io::ErrorKind::NotFound => Err(e.into()),
        _ => Ok(()),
    }
}

/// Remove a file or directory.
pub fn rm_rf(path: &Path) -> io::Result<()> {
    let res = if path.is_dir() {
        fs::remove_dir_all(path)
    } else {
        fs::remove_file(path)
    };

    res.or_else(|e| match e.kind() {
        io::ErrorKind::NotFound => Ok(()),
        _ => Err(e),
    })
}