mirror of
https://github.com/Homebrew/BrewUI.git
synced 2026-10-02 00:24:33 +08:00
`BrewCommandCenter` reported `.idle` the moment `brew` exited, but "done" to the UI means "the installed inventory reflects it". Every surface bridged that gap with its own latch, so each new way the world could fail to catch up needed its own release channel. Two bugs fell through: a batch `brew upgrade a b` that failed overall never refreshed the packages it did upgrade, leaving them marked outdated; and a refresh that itself failed released nothing, so Installed rows could spin "Uninstalling..." indefinitely and Discover's install chrome did the same. `BrewOperationPhase` gains `.reconciling(kind)`, so a mutating operation runs running -> reconciling -> idle | failed. `SerialBrewCommandCenter` takes a `BrewOperationReconciling` at construction and awaits it before publishing the terminal phase; the installed repository is that reconciler. No surface now sees a finished operation while the inventory still describes the world as it was, busy chrome becomes a pure function of the phase, and every latch is deleted. Read-only work settles directly; a failed command reconciles too. Overlapping fetches chain rather than race, and the phase observer seeds the newly selected subject so the Installed detail pane, which reuses one view model, cannot keep the previous package's chrome. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
16 lines
422 B
Swift
16 lines
422 B
Swift
//
|
|
// NoopBrewOperationReconciler.swift
|
|
// BrewServicesTestSupport
|
|
//
|
|
|
|
import BrewCore
|
|
import Foundation
|
|
|
|
/// Reconciler for tests whose subject is not the settling window. Production always reconciles against
|
|
/// the installed inventory, so ``SerialBrewCommandCenter`` requires one.
|
|
public final class NoopBrewOperationReconciler: BrewOperationReconciling {
|
|
public init() {}
|
|
|
|
public func reconcile() async {}
|
|
}
|