1
+ use crate :: files:: config:: get_config;
1
2
use crate :: packages:: Package ;
2
3
use log:: { debug, error, info, warn} ;
3
4
use std:: io:: { stdin, BufRead , BufReader , IsTerminal , Read , Write } ;
4
5
use std:: path:: Path ;
5
6
use std:: process:: { Command , Stdio } ;
7
+ use std:: thread;
6
8
7
9
pub fn run ( package : & Package , binary : Option < String > , params : & Vec < String > ) -> bool {
8
10
let interactive = !stdin ( ) . is_terminal ( ) ;
@@ -19,10 +21,10 @@ pub fn run(package: &Package, binary: Option<String>, params: &Vec<String>) -> b
19
21
args. push ( "-i" . to_string ( ) ) ;
20
22
}
21
23
22
- add_volumes ( & package, & mut args) ;
23
- add_current_directory ( & package, & mut args) ;
24
- add_environment_variables ( & package, & mut args) ;
25
- add_binary_entrypoint ( & package, & binary, & mut args) ;
24
+ add_volumes ( package, & mut args) ;
25
+ add_current_directory ( package, & mut args) ;
26
+ add_environment_variables ( package, & mut args) ;
27
+ add_binary_entrypoint ( package, & binary, & mut args) ;
26
28
27
29
args. push ( format ! (
28
30
"{}:{}" ,
@@ -77,13 +79,30 @@ fn add_binary_entrypoint(package: &Package, binary: &Option<String>, args: &mut
77
79
}
78
80
}
79
81
82
+ fn get_stdio ( config : & crate :: files:: config:: Root ) -> ( Stdio , Stdio ) {
83
+ let stdout = if config. experimental . capture_stdout {
84
+ Stdio :: piped ( )
85
+ } else {
86
+ Stdio :: inherit ( )
87
+ } ;
88
+ let stderr = if config. experimental . capture_stderr {
89
+ Stdio :: piped ( )
90
+ } else {
91
+ Stdio :: inherit ( )
92
+ } ;
93
+ ( stdout, stderr)
94
+ }
95
+
80
96
fn run_command_with_args ( command : & str , args : & [ String ] , stdin_buffer : Option < Vec < u8 > > ) -> bool {
81
97
debug ! ( "Running command: {} {:?}" , command, args) ;
82
98
99
+ let config = get_config ( ) . unwrap_or_default ( ) ;
100
+ let ( stdout, stderr) = get_stdio ( & config) ;
101
+
83
102
let mut child = Command :: new ( command)
84
103
. args ( args)
85
- . stdout ( Stdio :: piped ( ) )
86
- . stderr ( Stdio :: piped ( ) )
104
+ . stdout ( stdout )
105
+ . stderr ( stderr )
87
106
. stdin ( Stdio :: piped ( ) )
88
107
. spawn ( )
89
108
. expect ( "Failed to spawn command" ) ;
@@ -96,39 +115,52 @@ fn run_command_with_args(command: &str, args: &[String], stdin_buffer: Option<Ve
96
115
}
97
116
98
117
let stdout_thread = spawn_log_thread (
99
- BufReader :: new ( child. stdout . take ( ) . expect ( "Failed to open stdout" ) ) ,
118
+ child. stdout . take ( ) ,
100
119
|line| info ! ( "{}" , line) ,
120
+ config. experimental . capture_stdout ,
101
121
) ;
102
122
let stderr_thread = spawn_log_thread (
103
- BufReader :: new ( child. stderr . take ( ) . expect ( "Failed to open stderr" ) ) ,
123
+ child. stderr . take ( ) ,
104
124
|line| error ! ( "{}" , line) ,
125
+ config. experimental . capture_stderr ,
105
126
) ;
106
127
107
- let status = child. wait ( ) ;
108
- let _ = stdout_thread. join ( ) ;
109
- let _ = stderr_thread. join ( ) ;
128
+ let status = child. wait ( ) . expect ( "Failed to wait on child process" ) ;
110
129
111
- match status {
112
- Ok ( status) => status. success ( ) ,
113
- Err ( e) => {
114
- error ! ( "Command failed to complete: {}" , e) ;
115
- false
116
- }
130
+ if let Some ( thread) = stdout_thread {
131
+ let _ = thread. join ( ) ;
117
132
}
133
+
134
+ if let Some ( thread) = stderr_thread {
135
+ let _ = thread. join ( ) ;
136
+ }
137
+
138
+ status. success ( )
118
139
}
119
140
120
- fn spawn_log_thread < R : BufRead + Send + ' static > (
121
- reader : R ,
141
+ fn spawn_log_thread < R : Read + Send + ' static > (
142
+ reader : Option < R > ,
122
143
log_fn : impl Fn ( & str ) + Send + ' static ,
123
- ) -> std:: thread:: JoinHandle < ( ) > {
124
- std:: thread:: spawn ( move || {
125
- for line in reader. lines ( ) {
144
+ capture : bool ,
145
+ ) -> Option < thread:: JoinHandle < ( ) > > {
146
+ if !capture {
147
+ return None ;
148
+ }
149
+ let reader = reader. expect ( "Failed to open reader" ) ;
150
+ Some ( thread:: spawn ( move || {
151
+ let reader = BufReader :: new ( reader) ;
152
+ for line in reader. split ( b'\n' ) {
126
153
match line {
127
- Ok ( line) => log_fn ( & line) ,
154
+ Ok ( line) => match std:: str:: from_utf8 ( & line) {
155
+ Ok ( line) => log_fn ( line) ,
156
+ Err ( _) => error ! (
157
+ "Failed to read line from output: stream did not contain valid UTF-8"
158
+ ) ,
159
+ } ,
128
160
Err ( e) => error ! ( "Failed to read line from output: {}" , e) ,
129
161
}
130
162
}
131
- } )
163
+ } ) )
132
164
}
133
165
134
166
pub fn pull ( package : & Package ) -> bool {
0 commit comments