@@ -69,6 +69,13 @@ struct TargetNotFoundDiagnostic: DiagnosticData {
69
69
70
70
private class ToolWorkspaceDelegate : WorkspaceDelegate {
71
71
72
+ /// The stream to use for reporting progress.
73
+ private let stdoutStream : OutputByteStream
74
+
75
+ init ( _ stdoutStream: OutputByteStream ) {
76
+ self . stdoutStream = stdoutStream
77
+ }
78
+
72
79
func packageGraphWillLoad(
73
80
currentGraph: PackageGraph ,
74
81
dependencies: AnySequence < ManagedDependency > ,
@@ -77,39 +84,52 @@ private class ToolWorkspaceDelegate: WorkspaceDelegate {
77
84
}
78
85
79
86
func fetchingWillBegin( repository: String ) {
80
- print ( " Fetching \( repository) " )
87
+ stdoutStream <<< " Fetching \( repository) "
88
+ stdoutStream <<< " \n "
89
+ stdoutStream. flush ( )
81
90
}
82
91
83
92
func fetchingDidFinish( repository: String , diagnostic: Diagnostic ? ) {
84
93
}
85
94
86
95
func repositoryWillUpdate( _ repository: String ) {
87
- print ( " Updating \( repository) " )
96
+ stdoutStream <<< " Updating \( repository) "
97
+ stdoutStream <<< " \n "
98
+ stdoutStream. flush ( )
88
99
}
89
100
90
101
func repositoryDidUpdate( _ repository: String ) {
91
102
}
92
103
93
104
func dependenciesUpToDate( ) {
94
- print ( " Everything is already up-to-date " )
105
+ stdoutStream <<< " Everything is already up-to-date "
106
+ stdoutStream <<< " \n "
107
+ stdoutStream. flush ( )
95
108
}
96
109
97
110
func cloning( repository: String ) {
98
- print ( " Cloning \( repository) " )
111
+ stdoutStream <<< " Cloning \( repository) "
112
+ stdoutStream <<< " \n "
113
+ stdoutStream. flush ( )
99
114
}
100
115
101
116
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 ( )
105
120
}
106
121
107
122
func removing( repository: String ) {
108
- print ( " Removing \( repository) " )
123
+ stdoutStream <<< " Removing \( repository) "
124
+ stdoutStream <<< " \n "
125
+ stdoutStream. flush ( )
109
126
}
110
127
111
128
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 ( )
113
133
}
114
134
115
135
func managedDependenciesDidUpdate( _ dependencies: AnySequence < ManagedDependency > ) {
@@ -165,6 +185,22 @@ final class BuildManifestRegenerationToken {
165
185
}
166
186
}
167
187
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
+
168
204
public class SwiftTool < Options: ToolOptions > {
169
205
/// The original working directory.
170
206
let originalWorkingDirectory : AbsolutePath
@@ -202,11 +238,19 @@ public class SwiftTool<Options: ToolOptions> {
202
238
let interruptHandler : InterruptHandler
203
239
204
240
/// The diagnostics engine.
205
- let diagnostics = DiagnosticsEngine ( handlers: [ SwiftTool . diagnosticsHandler] )
241
+ let diagnostics : DiagnosticsEngine = DiagnosticsEngine (
242
+ handlers: [ DiagnosticsEngineHandler . default. diagnosticsHandler] )
206
243
207
244
/// The execution status of the tool.
208
245
var executionStatus : ExecutionStatus = . success
209
246
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
+
210
254
/// Create an instance of this tool.
211
255
///
212
256
/// - parameter args: The command line arguments to be passed to this tool.
@@ -394,7 +438,7 @@ public class SwiftTool<Options: ToolOptions> {
394
438
if let workspace = _workspace {
395
439
return workspace
396
440
}
397
- let delegate = ToolWorkspaceDelegate ( )
441
+ let delegate = ToolWorkspaceDelegate ( self . stdoutStream )
398
442
let rootPackage = try getPackageRoot ( )
399
443
let provider = GitRepositoryProvider ( processSet: processSet)
400
444
let workspace = Workspace (
@@ -431,10 +475,6 @@ public class SwiftTool<Options: ToolOptions> {
431
475
SwiftTool . exit ( with: executionStatus)
432
476
}
433
477
434
- static func diagnosticsHandler( _ diagnostic: Diagnostic ) {
435
- print ( diagnostic: diagnostic)
436
- }
437
-
438
478
/// Exit the tool with the given execution status.
439
479
private static func exit( with status: ExecutionStatus ) -> Never {
440
480
switch status {
@@ -448,6 +488,13 @@ public class SwiftTool<Options: ToolOptions> {
448
488
fatalError ( " Must be implemented by subclasses " )
449
489
}
450
490
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
+
451
498
/// Resolve the dependencies.
452
499
func resolve( ) throws {
453
500
let workspace = try getActiveWorkspace ( )
@@ -601,11 +648,19 @@ public class SwiftTool<Options: ToolOptions> {
601
648
env [ " TMPDIR " ] = tempDir. asString
602
649
603
650
// 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 )
605
652
try process. launch ( )
606
653
try processSet. add ( process)
607
654
let result = try process. waitUntilExit ( )
608
655
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
+
609
664
guard result. exitStatus == . terminated( code: 0 ) else {
610
665
throw ProcessResult . Error. nonZeroExit ( result)
611
666
}
0 commit comments