Commit 174b677412
Verified · cmc
Layout: unified · split
gitbay/Builds/BuildDetailViewModel.swift +8 −2
| @@ -5,12 +5,15 @@ nonisolated struct BuildDetail: Sendable { | ||
| 5 | 5 | let build: Build |
| 6 | 6 | let log: String |
| 7 | 7 | let lines: BuildLog |
| 8 | /// Fetched with `--tail`. | |
| 9 | let tail: Bool | |
| 8 | 10 | |
| 9 | 11 | /// `tail` is a log's last lines only, which may start inside a step |
| 10 | 12 | /// and cut its marker off, so it is drawn as one block. |
| 11 | 13 | init(build: Build, log: String, tail: Bool = false) { |
| 12 | 14 | self.build = build |
| 13 | 15 | self.log = log |
| 16 | self.tail = tail | |
| 14 | 17 | var split = build |
| 15 | 18 | if tail { |
| 16 | 19 | split.steps = nil |
| @@ -49,7 +52,10 @@ final class BuildDetailViewModel { | ||
| 49 | 52 | |
| 50 | 53 | func load() async { |
| 51 | 54 | do { |
| 52 | state = .loaded(try await fetch()) | |
| 55 | let detail = try await fetch() | |
| 56 | // A fetch from before the mode changed is not this screen's. | |
| 57 | guard detail.tail == tail else { return } | |
| 58 | state = .loaded(detail) | |
| 53 | 59 | } catch { |
| 54 | 60 | state = .from(error) |
| 55 | 61 | } |
| @@ -83,7 +89,7 @@ final class BuildDetailViewModel { | ||
| 83 | 89 | func poll() async { |
| 84 | 90 | while let build = state.value?.build, Self.isLive(status: build.status) { |
| 85 | 91 | guard (try? await Task.sleep(for: pollInterval)) != nil else { return } |
| 86 | if let detail = try? await fetch() { | |
| 92 | if let detail = try? await fetch(), detail.tail == tail { | |
| 87 | 93 | state = .loaded(detail) |
| 88 | 94 | } |
| 89 | 95 | } |
gitbayTests/BuildLogTests.swift +11
| @@ -248,4 +248,15 @@ struct BuildLogTailTests { | ||
| 248 | 248 | #expect(stub.seen.last { $0.url.absoluteString.contains("argv=log") }?.url.query()?.contains("tail") == false) |
| 249 | 249 | #expect(model.state.value?.lines.stepped == true) |
| 250 | 250 | } |
| 251 | ||
| 252 | @Test func aFetchFromTheOtherModeIsNotShown() async throws { | |
| 253 | let (client, stub) = try makeClient() | |
| 254 | stub.enqueue(.init(status: 200, json: buildShowJSON, match: "argv=show")) | |
| 255 | stub.enqueue(.init(status: 200, json: logEnvelope(failedLog), match: "argv=log")) | |
| 256 | let model = BuildDetailViewModel(client: client, repoPath: "krz/gitbay", number: 1) | |
| 257 | await model.load() | |
| 258 | // The detail records the mode it was fetched in. | |
| 259 | #expect(model.state.value?.tail == false) | |
| 260 | #expect(BuildDetail(build: try #require(model.state.value).build, log: "x\n", tail: true).tail) | |
| 261 | } | |
| 251 | 262 | } |