Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 23 additions & 8 deletions Sources/Basics/ProgressAnimation/NinjaProgressAnimation.swift
Original file line number Diff line number Diff line change
Expand Up @@ -18,14 +18,15 @@ extension ProgressAnimation {
@_spi(SwiftPMInternal)
public static func ninja(
stream: WritableByteStream,
verbose: Bool
verbose: Bool,
normalizeStep: Bool = true
) -> any ProgressAnimationProtocol {
Self.dynamic(
stream: stream,
verbose: verbose,
ttyTerminalAnimationFactory: { RedrawingNinjaProgressAnimation(terminal: $0) },
ttyTerminalAnimationFactory: { RedrawingNinjaProgressAnimation(terminal: $0, normalizeStep: normalizeStep) },
dumbTerminalAnimationFactory: { SingleLinePercentProgressAnimation(stream: stream, header: nil) },
defaultAnimationFactory: { MultiLineNinjaProgressAnimation(stream: stream) }
defaultAnimationFactory: { MultiLineNinjaProgressAnimation(stream: stream, normalizeStep: normalizeStep) }
)
}
}
Expand All @@ -34,17 +35,24 @@ extension ProgressAnimation {
final class RedrawingNinjaProgressAnimation: ProgressAnimationProtocol {
private let terminal: TerminalController
private var hasDisplayedProgress = false
private let normalizeStep: Bool

init(terminal: TerminalController) {
init(terminal: TerminalController, normalizeStep: Bool) {
self.terminal = terminal
self.normalizeStep = normalizeStep
}

func update(step: Int, total: Int, text: String) {
assert(step <= total)

terminal.clearLine()

let progressText = "[\(step)/\(total)] \(text)"
var progressText = ""
if step < 0 && normalizeStep {
let normalizedStep = max(0, step)
progressText = "[\(normalizedStep)/\(total)] \(text)"
} else {
progressText = "\(text)"
}
let width = terminal.width
if progressText.utf8.count > width {
let suffix = "…"
Expand Down Expand Up @@ -78,17 +86,24 @@ final class MultiLineNinjaProgressAnimation: ProgressAnimationProtocol {

private let stream: WritableByteStream
private var lastDisplayedText: String? = nil
private let normalizeStep: Bool

init(stream: WritableByteStream) {
init(stream: WritableByteStream, normalizeStep: Bool) {
self.stream = stream
self.normalizeStep = normalizeStep
}

func update(step: Int, total: Int, text: String) {
assert(step <= total)

guard text != lastDisplayedText else { return }

stream.send("[\(step)/\(total)] ").send(text)
if step < 0 && normalizeStep {
let normalizedStep = max(0, step)
stream.send("[\(normalizedStep)/\(total)] ")
}

stream.send(text)
stream.send("\n")
stream.flush()
lastDisplayedText = text
Expand Down
10 changes: 5 additions & 5 deletions Sources/SwiftBuildSupport/SwiftBuildSystemMessageHandler.swift
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,8 @@ public final class SwiftBuildSystemMessageHandler {
self.logLevel = logLevel
self.progressAnimation = ProgressAnimation.ninja(
stream: outputStream,
verbose: self.logLevel.isVerbose
verbose: self.logLevel.isVerbose,
normalizeStep: false
)
self.enableBacktraces = enableBacktraces
self.buildDelegate = buildDelegate
Expand Down Expand Up @@ -125,7 +126,7 @@ public final class SwiftBuildSystemMessageHandler {
if self.logLevel.isVerbose {
self.outputStream.send(started.description + "\n")
} else {
observabilityScope.emit(info: started)
observabilityScope.print(started, verbose: self.logLevel.isVerbose)
}
}

Expand Down Expand Up @@ -216,13 +217,13 @@ public final class SwiftBuildSystemMessageHandler {
}
}
case .didUpdateProgress(let progressInfo):
var step = Int(progressInfo.percentComplete)
if step < 0 { step = 0 }
let step = Int(progressInfo.percentComplete)
let message = if let targetName = progressInfo.targetName {
"\(targetName) \(progressInfo.message)"
} else {
"\(progressInfo.message)"
}
// TODO bp: some message suffixes seems to have its own stepping fraction.
progressAnimation.update(step: step, total: 100, text: message)
callback = { [weak self] buildSystem in
self?.buildDelegate?.buildSystem(buildSystem, didUpdateTaskProgress: message)
Expand Down Expand Up @@ -770,7 +771,6 @@ extension SwiftBuildMessage.LocationContext {
}
}


fileprivate extension SwiftBuild.SwiftBuildMessage.DiagnosticInfo.Location {
var userDescription: String? {
switch self {
Expand Down
3 changes: 1 addition & 2 deletions Tests/BuildTests/BuildSystemDelegateTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -45,13 +45,12 @@ struct BuildSystemDelegateTests {
"log didn't contain expected linker diagnostics. stderr: '\(stderr)')",
)
case .swiftbuild:
let searchPathRegex = try Regex("warning:(.*)Search path 'foobar' not found")
#expect(
stderr.contains("ld: warning: search path 'foobar' not found"),
"log didn't contain expected linker diagnostics. stderr: '\(stderr)",
)
#expect(
!stdout.contains(searchPathRegex),
!stdout.contains("ld: warning: search path 'foobar' not found"),
"log didn't contain expected linker diagnostics. stderr: '\(stderr)')",
)
case .xcode:
Expand Down
5 changes: 4 additions & 1 deletion Tests/CommandsTests/PackageCommandTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -4537,9 +4537,12 @@ struct PackageCommandTests {
// We expect a warning about `library.bar` but not about `library.foo`.
let libraryFooPath = RelativePath("Sources/MyLibrary/library.foo").pathString
#expect(!stderr.components(separatedBy: "\n").contains { $0.contains("warning: ") && $0.contains(libraryFooPath) })
if data.buildSystem == .native {
switch data.buildSystem {
case .native:
#expect(stderr.contains("found 1 file(s) which are unhandled"))
#expect(stderr.contains(RelativePath("Sources/MyLibrary/library.bar").pathString))
case .swiftbuild, .xcode:
return
}
}
}
Expand Down
Loading