thoughts_tool/utils/
git.rs

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