fix: IsWorkingDirectoryClean to work correctly in worktrees

- Check filesystem existence of staged files to handle worktree scenarios
- Ignore files staged in main repo that don't exist in worktree
- Allow staged files that exist in worktree to be committed normally

Co-Authored-By: Warp <agent@warp.dev>
This commit is contained in:
Kayvan Sylvan
2026-01-03 14:16:09 -08:00
parent 11e9e16078
commit 53bad5b70d

View File

@@ -2,6 +2,8 @@ package git
import (
"fmt"
"os"
"path/filepath"
"regexp"
"strconv"
"strings"
@@ -433,14 +435,27 @@ func (w *Walker) IsWorkingDirectoryClean() (bool, error) {
return false, fmt.Errorf("failed to get git status: %w", err)
}
// In worktrees, we need to check if files are actually modified in the working directory
// Ignore files that are only staged (Added) but not present in the worktree filesystem
for _, fileStatus := range status {
// Check if there are any changes in the working directory (not just staging)
// Worktree status codes: ' ' = unmodified, 'M' = modified, 'D' = deleted, '?' = untracked
worktreePath := worktree.Filesystem.Root()
// In worktrees, files staged in the main repo may appear in status but not exist in the worktree
// We need to check both the working directory status AND filesystem existence
for file, fileStatus := range status {
// Check if there are any changes in the working directory
if fileStatus.Worktree != git.Unmodified && fileStatus.Worktree != git.Untracked {
return false, nil
}
// For staged files (Added, Modified in index), verify they exist in this worktree's filesystem
// This handles the worktree case where the main repo has staged files that don't exist here
if fileStatus.Staging != git.Unmodified && fileStatus.Staging != git.Untracked {
filePath := filepath.Join(worktreePath, file)
if _, err := os.Stat(filePath); os.IsNotExist(err) {
// File is staged but doesn't exist in this worktree - ignore it
continue
}
// File is staged AND exists in this worktree - not clean
return false, nil
}
}
return true, nil