native macOS codings agent orchestrator
6
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge pull request #57 from supabitapp/lively-tiger

Make worktree removal resilient to git status failures

authored by

khoi and committed by
GitHub
ea289eec 087a3a53

+28 -26
+14 -12
Resources/git-wt/wt
··· 670 670 if [ "$path" = "$root" ]; then 671 671 die "cannot remove main worktree" 672 672 fi 673 - local dirty 674 - dirty=$(git -C "$path" status --porcelain) 675 - if [ -n "$dirty" ] && [ "$force" -eq 0 ]; then 676 - if [ -t 0 ]; then 677 - printf "workspace '%s' has uncommitted changes. remove anyway? [y/N] " "$branch" >&2 678 - read -r answer 679 - case "$answer" in 680 - y | Y | yes | YES) force=1 ;; 681 - *) exit 1 ;; 682 - esac 683 - else 684 - die "workspace dirty: '$branch'" 673 + if [ "$force" -eq 0 ]; then 674 + local dirty 675 + dirty=$(git -C "$path" status --porcelain 2>/dev/null || true) 676 + if [ -n "$dirty" ]; then 677 + if [ -t 0 ]; then 678 + printf "workspace '%s' has uncommitted changes. remove anyway? [y/N] " "$branch" >&2 679 + read -r answer 680 + case "$answer" in 681 + y | Y | yes | YES) force=1 ;; 682 + *) exit 1 ;; 683 + esac 684 + else 685 + die "workspace dirty: '$branch'" 686 + fi 685 687 fi 686 688 fi 687 689 if [ "$force" -eq 1 ]; then
+7 -3
supacode/Clients/Git/GitClient.swift
··· 126 126 ) 127 127 } 128 128 129 - nonisolated func isWorktreeDirty(at worktreeURL: URL) async throws -> Bool { 129 + nonisolated func isWorktreeDirty(at worktreeURL: URL) async -> Bool { 130 130 let path = worktreeURL.path(percentEncoded: false) 131 - let output = try await runGit(arguments: ["-C", path, "status", "--porcelain"]) 132 - return WorktreeDirtCheck.isDirty(statusOutput: output) 131 + do { 132 + let output = try await runGit(arguments: ["-C", path, "status", "--porcelain"]) 133 + return WorktreeDirtCheck.isDirty(statusOutput: output) 134 + } catch { 135 + return true 136 + } 133 137 } 134 138 135 139 nonisolated func removeWorktree(_ worktree: Worktree) async throws -> URL {
+2 -2
supacode/Clients/Repositories/GitClientDependency.swift
··· 6 6 var worktrees: @Sendable (URL) async throws -> [Worktree] 7 7 var localBranchNames: @Sendable (URL) async throws -> Set<String> 8 8 var createWorktree: @Sendable (_ name: String, _ repoRoot: URL) async throws -> Worktree 9 - var isWorktreeDirty: @Sendable (URL) async throws -> Bool 9 + var isWorktreeDirty: @Sendable (URL) async -> Bool 10 10 var removeWorktree: @Sendable (_ worktree: Worktree) async throws -> URL 11 11 } 12 12 ··· 18 18 createWorktree: { name, repoRoot in 19 19 try await GitClient().createWorktree(named: name, in: repoRoot) 20 20 }, 21 - isWorktreeDirty: { try await GitClient().isWorktreeDirty(at: $0) }, 21 + isWorktreeDirty: { await GitClient().isWorktreeDirty(at: $0) }, 22 22 removeWorktree: { worktree in 23 23 try await GitClient().removeWorktree(worktree) 24 24 }
+5 -9
supacode/Features/Repositories/Reducer/RepositoriesFeature.swift
··· 313 313 return .none 314 314 } 315 315 return .run { send in 316 - do { 317 - let dirty = try await gitClient.isWorktreeDirty(worktree.workingDirectory) 318 - if dirty { 319 - await send(.presentWorktreeRemovalConfirmation(worktree.id, repository.id)) 320 - } else { 321 - await send(.removeWorktreeConfirmed(worktree.id, repository.id)) 322 - } 323 - } catch { 324 - await send(.worktreeRemovalFailed(error.localizedDescription, worktreeID: worktree.id)) 316 + let dirty = await gitClient.isWorktreeDirty(worktree.workingDirectory) 317 + if dirty { 318 + await send(.presentWorktreeRemovalConfirmation(worktree.id, repository.id)) 319 + } else { 320 + await send(.removeWorktreeConfirmed(worktree.id, repository.id)) 325 321 } 326 322 } 327 323