envvault/cli/
gitignore.rs1use std::fs;
7use std::path::Path;
8
9use crate::cli::output;
10
11pub fn patch_gitignore(project_dir: &Path, entry: &str) {
16 let gitignore_path = project_dir.join(".gitignore");
17
18 let existing = fs::read_to_string(&gitignore_path).unwrap_or_default();
19
20 if existing.lines().any(|line| line.trim() == entry) {
21 return;
22 }
23
24 let separator = if existing.ends_with('\n') || existing.is_empty() {
25 ""
26 } else {
27 "\n"
28 };
29
30 if fs::write(&gitignore_path, format!("{existing}{separator}{entry}\n")).is_ok() {
31 output::info(&format!("Added '{entry}' to .gitignore"));
32 }
33}
34
35#[cfg(test)]
36mod tests {
37 use super::*;
38 use tempfile::TempDir;
39
40 #[test]
41 fn adds_entry_to_new_gitignore() {
42 let dir = TempDir::new().unwrap();
43 patch_gitignore(dir.path(), ".envvault/");
44
45 let content = fs::read_to_string(dir.path().join(".gitignore")).unwrap();
46 assert!(content.contains(".envvault/"));
47 }
48
49 #[test]
50 fn does_not_duplicate_entry() {
51 let dir = TempDir::new().unwrap();
52 fs::write(dir.path().join(".gitignore"), ".envvault/\n").unwrap();
53
54 patch_gitignore(dir.path(), ".envvault/");
55
56 let content = fs::read_to_string(dir.path().join(".gitignore")).unwrap();
57 assert_eq!(content.matches(".envvault/").count(), 1);
58 }
59
60 #[test]
61 fn appends_with_newline_separator() {
62 let dir = TempDir::new().unwrap();
63 fs::write(dir.path().join(".gitignore"), "node_modules/").unwrap(); patch_gitignore(dir.path(), ".envvault/");
66
67 let content = fs::read_to_string(dir.path().join(".gitignore")).unwrap();
68 assert_eq!(content, "node_modules/\n.envvault/\n");
69 }
70}