Skip to main content

git_worktree_manager/
shared_files.rs

1/// File sharing for worktrees via .cwshare configuration.
2///
3/// Reads .cwshare file from repository root and copies specified files
4/// to new worktrees during creation.
5use std::path::Path;
6
7use console::style;
8
9/// Parse .cwshare file and return list of paths to share.
10pub fn parse_cwshare(repo_path: &Path) -> Vec<String> {
11    let cwshare_path = repo_path.join(".cwshare");
12    if !cwshare_path.exists() {
13        return Vec::new();
14    }
15
16    match std::fs::read_to_string(&cwshare_path) {
17        Ok(content) => content
18            .lines()
19            .map(|l| l.trim())
20            .filter(|l| !l.is_empty() && !l.starts_with('#'))
21            .map(String::from)
22            .collect(),
23        Err(_) => Vec::new(),
24    }
25}
26
27/// Copy files specified in .cwshare to target worktree.
28pub fn share_files(source_repo: &Path, target_worktree: &Path) {
29    let paths = parse_cwshare(source_repo);
30    if paths.is_empty() {
31        return;
32    }
33
34    println!("\n{}", style("Copying shared files:").cyan().bold());
35
36    for rel_path in &paths {
37        let source = source_repo.join(rel_path);
38        let target = target_worktree.join(rel_path);
39
40        if !source.exists() || target.exists() {
41            continue;
42        }
43
44        let result = if source.is_dir() {
45            copy_dir_recursive(&source, &target)
46        } else {
47            if let Some(parent) = target.parent() {
48                let _ = std::fs::create_dir_all(parent);
49            }
50            std::fs::copy(&source, &target).map(|_| ())
51        };
52
53        match result {
54            Ok(()) => println!("  {} Copied: {}", style("*").green(), rel_path),
55            Err(e) => println!("  {} Failed: {}: {}", style("!").yellow(), rel_path, e),
56        }
57    }
58    println!();
59}
60
61fn copy_dir_recursive(src: &Path, dst: &Path) -> std::io::Result<()> {
62    std::fs::create_dir_all(dst)?;
63    for entry in std::fs::read_dir(src)? {
64        let entry = entry?;
65        let ty = entry.file_type()?;
66        let dst_path = dst.join(entry.file_name());
67        if ty.is_dir() {
68            copy_dir_recursive(&entry.path(), &dst_path)?;
69        } else if ty.is_symlink() {
70            let target = std::fs::read_link(entry.path())?;
71            #[cfg(unix)]
72            std::os::unix::fs::symlink(&target, &dst_path)?;
73            #[cfg(windows)]
74            std::os::windows::fs::symlink_file(&target, &dst_path)?;
75        } else {
76            std::fs::copy(entry.path(), &dst_path)?;
77        }
78    }
79    Ok(())
80}