Skip to main content

git_claw/infra/
fs.rs

1//! Filesystem utilities and shared cache directory symlinking.
2
3use crate::core::config::{CacheConfig, CacheStrategy};
4use std::fs;
5use std::io;
6use std::path::Path;
7
8#[cfg(unix)]
9use std::os::unix::fs::symlink;
10
11#[cfg(windows)]
12use std::os::windows::fs::symlink_dir as symlink;
13
14/// Links configured cache directories from the primary repository into the worktree
15/// using symlinks, unless `isolated` is specified or strategy is isolated.
16/// Returns the number of symlinks successfully created.
17pub fn link_shared_cache_directories(
18    repo_root: &Path,
19    worktree_path: &Path,
20    cache_config: &CacheConfig,
21    isolated: bool,
22) -> io::Result<usize> {
23    if isolated || cache_config.strategy == CacheStrategy::Isolated {
24        return Ok(0);
25    }
26
27    let mut linked_count = 0;
28    for dir_rel in &cache_config.directories {
29        let dir_rel = dir_rel.trim();
30        if dir_rel.is_empty() {
31            continue;
32        }
33
34        let primary_dir = repo_root.join(dir_rel);
35        if !primary_dir.exists() {
36            fs::create_dir_all(&primary_dir)?;
37        }
38
39        let worktree_target = worktree_path.join(dir_rel);
40        if worktree_target.exists() || worktree_target.is_symlink() {
41            let _ = fs::remove_file(&worktree_target).or_else(|_| fs::remove_dir(&worktree_target));
42        }
43
44        if let Some(parent) = worktree_target.parent() {
45            fs::create_dir_all(parent)?;
46        }
47
48        symlink(&primary_dir, &worktree_target)?;
49        linked_count += 1;
50    }
51
52    Ok(linked_count)
53}