shepherd-cli 6.7.1

The canonical shepherd command-line interface over the per-project registry, run artifacts, and sprint pipeline.
//! Drop-safe ownership for linked-worktree fixtures created outside a TempDir.

use std::{
    ops::Deref,
    path::{Path, PathBuf},
    process::Command,
    thread,
    time::Duration,
};

pub(crate) struct LinkedWorktreeGuard {
    repository: PathBuf,
    path: PathBuf,
}

impl LinkedWorktreeGuard {
    pub(crate) fn new(repository: &Path, path: PathBuf) -> Self {
        assert_ne!(
            repository, path,
            "linked worktree cannot replace its repository"
        );
        assert_eq!(
            repository.parent(),
            path.parent(),
            "fixture worktree must be a sibling of its owning repository"
        );
        Self {
            repository: repository.to_path_buf(),
            path,
        }
    }

    pub(crate) fn path(&self) -> &Path {
        &self.path
    }

    pub(crate) fn remove(&self) -> bool {
        if !self.path.exists() {
            let _ = Command::new("git")
                .args(["worktree", "prune"])
                .current_dir(&self.repository)
                .status();
            return true;
        }
        let _ = Command::new("git")
            .args(["worktree", "remove", "--force"])
            .arg(&self.path)
            .current_dir(&self.repository)
            .status()
            .is_ok_and(|status| status.success());
        let _ = Command::new("git")
            .args(["worktree", "prune"])
            .current_dir(&self.repository)
            .status();
        if !self.path.exists() {
            return true;
        }
        for attempt in 0..100 {
            match std::fs::remove_dir_all(&self.path) {
                Ok(()) => break,
                Err(error) if error.kind() == std::io::ErrorKind::NotFound => break,
                Err(_) if attempt < 99 => thread::sleep(Duration::from_millis(10)),
                Err(_) => break,
            }
        }
        let _ = Command::new("git")
            .args(["worktree", "prune"])
            .current_dir(&self.repository)
            .status();
        !self.path.exists()
    }
}

impl Deref for LinkedWorktreeGuard {
    type Target = Path;

    fn deref(&self) -> &Self::Target {
        &self.path
    }
}

impl AsRef<Path> for LinkedWorktreeGuard {
    fn as_ref(&self) -> &Path {
        &self.path
    }
}

impl Drop for LinkedWorktreeGuard {
    fn drop(&mut self) {
        if !self.remove() {
            eprintln!(
                "linked worktree fixture survived cleanup: {}",
                self.path.display()
            );
        }
    }
}