Commit 224142832e
Verified · cmc
Layout: unified · split
gitbay/Push/PushTarget.swift +7 −1
| @@ -15,8 +15,14 @@ nonisolated struct PushTarget: Equatable, Sendable { | |||
| 15 | // comparing raw URLs, which a server's unnormalised config can | 15 | // comparing raw URLs, which a server's unnormalised config can |
| 16 | // make unequal even when they name the same instance. | 16 | // make unequal even when they name the same instance. |
| 17 | guard let instance = try? GitbayInstance(url: payload.instance.absoluteString) else { return nil } | 17 | guard let instance = try? GitbayInstance(url: payload.instance.absoluteString) else { return nil } |
| 18 | // Both sides, not just the payload's: an account stored before | ||
| 19 | // the constructor folded the default port still holds an | ||
| 20 | // explicit ":443". Normalising is for the comparison only — | ||
| 21 | // rewriting what is stored would change `Account.id` and orphan | ||
| 22 | // the Keychain token it keys. | ||
| 18 | let match = accounts.first { | 23 | let match = accounts.first { |
| 19 | $0.username == payload.user && $0.instance.baseURL == instance.baseURL | 24 | $0.username == payload.user |
| 25 | && (try? GitbayInstance(url: $0.instance.baseURL.absoluteString))?.baseURL == instance.baseURL | ||
| 20 | } | 26 | } |
| 21 | guard let match else { return nil } | 27 | guard let match else { return nil } |
| 22 | self.accountID = match.id | 28 | self.accountID = match.id |
gitbayTests/PushTargetTests.swift +16
| @@ -65,3 +65,19 @@ private func payload(_ instance: String, _ user: String, _ path: String) throws | |||
| 65 | accounts: accounts)) | 65 | accounts: accounts)) |
| 66 | #expect(target.accountID == accounts[0].id) | 66 | #expect(target.accountID == accounts[0].id) |
| 67 | } | 67 | } |
| 68 | |||
| 69 | // The other side of the same mismatch: an account stored before the | ||
| 70 | // constructor folded the default port keeps ":443" in its baseURL, so | ||
| 71 | // decoding is the only way to build one. Its id keeps the port — | ||
| 72 | // rewriting that would orphan the Keychain token keyed by it. | ||
| 73 | @Test func targetMatchesAnAccountStoredWithAnExplicitDefaultPort() throws { | ||
| 74 | let legacy = try JSONDecoder().decode( | ||
| 75 | GitbayInstance.self, from: Data(#"{"baseURL":"https://gitbay.org:443"}"#.utf8)) | ||
| 76 | let accounts = [Account(instance: legacy, username: "cmc")] | ||
| 77 | #expect(accounts[0].id.contains(":443")) | ||
| 78 | |||
| 79 | let target = try #require(PushTarget( | ||
| 80 | payload: try payload("https://gitbay.org", "cmc", "a/b/issues/1"), | ||
| 81 | accounts: accounts)) | ||
| 82 | #expect(target.accountID == accounts[0].id) | ||
| 83 | } | ||