Skip to main content

solar_core/tool/
pre_commit.rs

1use crate::{Config, Global, SolarError, ToolTrait};
2use clap::Parser;
3use derive_getters::Getters;
4use serde::{Deserialize, Serialize};
5use std::{
6    fs,
7    io::Write,
8    path::{Path, PathBuf},
9};
10
11mod script;
12pub use script::Script;
13
14#[derive(Parser, Clone, Default, PartialEq, Debug, Serialize, Deserialize, Getters)]
15pub struct PreCommit {
16    /// The working directory to use for installation.
17    #[arg(short, long, default_value = ".")]
18    #[serde(skip)]
19    destination: PathBuf,
20
21    // The script to use as the pre-commit hook.
22    #[arg(short, long)]
23    script: Option<Script>,
24}
25
26impl PreCommit {
27    pub fn new(destination: PathBuf, script: Option<Script>) -> Self {
28        Self {
29            destination,
30            script,
31        }
32    }
33
34    fn precommit_path(&self) -> Result<PathBuf, SolarError> {
35        let git_hooks_path = Global::git_hooks_path(&self.destination)?;
36        Ok(self.destination.join(git_hooks_path.join("pre-commit")))
37    }
38}
39
40impl ToolTrait for PreCommit {
41    fn set_dest(&mut self, dest: &Path) {
42        self.destination = dest.to_path_buf();
43    }
44
45    fn install(&mut self) -> Result<(), SolarError> {
46        let script = self.script.as_ref().ok_or("No script value provided")?;
47        // Update configuration file.
48        let config = Config::load_or_default(&self.destination);
49        config.set_pre_commit(Some(self.clone())).save()?;
50
51        // Ensure working directory is a git repository.
52        Global::git_init(&self.destination)?;
53
54        let mut precommit_file = Global::ovrwrt_file_or_default(&self.precommit_path()?)?;
55        precommit_file.write_all(script.content().as_bytes())?;
56        Ok(())
57    }
58
59    fn uninstall(&mut self) -> Result<(), SolarError> {
60        // Get configuration file.
61        let config = Config::load_or_default(&self.destination);
62
63        // Remove pre-commit script.
64        fs::remove_file(self.precommit_path()?)?;
65
66        // Update configuration.
67        let config = config.set_pre_commit(None);
68        match config.is_empty() {
69            true => fs::remove_file(config.path())?,
70            false => config.save()?,
71        }
72
73        Ok(())
74    }
75}