···11+import Foundation
22+33+struct RemoveRepositoryError: Identifiable, Hashable {
44+ let id: UUID
55+ let title: String
66+ let message: String
77+}
+79-8
supacode/RepositoryStore.swift
···1616 var openError: OpenRepositoryError?
1717 var createWorktreeError: CreateWorktreeError?
1818 var removeWorktreeError: RemoveWorktreeError?
1919+ var removeRepositoryError: RemoveRepositoryError?
1920 var loadError: LoadRepositoryError?
2021 var pendingWorktrees: [PendingWorktree] = []
2122 var deletingWorktreeIDs: Set<Worktree.ID> = []
2323+ var removingRepositoryIDs: Set<Repository.ID> = []
2224 private(set) var pinnedWorktreeIDs: [Worktree.ID] = []
23252426 var canCreateWorktree: Bool {
2527 if repositories.isEmpty {
2628 return false
2729 }
2828- if selectedWorktreeID != nil {
2929- return true
3030+ if let repository = repositoryForWorktreeCreation() {
3131+ return !isRemovingRepository(repository)
3032 }
3131- return repositories.count == 1
3333+ return false
3234 }
33353436 init(userDefaults: UserDefaults = .standard, gitClient: GitClient = .init()) {
···110112 )
111113 return
112114 }
115115+ if isRemovingRepository(repository) {
116116+ createWorktreeError = CreateWorktreeError(
117117+ id: UUID(),
118118+ title: "Unable to create worktree",
119119+ message: "This repository is being removed."
120120+ )
121121+ return
122122+ }
113123114124 await createRandomWorktree(in: repository)
115125 }
116126117127 func createRandomWorktree(in repository: Repository) async {
118128 createWorktreeError = nil
129129+ if isRemovingRepository(repository) {
130130+ createWorktreeError = CreateWorktreeError(
131131+ id: UUID(),
132132+ title: "Unable to create worktree",
133133+ message: "This repository is being removed."
134134+ )
135135+ return
136136+ }
119137 let previousSelection = selectedWorktreeID
120138 let pendingID = "pending:\(UUID().uuidString)"
121139 let pendingWorktree = PendingWorktree(
···188206 func worktreeRows(in repository: Repository) -> [WorktreeRowModel] {
189207 let ordered = orderedWorktrees(in: repository)
190208 let pinnedIDs = Set(pinnedWorktreeIDs)
209209+ let isRemovingRepository = removingRepositoryIDs.contains(repository.id)
191210 let pinnedWorktrees = ordered.filter { pinnedIDs.contains($0.id) }
192211 let unpinnedWorktrees = ordered.filter { !pinnedIDs.contains($0.id) }
193212 let pendingEntries = pendingWorktrees.filter { $0.repositoryID == repository.id }
194213 var rows: [WorktreeRowModel] = []
195214 for worktree in pinnedWorktrees {
196196- let isDeleting = deletingWorktreeIDs.contains(worktree.id)
215215+ let isDeleting = isRemovingRepository || deletingWorktreeIDs.contains(worktree.id)
197216 rows.append(
198217 WorktreeRowModel(
199218 id: worktree.id,
···216235 detail: pending.detail,
217236 isPinned: false,
218237 isPending: true,
219219- isDeleting: false,
238238+ isDeleting: isRemovingRepository,
220239 isRemovable: false
221240 )
222241 )
223242 }
224243 for worktree in unpinnedWorktrees {
225225- let isDeleting = deletingWorktreeIDs.contains(worktree.id)
244244+ let isDeleting = isRemovingRepository || deletingWorktreeIDs.contains(worktree.id)
226245 rows.append(
227246 WorktreeRowModel(
228247 id: worktree.id,
···242261 func selectedRow(for id: Worktree.ID?) -> WorktreeRowModel? {
243262 guard let id else { return nil }
244263 if let pending = pendingWorktree(for: id) {
264264+ let isDeleting = removingRepositoryIDs.contains(pending.repositoryID)
245265 return WorktreeRowModel(
246266 id: pending.id,
247267 repositoryID: pending.repositoryID,
···249269 detail: pending.detail,
250270 isPinned: false,
251271 isPending: true,
252252- isDeleting: false,
272272+ isDeleting: isDeleting,
253273 isRemovable: false
254274 )
255275 }
256276 for repository in repositories {
257277 if let worktree = repository.worktrees.first(where: { $0.id == id }) {
258258- let isDeleting = deletingWorktreeIDs.contains(worktree.id)
278278+ let isDeleting =
279279+ removingRepositoryIDs.contains(repository.id)
280280+ || deletingWorktreeIDs.contains(worktree.id)
259281 return WorktreeRowModel(
260282 id: worktree.id,
261283 repositoryID: repository.id,
···298320 pinnedWorktreeIDs.contains(worktree.id)
299321 }
300322323323+ func isRemovingRepository(_ repository: Repository) -> Bool {
324324+ removingRepositoryIDs.contains(repository.id)
325325+ }
326326+301327 func pinWorktree(_ worktree: Worktree) {
302328 pinnedWorktreeIDs.removeAll { $0 == worktree.id }
303329 pinnedWorktreeIDs.insert(worktree.id, at: 0)
···345371 id: UUID(),
346372 title: "Unable to remove worktree",
347373 message: error.localizedDescription
374374+ )
375375+ }
376376+ }
377377+378378+ func removeRepository(_ repository: Repository) async {
379379+ removeRepositoryError = nil
380380+ if removingRepositoryIDs.contains(repository.id) {
381381+ return
382382+ }
383383+ removingRepositoryIDs.insert(repository.id)
384384+ defer { removingRepositoryIDs.remove(repository.id) }
385385+ let selectionWasRemoved =
386386+ selectedWorktreeID.map { id in
387387+ repository.worktrees.contains(where: { $0.id == id })
388388+ } ?? false
389389+ var failures: [String] = []
390390+ for worktree in repository.worktrees {
391391+ do {
392392+ _ = try await gitClient.removeWorktree(
393393+ named: worktree.name,
394394+ in: repository.rootURL,
395395+ force: true
396396+ )
397397+ } catch {
398398+ failures.append(error.localizedDescription)
399399+ }
400400+ }
401401+ if failures.isEmpty {
402402+ let rootPaths = uniqueRootPaths(loadRootPaths())
403403+ let normalized = repository.rootURL.standardizedFileURL.path(percentEncoded: false)
404404+ let remaining = rootPaths.filter { $0 != normalized }
405405+ persistRootPaths(remaining)
406406+ }
407407+ let roots = uniqueRootPaths(loadRootPaths()).map { URL(fileURLWithPath: $0) }
408408+ let loaded = await loadRepositories(for: roots)
409409+ applyRepositories(loaded, animated: true)
410410+ if selectionWasRemoved {
411411+ selectedWorktreeID = firstAvailableWorktreeID(from: repositories)
412412+ }
413413+ if !failures.isEmpty {
414414+ let message = failures.joined(separator: "\n")
415415+ removeRepositoryError = RemoveRepositoryError(
416416+ id: UUID(),
417417+ title: "Unable to remove repository",
418418+ message: message
348419 )
349420 }
350421 }