mirror of
https://codeberg.org/secana/Forji.git
synced 2026-06-16 05:13:55 -07:00
Don't trap when two accounts share a sourceKey
Adding the same server and username twice yields two connections with the same sourceKey. PaginationState.rehydrate built its lookup with Dictionary(uniqueKeysWithValues:), which traps on a duplicate key, so every merged overview (notifications, issues/PRs, repositories) crashed on construction. Keep the first source instead, and add a regression test. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
992c628abd
commit
d96a953b6f
2 changed files with 33 additions and 1 deletions
|
|
@ -73,8 +73,11 @@ extension PaginationState where Item: Identifiable {
|
|||
/// Replace placeholder auth services using the given connection sources.
|
||||
/// Items whose sourceKey has no matching source are removed.
|
||||
func rehydrate<T>(from sources: [ConnectionSource]) where Item == TaggedItem<T> {
|
||||
// Two connected accounts with the same server+username share a sourceKey,
|
||||
// so keep the first rather than trapping on a duplicate key.
|
||||
let lookup = Dictionary(
|
||||
uniqueKeysWithValues: sources.map { ($0.sourceKey, $0.authService) },
|
||||
sources.map { ($0.sourceKey, $0.authService) },
|
||||
uniquingKeysWith: { first, _ in first },
|
||||
)
|
||||
items = items.compactMap { item in
|
||||
guard let auth = lookup[item.sourceKey] else { return nil }
|
||||
|
|
|
|||
|
|
@ -190,4 +190,33 @@ struct TaggedItemTests {
|
|||
|
||||
#expect(pagination.items.isEmpty)
|
||||
}
|
||||
|
||||
@MainActor
|
||||
@Test func rehydrateHandlesDuplicateSourceKeys() {
|
||||
// Two connected accounts with the same server+username produce duplicate
|
||||
// sourceKeys; rehydrate must not trap on the duplicate key.
|
||||
let liveAuth = AuthenticationService()
|
||||
let key = "https://a.com:u"
|
||||
let sources = [
|
||||
ConnectionSource(
|
||||
sourceKey: key, name: "A",
|
||||
client: ForgejoClient(serverURL: "https://a.com", username: "u", token: "t"),
|
||||
authService: liveAuth,
|
||||
),
|
||||
ConnectionSource(
|
||||
sourceKey: key, name: "A (duplicate)",
|
||||
client: ForgejoClient(serverURL: "https://a.com", username: "u", token: "t"),
|
||||
authService: AuthenticationService(),
|
||||
),
|
||||
]
|
||||
let pagination = PaginationState<TaggedItem<FIssue>>()
|
||||
pagination.items = [
|
||||
TaggedItem(item: makeIssue(id: 1), sourceKey: key, instanceName: "A", authService: makeAuth()),
|
||||
]
|
||||
|
||||
pagination.rehydrate(from: sources)
|
||||
|
||||
#expect(pagination.items.count == 1)
|
||||
#expect(pagination.items[0].authService === liveAuth) // first source wins
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue