rusty_hooks_integration/
lib.rs

1use std::collections::HashMap;
2
3mod config;
4pub use config::NO_CONFIG_FILE_FOUND;
5
6mod git;
7pub use git::NO_CONFIG_FILE_FOUND_ERROR_CODE;
8
9pub mod hooks;
10
11pub fn init_directory<F, G, H>(
12    run_command: F,
13    write_file: G,
14    file_exists: H,
15    target_directory: Option<&str>,
16    hook_file_skip_list: Vec<&str>,
17) -> Result<(), String>
18where
19    F: Fn(
20        &str,
21        Option<&str>,
22        bool,
23        Option<&HashMap<String, String>>,
24    ) -> Result<Option<String>, Option<String>>,
25    G: Fn(&str, &str, bool) -> Result<(), String>,
26    H: Fn(&str) -> Result<bool, ()>,
27{
28    let root_directory_path = match git::get_root_directory_path(&run_command, target_directory) {
29        Ok(Some(path)) => path,
30        _ => return Err(String::from("Failure determining git repo root directory")),
31    };
32    if git::setup_hooks(
33        &run_command,
34        &write_file,
35        &root_directory_path,
36        &hook_file_skip_list,
37    )
38    .is_err()
39    {
40        return Err(String::from("Unable to create git hooks"));
41    };
42
43    if config::create_default_config_file(&write_file, &file_exists, &root_directory_path).is_err()
44    {
45        return Err(String::from("Unable to create config file"));
46    }
47
48    Ok(())
49}
50
51pub fn init<F, G, H>(
52    run_command: F,
53    write_file: G,
54    file_exists: H,
55    hook_file_skip_list: Vec<&str>,
56) -> Result<(), String>
57where
58    F: Fn(
59        &str,
60        Option<&str>,
61        bool,
62        Option<&HashMap<String, String>>,
63    ) -> Result<Option<String>, Option<String>>,
64    G: Fn(&str, &str, bool) -> Result<(), String>,
65    H: Fn(&str) -> Result<bool, ()>,
66{
67    init_directory(
68        &run_command,
69        &write_file,
70        &file_exists,
71        None,
72        hook_file_skip_list,
73    )
74}
75
76pub fn run<F, G, H, I>(
77    run_command: F,
78    file_exists: G,
79    read_file: H,
80    log: I,
81    hook_name: &str,
82    args: Option<String>,
83) -> Result<(), Option<String>>
84where
85    F: Fn(
86        &str,
87        Option<&str>,
88        bool,
89        Option<&HashMap<String, String>>,
90    ) -> Result<Option<String>, Option<String>>,
91    G: Fn(&str) -> Result<bool, ()>,
92    H: Fn(&str) -> Result<String, ()>,
93    I: Fn(&str, bool),
94{
95    let root_directory_path = match git::get_root_directory_path(&run_command, None) {
96        Ok(Some(path)) => path,
97        _ => {
98            return Err(Some(String::from(
99                "Failure determining git repo root directory",
100            )));
101        }
102    };
103
104    let config_file_contents =
105        config::get_config_file_contents(read_file, file_exists, &root_directory_path).map_err(
106            |e| {
107                if e == config::NO_CONFIG_FILE_FOUND {
108                    Some(e)
109                } else {
110                    Some(String::from("Failed to parse config file"))
111                }
112            },
113        )?;
114
115    let log_details = config::get_log_setting(&config_file_contents);
116    let (script, env_vars) = match (
117        config::get_hook_script(&config_file_contents, hook_name),
118        args,
119    ) {
120        (Ok(script), None) => (script, None),
121        (Ok(script), Some(a)) => (
122            script.replace("%rh!", &a),
123            Some(
124                vec![("RUSTY_HOOKS_GIT_PARAMS".to_owned(), a)]
125                    .into_iter()
126                    .collect::<HashMap<String, String>>(),
127            ),
128        ),
129        (Err(err), _) => {
130            if err == config::MISSING_CONFIG_KEY {
131                return Ok(());
132            }
133            return Err(Some(String::from("Invalid rusty-hooks config file")));
134        }
135    };
136
137    let message = format!(
138        "[rusty-hooks] Found configured hook: {hook_name}\n[rusty-hooks] Running command: {script}\n"
139    );
140    log(&message, log_details);
141
142    run_command(
143        &script,
144        Some(&root_directory_path),
145        log_details,
146        env_vars.as_ref(),
147    )
148    .map(|_| ())
149}
150
151#[cfg(test)]
152mod tests;