1
+ use crate :: crates:: Crate ;
1
2
use crate :: prelude:: * ;
3
+ use crate :: results:: DiagnosticCode ;
2
4
use crate :: results:: { BrokenReason , EncodingType , FailureReason , TestResult , WriteResults } ;
3
5
use crate :: runner:: tasks:: TaskCtx ;
4
6
use crate :: runner:: OverrideResult ;
7
+ use cargo_metadata:: diagnostic:: DiagnosticLevel ;
8
+ use cargo_metadata:: Message ;
5
9
use failure:: Error ;
6
10
use remove_dir_all:: remove_dir_all;
7
- use rustwide:: cmd:: { CommandError , SandboxBuilder } ;
11
+ use rustwide:: cmd:: { CommandError , ProcessLinesActions , SandboxBuilder } ;
8
12
use rustwide:: { Build , PrepareError } ;
13
+ use std:: collections:: BTreeSet ;
14
+ use std:: convert:: TryFrom ;
9
15
10
16
fn failure_reason ( err : & Error ) -> FailureReason {
11
17
for cause in err. iter_chain ( ) {
@@ -16,7 +22,7 @@ fn failure_reason(err: &Error) -> FailureReason {
16
22
} else if let Some ( & CommandError :: Timeout ( _) ) = cause. downcast_ctx ( ) {
17
23
return FailureReason :: Timeout ;
18
24
} else if let Some ( reason) = cause. downcast_ctx :: < FailureReason > ( ) {
19
- return * reason;
25
+ return reason. clone ( ) ;
20
26
}
21
27
}
22
28
@@ -73,31 +79,76 @@ fn run_cargo<DB: WriteResults>(
73
79
} ;
74
80
75
81
let mut did_ice = false ;
76
- let mut tracker = |line : & str | {
77
- did_ice |= line. contains ( "error: internal compiler error" ) ;
82
+ let mut error_codes = BTreeSet :: new ( ) ;
83
+ let mut deps = BTreeSet :: new ( ) ;
84
+
85
+ let mut detect_error = |line : & str , actions : & mut ProcessLinesActions | {
86
+ // Avoid trying to deserialize non JSON output
87
+ if line. starts_with ( '{' ) {
88
+ let message = serde_json:: from_str ( line) ;
89
+ if let Ok ( message) = message {
90
+ match message {
91
+ Message :: CompilerMessage ( compiler_message) => {
92
+ let inner_message = compiler_message. message ;
93
+ match (
94
+ inner_message. level ,
95
+ Crate :: try_from ( & compiler_message. package_id ) ,
96
+ ) {
97
+ // the only local crate in a well defined job is the crate currently being tested
98
+ ( DiagnosticLevel :: Error , Ok ( Crate :: Local ( _) ) ) => {
99
+ if let Some ( code) = inner_message. code {
100
+ error_codes. insert ( DiagnosticCode :: from ( code. code ) ) ;
101
+ }
102
+ }
103
+ ( DiagnosticLevel :: Ice , Ok ( Crate :: Local ( _) ) ) => did_ice = true ,
104
+ // If the error is in a crate that is not local then it's referred to a dependency
105
+ // of the current crate
106
+ ( DiagnosticLevel :: Error , Ok ( krate) ) => {
107
+ deps. insert ( krate) ;
108
+ }
109
+ ( DiagnosticLevel :: Ice , Ok ( krate) ) => {
110
+ deps. insert ( krate) ;
111
+ }
112
+
113
+ _ => ( ) ,
114
+ }
115
+
116
+ actions. replace_with_lines (
117
+ inner_message. rendered . unwrap_or_default ( ) . split ( '\n' ) ,
118
+ ) ;
119
+ }
120
+ _ => actions. remove_line ( ) ,
121
+ }
122
+ }
123
+ }
78
124
} ;
125
+
79
126
let mut command = build_env
80
127
. cargo ( )
81
128
. args ( args)
82
129
. env ( "CARGO_INCREMENTAL" , "0" )
83
130
. env ( "RUST_BACKTRACE" , "full" )
84
131
. env ( rustflags_env, rustflags)
85
- . process_lines ( & mut tracker) ;
132
+ . process_lines ( & mut detect_error) ;
133
+
86
134
if ctx. quiet {
87
135
command = command. no_output_timeout ( None ) ;
88
136
}
137
+
89
138
match command. run ( ) {
90
- Ok ( ( ) ) => { }
139
+ Ok ( ( ) ) => Ok ( ( ) ) ,
91
140
Err ( e) => {
92
141
if did_ice {
93
- return Err ( e. context ( FailureReason :: ICE ) . into ( ) ) ;
142
+ Err ( e. context ( FailureReason :: ICE ) . into ( ) )
143
+ } else if !deps. is_empty ( ) {
144
+ Err ( e. context ( FailureReason :: DependsOn ( deps) ) . into ( ) )
145
+ } else if !error_codes. is_empty ( ) {
146
+ Err ( e. context ( FailureReason :: CompilerError ( error_codes) ) . into ( ) )
94
147
} else {
95
- return Err ( e) ;
148
+ Err ( e)
96
149
}
97
150
}
98
151
}
99
-
100
- Ok ( ( ) )
101
152
}
102
153
103
154
pub ( super ) fn run_test < DB : WriteResults > (
@@ -152,13 +203,25 @@ pub(super) fn run_test<DB: WriteResults>(
152
203
}
153
204
154
205
fn build < DB : WriteResults > ( ctx : & TaskCtx < DB > , build_env : & Build ) -> Fallible < ( ) > {
155
- run_cargo ( ctx, build_env, & [ "build" , "--frozen" ] ) ?;
156
- run_cargo ( ctx, build_env, & [ "test" , "--frozen" , "--no-run" ] ) ?;
206
+ run_cargo (
207
+ ctx,
208
+ build_env,
209
+ & [ "build" , "--frozen" , "--message-format=json" ] ,
210
+ ) ?;
211
+ run_cargo (
212
+ ctx,
213
+ build_env,
214
+ & [ "test" , "--frozen" , "--no-run" , "--message-format=json" ] ,
215
+ ) ?;
157
216
Ok ( ( ) )
158
217
}
159
218
160
219
fn test < DB : WriteResults > ( ctx : & TaskCtx < DB > , build_env : & Build ) -> Fallible < ( ) > {
161
- run_cargo ( ctx, build_env, & [ "test" , "--frozen" ] )
220
+ run_cargo (
221
+ ctx,
222
+ build_env,
223
+ & [ "test" , "--frozen" , "--message-format=json" ] ,
224
+ )
162
225
}
163
226
164
227
pub ( super ) fn test_build_and_test < DB : WriteResults > (
0 commit comments