git_helpe_rs/
git_config.rs1use std::{collections::HashMap, fs, path::PathBuf};
2
3use crate::{
4 cli::{CommitOperationArguments, SetClipboardCommands, SetFormat, UseTemplate},
5 file_utils::config_file::get_path_to_config,
6};
7use anyhow::{Error, Result};
8use regex::Regex;
9use serde::{Deserialize, Serialize};
10
11#[derive(Debug, Serialize, Deserialize)]
12pub struct GitConfig {
13 pub data: Data,
14 config_path: PathBuf,
15}
16
17type Variants = HashMap<String, String>;
18
19#[derive(Debug, Serialize, Deserialize)]
20pub struct ClipboardCommands {
21 pub copy: String,
22 pub paste: String,
23}
24#[derive(Debug, Serialize, Deserialize)]
25pub struct Data {
26 pub clipboard_commands: ClipboardCommands,
27 pub commit_template_variants: Variants,
28 pub branch_template_variants: Variants,
29 pub branch_prefix_variants: Variants,
30 pub autocomplete_values: Option<Vec<String>>,
31}
32
33pub struct Templates {
34 pub commit_template_variants: Variants,
35 pub branch_template_variants: Variants,
36}
37
38pub enum BranchOrCommitAction {
39 Commit(CommitOperationArguments),
40 BranchFromTemplate(UseTemplate),
41}
42
43impl Data {
44 fn default() -> Self {
45 Data {
46 clipboard_commands: ClipboardCommands {
47 copy: "pbcopy".to_string(),
48 paste: "pbpaste".to_string(),
49 },
50 commit_template_variants: HashMap::new(),
51 branch_template_variants: HashMap::new(),
52 branch_prefix_variants: HashMap::new(),
53 autocomplete_values: None,
54 }
55 }
56}
57
58impl GitConfig {
59 fn default_config() -> Self {
60 return GitConfig {
61 data: Data::default(),
62 config_path: get_path_to_config(None).to_path_buf(),
63 };
64 }
65
66 pub fn new_config(
67 clipboard_commands: ClipboardCommands,
68 branch_prefix_variants: Variants,
69 branch_format_variants: Variants,
70 commit_format_variants: Variants,
71 config_path: Option<PathBuf>,
72 ) -> Self {
73 return GitConfig {
74 data: Data {
75 clipboard_commands,
76 branch_template_variants: branch_format_variants,
77 commit_template_variants: commit_format_variants,
78 branch_prefix_variants,
79 autocomplete_values: None,
80 },
81 config_path: if let Some(config_path) = config_path {
82 config_path
83 } else {
84 get_path_to_config(None).to_path_buf()
85 },
86 };
87 }
88
89 pub fn from_file(path_to_file: PathBuf) -> Self {
90 if fs::metadata(&path_to_file).is_ok() {
91 let contents = fs::read_to_string(&path_to_file);
92 let contents = contents.unwrap_or(
93 "{\
94 \"clipboard_commands\": {}, \
95 \"branch_template_variants\": {}, \
96 \"commit_template_variants\": {}, \
97 \"branch_prefix_variants\": {}
98 }"
99 .to_string(),
100 );
101
102 let data = serde_json::from_str(&contents);
103 let data: Data = data.unwrap_or(Data::default());
104
105 GitConfig {
106 data: data,
107 config_path: path_to_file,
108 }
109 } else {
110 Self::default_config()
111 }
112 }
113
114 pub fn validate_against_interpolation_regex<'a>(
115 string_to_interpolate: &'a String,
116 name_of_field_to_check: &'static str,
117 ) -> Result<&'a String> {
118 let interpolation_regex = Regex::new(r"\{.*?\}").unwrap();
119 if interpolation_regex.is_match(string_to_interpolate) {
120 return Ok(string_to_interpolate);
121 };
122 return Err(Error::msg(format!(
123 "There was no interpolation signature: {{}} introduced in {name_of_field_to_check}"
124 )));
125 }
126
127 pub fn set_branch_template_variant(&mut self, arg: SetFormat) -> Result<()> {
128 let result = Self::validate_against_interpolation_regex(&arg.value, "branch_template");
129 match result {
130 Err(e) => panic!("{}", e),
131 Ok(_) => self
132 .data
133 .branch_template_variants
134 .insert(arg.key, arg.value),
135 };
136 self.save_to_file()
137 }
138
139 pub fn set_commit_template_variant(&mut self, arg: SetFormat) -> Result<()> {
140 let result = Self::validate_against_interpolation_regex(&arg.value, "commit_template");
141 match result {
142 Err(e) => panic!("{}", e),
143 Ok(_) => {
144 self.data
145 .commit_template_variants
146 .insert(arg.key, arg.value);
147 }
148 };
149 self.save_to_file()
150 }
151
152 pub fn set_branch_prefix_variant(&mut self, key: String, value: String) -> Result<()> {
153 self.data.branch_prefix_variants.insert(key, value);
154 self.save_to_file()
155 }
156
157 pub fn set_clipboard_command(&mut self, args: SetClipboardCommands) -> Result<()> {
158 let new_clipboard_commands = ClipboardCommands {
159 copy: args.copy,
160 paste: args.paste,
161 };
162
163 self.data.clipboard_commands = new_clipboard_commands;
164 self.save_to_file()
165 }
166
167 pub fn delete_branch_prefix_variant(&mut self, key: String) -> Result<()> {
168 let old_val = self.data.branch_prefix_variants.remove(&key);
169 println!(
170 "Removed {} : {} from config ",
171 key,
172 old_val.unwrap_or(String::from("None"))
173 );
174 self.save_to_file()
175 }
176
177 fn save_to_file(&self) -> Result<()> {
178 if let Some(dir) = self.config_path.parent() {
179 if !std::fs::metadata(&dir).is_ok() {
180 std::fs::create_dir_all(dir)?;
181 }
182 };
183
184 let contents = serde_json::to_string(&self.data)?;
185 std::fs::write(&self.config_path, contents)?;
186 return Ok(());
187 }
188
189 pub fn display_config(&self) -> Result<String> {
190 let clipboard_command = &self.data.clipboard_commands;
191 let copy = &clipboard_command.copy;
192 let paste = &clipboard_command.paste;
193 let branch = self.data.branch_template_variants.to_owned();
194 let commit = self.data.commit_template_variants.to_owned();
195 let prefixes = self.data.branch_prefix_variants.to_owned();
196
197 Ok(format!(
198 "
199 clipboard commands: {{
200 \"copy\": {:?}
201 \"paste\": {:?}
202 }}
203 branch formats: {:?}
204 commit formats: {:?}
205 branch prefixes: {:?}
206 ",
207 *copy, *paste, branch, commit, prefixes
208 ))
209 }
210}