Fix worktree cleanup looping on orphaned directories
When git worktree remove fails with "not a working tree", fall back to removing the directory directly and run git worktree prune to clean stale metadata. Fixes bug 364. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -253,7 +253,23 @@ fn remove_worktree_sync(project_root: &Path, wt_path: &Path, branch: &str) -> Re
|
||||
|
||||
if !output.status.success() {
|
||||
let stderr = String::from_utf8_lossy(&output.stderr);
|
||||
slog!("[worktree] remove warning: {stderr}");
|
||||
if stderr.contains("not a working tree") {
|
||||
// Orphaned directory: git doesn't recognise it as a worktree.
|
||||
// Remove the directory directly and prune stale git metadata.
|
||||
slog!(
|
||||
"[worktree] orphaned worktree detected, removing directory: {}",
|
||||
wt_path.display()
|
||||
);
|
||||
if let Err(e) = std::fs::remove_dir_all(wt_path) {
|
||||
slog!("[worktree] failed to remove orphaned directory: {e}");
|
||||
}
|
||||
let _ = Command::new("git")
|
||||
.args(["worktree", "prune"])
|
||||
.current_dir(project_root)
|
||||
.output();
|
||||
} else {
|
||||
slog!("[worktree] remove warning: {stderr}");
|
||||
}
|
||||
}
|
||||
|
||||
// Delete branch (best effort)
|
||||
@@ -630,6 +646,28 @@ mod tests {
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn remove_worktree_sync_removes_orphaned_directory() {
|
||||
let tmp = TempDir::new().unwrap();
|
||||
let project_root = tmp.path().join("my-project");
|
||||
fs::create_dir_all(&project_root).unwrap();
|
||||
init_git_repo(&project_root);
|
||||
|
||||
// Create a directory that looks like a worktree but isn't registered with git
|
||||
let wt_path = project_root
|
||||
.join(".storkit")
|
||||
.join("worktrees")
|
||||
.join("orphan");
|
||||
fs::create_dir_all(&wt_path).unwrap();
|
||||
fs::write(wt_path.join("some_file.txt"), "stale").unwrap();
|
||||
assert!(wt_path.exists());
|
||||
|
||||
// git worktree remove will fail with "not a working tree",
|
||||
// but the fallback should rm -rf the directory
|
||||
remove_worktree_sync(&project_root, &wt_path, "feature/orphan").unwrap();
|
||||
assert!(!wt_path.exists());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn remove_worktree_sync_cleans_up_directory() {
|
||||
let tmp = TempDir::new().unwrap();
|
||||
|
||||
Reference in New Issue
Block a user