Commit 9f246fb2a7

9f246fb2a773864c5cc0b773c5b5eef29814c4ae

parent: 0c8cbc1f07

Unsigned

cmc <hello@cleberg.net> · 2026-07-16 06:16 UTC

fix: deleted repositories linger until the cache expires

Deleting a repository left it on the list, and pulling to refresh did not shift
it. Two independent reasons, both cache-related.

deleteRepository never invalidated anything. Creation invalidates the
repositories and home prefixes; deletion was written without it, so the list and
Home kept serving a repository that no longer exists.

And forceRefresh only ever reached the build statuses — its own doc comment says
so — while the repository list itself was pinned to useCache: true. So a pull to
refresh re-served the same cache it already had. fetchPage already takes
useCache and falls through to an uncached fetch; it was simply never told.

Layout: unified · split

Hutch/Views/Repositories/RepositoryListViewModel.swift +4 −1
@@ -189,7 +189,10 @@ final class RepositoryListViewModel {
189 filteredResults = [] 189 filteredResults = []
190 } 190 }
191 } else { 191 } else {
192 let repositories = try await fetchAllRepositories(useCache: true) 192 // forceRefresh used to reach only the build statuses, so a pull to
193 // refresh re-served the cached list and a deleted repository stayed
194 // on screen.
195 let repositories = try await fetchAllRepositories(useCache: !forceRefresh)
193 updateSearchIndex(with: repositories) 196 updateSearchIndex(with: repositories)
194 filteredResults = repositories 197 filteredResults = repositories
195 } 198 }
Hutch/Views/Repositories/RepositorySettingsViewModel.swift +5
@@ -231,6 +231,11 @@ final class RepositorySettingsViewModel {
231 variables: ["id": repositoryId], 231 variables: ["id": repositoryId],
232 responseType: DeleteRepositoryResponse.self 232 responseType: DeleteRepositoryResponse.self
233 ) 233 )
234 // The list and Home are both served from cache, so without this the
235 // repository lingers on screen after it no longer exists. Creation
236 // already does this; deletion never did.
237 await client.invalidateCache(prefix: APICacheKeys.prefix(service.rawValue, "repositories"))
238 await client.invalidateCache(prefix: APICacheKeys.prefix("home"))
234 didDelete = true 239 didDelete = true
235 } catch { 240 } catch {
236 self.error = error.userFacingMessage 241 self.error = error.userFacingMessage