Skip to main content

thoughts_tool/utils/
git.rs

1use std::fmt::Write;
2use std::fs;
3use std::path::Path;
4
5use anyhow::Result;
6use tracing::info;
7
8/// Ensures a gitignore entry exists in the repository's .gitignore file
9pub fn ensure_gitignore_entry(
10    repo_path: &Path,
11    entry: &str,
12    comment: Option<&str>,
13) -> Result<bool> {
14    let gitignore_path = repo_path.join(".gitignore");
15
16    // Check if .gitignore exists
17    if gitignore_path.exists() {
18        let content = fs::read_to_string(&gitignore_path)?;
19
20        // Check if entry is already ignored
21        let entry_no_slash = entry.trim_start_matches('/');
22        let has_entry = content.lines().any(|line| {
23            let trimmed = line.trim();
24            trimmed == entry || trimmed == entry_no_slash || trimmed == format!("{entry_no_slash}/")
25        });
26
27        if has_entry {
28            Ok(false)
29        } else {
30            // Append to .gitignore
31            let mut new_content = content;
32            if !new_content.ends_with('\n') {
33                new_content.push('\n');
34            }
35            if let Some(comment_text) = comment {
36                new_content.push('\n');
37                let _ = writeln!(new_content, "# {comment_text}");
38            }
39            new_content.push_str(entry);
40            new_content.push('\n');
41
42            fs::write(&gitignore_path, new_content)?;
43            info!("Added {} to .gitignore", entry);
44            Ok(true)
45        }
46    } else {
47        // Create new .gitignore
48        let mut content = String::new();
49        if let Some(comment_text) = comment {
50            let _ = writeln!(content, "# {comment_text}");
51        }
52        let _ = writeln!(content, "{entry}");
53
54        fs::write(&gitignore_path, content)?;
55        info!("Created .gitignore with {} entry", entry);
56        Ok(true)
57    }
58}