@@ -69,6 +69,13 @@ struct TargetNotFoundDiagnostic: DiagnosticData {
6969
7070private class ToolWorkspaceDelegate : WorkspaceDelegate {
7171
72+ /// The stream to use for reporting progress.
73+ private let stdoutStream : OutputByteStream
74+
75+ init ( _ stdoutStream: OutputByteStream ) {
76+ self . stdoutStream = stdoutStream
77+ }
78+
7279 func packageGraphWillLoad(
7380 currentGraph: PackageGraph ,
7481 dependencies: AnySequence < ManagedDependency > ,
@@ -77,39 +84,52 @@ private class ToolWorkspaceDelegate: WorkspaceDelegate {
7784 }
7885
7986 func fetchingWillBegin( repository: String ) {
80- print ( " Fetching \( repository) " )
87+ stdoutStream <<< " Fetching \( repository) "
88+ stdoutStream <<< " \n "
89+ stdoutStream. flush ( )
8190 }
8291
8392 func fetchingDidFinish( repository: String , diagnostic: Diagnostic ? ) {
8493 }
8594
8695 func repositoryWillUpdate( _ repository: String ) {
87- print ( " Updating \( repository) " )
96+ stdoutStream <<< " Updating \( repository) "
97+ stdoutStream <<< " \n "
98+ stdoutStream. flush ( )
8899 }
89100
90101 func repositoryDidUpdate( _ repository: String ) {
91102 }
92103
93104 func dependenciesUpToDate( ) {
94- print ( " Everything is already up-to-date " )
105+ stdoutStream <<< " Everything is already up-to-date "
106+ stdoutStream <<< " \n "
107+ stdoutStream. flush ( )
95108 }
96109
97110 func cloning( repository: String ) {
98- print ( " Cloning \( repository) " )
111+ stdoutStream <<< " Cloning \( repository) "
112+ stdoutStream <<< " \n "
113+ stdoutStream. flush ( )
99114 }
100115
101116 func checkingOut( repository: String , atReference reference: String , to path: AbsolutePath ) {
102- // FIXME: This is temporary output similar to old one, we will need to figure
103- // out better reporting text.
104- print ( " Resolving \( repository ) at \( reference ) " )
117+ stdoutStream <<< " Resolving \( repository ) at \( reference ) "
118+ stdoutStream <<< " \n "
119+ stdoutStream . flush ( )
105120 }
106121
107122 func removing( repository: String ) {
108- print ( " Removing \( repository) " )
123+ stdoutStream <<< " Removing \( repository) "
124+ stdoutStream <<< " \n "
125+ stdoutStream. flush ( )
109126 }
110127
111128 func warning( message: String ) {
112- print ( " warning: " + message)
129+ // FIXME: We should emit warnings through the diagnostic engine.
130+ stdoutStream <<< " warning: " <<< message
131+ stdoutStream <<< " \n "
132+ stdoutStream. flush ( )
113133 }
114134
115135 func managedDependenciesDidUpdate( _ dependencies: AnySequence < ManagedDependency > ) {
@@ -165,6 +185,22 @@ final class BuildManifestRegenerationToken {
165185 }
166186}
167187
188+ /// Handler for the main DiagnosticsEngine used by the SwiftTool class.
189+ private final class DiagnosticsEngineHandler {
190+
191+ /// The standard output stream.
192+ var stdoutStream = Basic . stdoutStream
193+
194+ /// The default instance.
195+ static let `default` = DiagnosticsEngineHandler ( )
196+
197+ private init ( ) { }
198+
199+ func diagnosticsHandler( _ diagnostic: Diagnostic ) {
200+ print ( diagnostic: diagnostic, stdoutStream: stderrStream)
201+ }
202+ }
203+
168204public class SwiftTool < Options: ToolOptions > {
169205 /// The original working directory.
170206 let originalWorkingDirectory : AbsolutePath
@@ -202,11 +238,19 @@ public class SwiftTool<Options: ToolOptions> {
202238 let interruptHandler : InterruptHandler
203239
204240 /// The diagnostics engine.
205- let diagnostics = DiagnosticsEngine ( handlers: [ SwiftTool . diagnosticsHandler] )
241+ let diagnostics : DiagnosticsEngine = DiagnosticsEngine (
242+ handlers: [ DiagnosticsEngineHandler . default. diagnosticsHandler] )
206243
207244 /// The execution status of the tool.
208245 var executionStatus : ExecutionStatus = . success
209246
247+ /// The stream to print standard output on.
248+ fileprivate var stdoutStream : OutputByteStream = Basic . stdoutStream
249+
250+ /// If true, Redirects the stdout stream to stderr when invoking
251+ /// `swift-build-tool`.
252+ private var shouldRedirectStdoutToStderr = false
253+
210254 /// Create an instance of this tool.
211255 ///
212256 /// - parameter args: The command line arguments to be passed to this tool.
@@ -394,7 +438,7 @@ public class SwiftTool<Options: ToolOptions> {
394438 if let workspace = _workspace {
395439 return workspace
396440 }
397- let delegate = ToolWorkspaceDelegate ( )
441+ let delegate = ToolWorkspaceDelegate ( self . stdoutStream )
398442 let rootPackage = try getPackageRoot ( )
399443 let provider = GitRepositoryProvider ( processSet: processSet)
400444 let workspace = Workspace (
@@ -431,10 +475,6 @@ public class SwiftTool<Options: ToolOptions> {
431475 SwiftTool . exit ( with: executionStatus)
432476 }
433477
434- static func diagnosticsHandler( _ diagnostic: Diagnostic ) {
435- print ( diagnostic: diagnostic)
436- }
437-
438478 /// Exit the tool with the given execution status.
439479 private static func exit( with status: ExecutionStatus ) -> Never {
440480 switch status {
@@ -448,6 +488,13 @@ public class SwiftTool<Options: ToolOptions> {
448488 fatalError ( " Must be implemented by subclasses " )
449489 }
450490
491+ /// Start redirecting the standard output stream to the standard error stream.
492+ func redirectStdoutToStderr( ) {
493+ self . shouldRedirectStdoutToStderr = true
494+ self . stdoutStream = Basic . stderrStream
495+ DiagnosticsEngineHandler . default. stdoutStream = Basic . stdoutStream
496+ }
497+
451498 /// Resolve the dependencies.
452499 func resolve( ) throws {
453500 let workspace = try getActiveWorkspace ( )
@@ -601,11 +648,19 @@ public class SwiftTool<Options: ToolOptions> {
601648 env [ " TMPDIR " ] = tempDir. asString
602649
603650 // Run llbuild and print output on standard streams.
604- let process = Process ( arguments: args, environment: env, redirectOutput: false )
651+ let process = Process ( arguments: args, environment: env, redirectOutput: shouldRedirectStdoutToStderr )
605652 try process. launch ( )
606653 try processSet. add ( process)
607654 let result = try process. waitUntilExit ( )
608655
656+ // Emit the output to the selected stream if we need to redirect the
657+ // stream.
658+ if shouldRedirectStdoutToStderr {
659+ self . stdoutStream <<< ( try result. utf8stderrOutput ( ) )
660+ self . stdoutStream <<< ( try result. utf8Output ( ) )
661+ self . stdoutStream. flush ( )
662+ }
663+
609664 guard result. exitStatus == . terminated( code: 0 ) else {
610665 throw ProcessResult . Error. nonZeroExit ( result)
611666 }
0 commit comments