use crate::{Config, Global, SolarError, ToolTrait};
use clap::Parser;
use derive_getters::Getters;
use rust_terminal::Terminal;
use serde::{Deserialize, Serialize};
use std::{
fs,
path::{Path, PathBuf},
};
fn default_name() -> String {
".hooks".to_string()
}
#[derive(Parser, Clone, Default, PartialEq, Debug, Serialize, Deserialize, Getters)]
pub struct Vhooks {
#[arg(short, long, default_value = ".")]
#[serde(skip)]
destination: PathBuf,
#[arg(short, long, default_value = ".hooks")]
#[serde(default = "default_name")]
name: String,
#[arg(short, long, default_value = "false")]
#[serde(skip)]
remove_all: bool,
}
impl Vhooks {
pub fn new(destination: PathBuf, name: String, remove_all: bool) -> Self {
Self {
destination,
name,
remove_all,
}
}
pub fn move_hooks(prev: &PathBuf, new: &Path) -> Result<(), SolarError> {
for item in fs::read_dir(prev)? {
let item = item?;
fs::rename(item.path(), new.join(item.file_name()))?;
}
Ok(())
}
pub fn set_hooks_path(&self, path: PathBuf) -> Result<(), SolarError> {
Terminal::command()
.current_dir(&self.destination)
.piped()
.run(
"git",
vec![
"config",
"core.hooksPath",
path.to_str().ok_or("Could not convert path to string.")?,
],
)?;
Ok(())
}
}
impl ToolTrait for Vhooks {
fn set_dest(&mut self, dest: &Path) {
self.destination = dest.to_path_buf();
}
fn install(&mut self) -> Result<(), SolarError> {
let config = Config::load_or_default(&self.destination);
let current_tool_cfg = config.vhooks().clone();
config.set_vhooks(Some(self.clone())).save()?;
Global::git_init(&self.destination)?;
let hooks_path = self.destination.join(&self.name);
fs::create_dir_all(&hooks_path)?;
self.set_hooks_path(PathBuf::from(format!("./{}", &self.name)))?;
if let Some(vhooks) = current_tool_cfg {
let old_hooks_path = self.destination.join(vhooks.name());
Self::move_hooks(&old_hooks_path, &hooks_path)?;
fs::remove_dir_all(&old_hooks_path)?;
}
Ok(())
}
fn uninstall(&mut self) -> Result<(), SolarError> {
let config = Config::load_from(&self.destination)?;
let current_tool_cfg: Self = config
.vhooks()
.clone()
.ok_or("Cannot uninstall vhooks - vhooks not found in configuration.")?;
let hooks_path = self.destination.join(current_tool_cfg.name());
let default_path = self.destination.join(Global::default_git_hook_dir());
Global::is_git(&self.destination)?;
fs::create_dir_all(&default_path)?;
if !self.remove_all {
Self::move_hooks(&hooks_path, &default_path)?;
}
self.set_hooks_path(PathBuf::from(format!(
"./{}",
Global::default_git_hook_dir()
.to_str()
.ok_or("Could not convert path to string.")?
)))?;
fs::remove_dir_all(&hooks_path)?;
let config = config.set_vhooks(None);
match config.is_empty() {
true => fs::remove_file(config.path())?,
false => config.save()?,
}
Ok(())
}
}