Skip to content

Commit fca18e0

Browse files
committed
plugin: handle chunks of output correctly
1 parent b0a23d0 commit fca18e0

File tree

1 file changed

+49
-7
lines changed

1 file changed

+49
-7
lines changed

Plugins/ContainerImageBuilder/main.swift

Lines changed: 49 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -99,16 +99,48 @@ extension PluginError: CustomStringConvertible {
9999

100100
await withThrowingTaskGroup(of: Void.self) { group in
101101
group.addTask {
102+
enum LoggingState {
103+
// Normal output is logged at 'progress' level.
104+
case progress
105+
106+
// If an error is detected, all output from that point onwards is logged at 'error' level, which is always printed.
107+
// Errors are reported even without the --verbose flag and cause the build to return a nonzero exit code.
108+
case error
109+
110+
func log(_ msg: String) {
111+
let trimmed = msg.trimmingCharacters(in: .newlines)
112+
switch self {
113+
case .progress: Diagnostics.progress(trimmed)
114+
case .error: Diagnostics.error(trimmed)
115+
}
116+
}
117+
}
118+
119+
var buf = ""
120+
var logger = LoggingState.progress
121+
102122
for try await line in err.lines {
103-
let errorLabel = "Error: " // SwiftArgumentParser adds this prefix to all errors which bubble up
104-
let trimmed = line.trimmingCharacters(in: .whitespacesAndNewlines)
123+
buf.append(line)
105124

106-
if trimmed.starts(with: errorLabel) {
107-
// Errors are reported even without the --verbose flag and cause the build to fail.
108-
Diagnostics.error(String(trimmed.dropFirst(errorLabel.count)))
109-
} else {
110-
Diagnostics.progress(trimmed)
125+
guard let (before, after) = buf.splitOn(first: "\n") else {
126+
continue
127+
}
128+
129+
var msg = before
130+
buf = String(after)
131+
132+
let errorLabel = "Error: " // SwiftArgumentParser adds this prefix to all errors which bubble up
133+
if msg.starts(with: errorLabel) {
134+
logger = .error
135+
msg.trimPrefix(errorLabel)
111136
}
137+
138+
logger.log(String(msg))
139+
}
140+
141+
// Print any leftover output in the buffer, in case the child exited without sending a final newline.
142+
if !buf.isEmpty {
143+
logger.log(buf)
112144
}
113145
}
114146

@@ -118,3 +150,13 @@ extension PluginError: CustomStringConvertible {
118150
}
119151
}
120152
}
153+
154+
extension Collection where Element: Equatable {
155+
func splitOn(first element: Element) -> (before: SubSequence, after: SubSequence)? {
156+
guard let idx = self.firstIndex(of: element) else {
157+
return nil
158+
}
159+
160+
return (self[..<idx], self[idx...].dropFirst())
161+
}
162+
}

0 commit comments

Comments
 (0)