Skip to main content

git_side/commands/
add.rs

1use std::path::Path;
2
3use colored::Colorize;
4
5use crate::error::{Error, Result};
6use crate::git;
7use crate::side_repo::SideRepo;
8use crate::tracked::TrackedPaths;
9
10/// Add a path to side tracking.
11///
12/// # Errors
13///
14/// Returns an error if the path doesn't exist, is already tracked, or if staging fails.
15pub fn run(path: &Path) -> Result<()> {
16    let work_tree = git::repo_root()?;
17
18    // Normalize path: make it relative to work tree
19    let relative_path = if path.is_absolute() {
20        path.strip_prefix(&work_tree)
21            .map_or_else(|_| path.to_path_buf(), Path::to_path_buf)
22    } else {
23        path.to_path_buf()
24    };
25
26    // Check if path exists
27    let full_path = work_tree.join(&relative_path);
28    if !full_path.exists() {
29        return Err(Error::PathNotFound(relative_path));
30    }
31
32    // Open side repo (lazy init)
33    let repo = SideRepo::open()?;
34    repo.ensure_initialized()?;
35
36    // Load tracked paths
37    let mut tracked = TrackedPaths::load(&repo)?;
38
39    // Check if already tracked
40    if tracked.contains(&relative_path) {
41        return Err(Error::PathAlreadyTracked(relative_path));
42    }
43
44    // Add to tracked list
45    tracked.add(&relative_path);
46    tracked.save()?;
47
48    // Stage the path
49    repo.stage(&relative_path)?;
50
51    // Stage .side-tracked file itself
52    repo.stage_tracked_file()?;
53
54    println!(
55        "{} {}",
56        "Tracking:".green().bold(),
57        relative_path.display()
58    );
59
60    Ok(())
61}