x-git-hooks 0.0.1

Git Hooks Manager
Documentation
use serde::Deserialize;
use serde_yaml::from_str;
use std::env::var;
use std::fs::read_to_string;
use std::path::PathBuf;

#[derive(Debug, Deserialize)]
struct ConfigFile {
    mode: Option<String>,
    hooks_path: Option<String>,
}

#[derive(Debug, PartialEq)]
pub enum GitHooksMode {
    Single,
    Multi,
}

#[derive(Debug)]
pub struct GitHooksConfig {
    pub mode: GitHooksMode,
    pub hooks_path: PathBuf,
}

fn get_mode(config: &ConfigFile) -> Result<GitHooksMode, ()> {
    let mode = var("GIT_HOOKS_MODE");

    if mode.is_ok() {
        return match mode.unwrap_or_default().as_ref() {
            "single" => Ok(GitHooksMode::Single),
            "multi" => Ok(GitHooksMode::Multi),
            _ => Err(()),
        };
    }

    if let Some(mode) = &config.mode {
        return match mode.as_ref() {
            "single" => Ok(GitHooksMode::Single),
            "multi" => Ok(GitHooksMode::Multi),
            _ => Err(()),
        };
    }

    Ok(GitHooksMode::Single)
}

fn get_hooks_path(config: &ConfigFile, git_root: &PathBuf) -> PathBuf {
    let hooks_path = var("GIT_HOOKS_PATH");

    if let Ok(path) = hooks_path {
        return git_root.join(path);
    }

    if let Some(hooks_path) = &config.hooks_path {
        return git_root.join(hooks_path);
    }

    git_root.join(".git-hooks")
}

pub fn get_config(git_root: &PathBuf) -> Result<GitHooksConfig, serde_yaml::Error> {
    let config_path = git_root.join(".git-hooks.yml");

    let config_blob = match config_path.exists() {
        true => read_to_string(config_path).expect("error reading config file!"),
        false => String::from("mode: single"),
    };

    let config: ConfigFile = from_str(&config_blob)?;

    let mode = get_mode(&config).expect("invalid config: mode");
    let hooks_path = get_hooks_path(&config, git_root);

    Ok(GitHooksConfig { mode, hooks_path })
}