@@ -5,12 +5,13 @@ use crate::results::{BrokenReason, EncodingType, FailureReason, TestResult, Writ
5
5
use crate :: runner:: tasks:: TaskCtx ;
6
6
use crate :: runner:: OverrideResult ;
7
7
use cargo_metadata:: diagnostic:: DiagnosticLevel ;
8
- use cargo_metadata:: { Message , Metadata , PackageId } ;
8
+ use cargo_metadata:: { Message , Metadata , Package , Target } ;
9
+ use docsrs_metadata:: Metadata as DocsrsMetadata ;
9
10
use failure:: Error ;
10
11
use remove_dir_all:: remove_dir_all;
11
12
use rustwide:: cmd:: { CommandError , ProcessLinesActions , SandboxBuilder } ;
12
13
use rustwide:: { Build , PrepareError } ;
13
- use std:: collections:: { BTreeSet , HashSet } ;
14
+ use std:: collections:: { BTreeSet , HashMap , HashSet } ;
14
15
use std:: convert:: TryFrom ;
15
16
16
17
fn failure_reason ( err : & Error ) -> FailureReason {
@@ -64,7 +65,7 @@ pub(super) fn detect_broken<T>(res: Result<T, Error>) -> Result<T, Error> {
64
65
}
65
66
}
66
67
67
- fn get_local_packages ( build_env : & Build ) -> Fallible < HashSet < PackageId > > {
68
+ fn get_local_packages ( build_env : & Build ) -> Fallible < Vec < Package > > {
68
69
Ok ( build_env
69
70
. cargo ( )
70
71
. args ( & [ "metadata" , "--no-deps" , "--format-version=1" ] )
@@ -73,17 +74,20 @@ fn get_local_packages(build_env: &Build) -> Fallible<HashSet<PackageId>> {
73
74
. stdout_lines ( )
74
75
. iter ( )
75
76
. filter_map ( |line| serde_json:: from_str :: < Metadata > ( line) . ok ( ) )
76
- . flat_map ( |metadata| metadata. packages . into_iter ( ) . map ( |pkg| pkg . id ) )
77
- . collect :: < HashSet < _ > > ( ) )
77
+ . flat_map ( |metadata| metadata. packages )
78
+ . collect ( ) )
78
79
}
79
80
80
81
fn run_cargo < DB : WriteResults > (
81
82
ctx : & TaskCtx < DB > ,
82
83
build_env : & Build ,
83
84
args : & [ & str ] ,
84
85
check_errors : bool ,
85
- local_packages_id : & HashSet < PackageId > ,
86
+ local_packages : & [ Package ] ,
87
+ env : HashMap < & ' static str , String > ,
86
88
) -> Fallible < ( ) > {
89
+ let local_packages_id: HashSet < _ > = local_packages. iter ( ) . map ( |p| & p. id ) . collect ( ) ;
90
+
87
91
let mut rustflags = format ! ( "--cap-lints={}" , ctx. experiment. cap_lints. to_str( ) ) ;
88
92
if let Some ( ref tc_rustflags) = ctx. toolchain . rustflags {
89
93
rustflags. push ( ' ' ) ;
@@ -151,6 +155,9 @@ fn run_cargo<DB: WriteResults>(
151
155
. env ( "CARGO_INCREMENTAL" , "0" )
152
156
. env ( "RUST_BACKTRACE" , "full" )
153
157
. env ( rustflags_env, rustflags) ;
158
+ for ( var, data) in env {
159
+ command = command. env ( var, data) ;
160
+ }
154
161
155
162
if check_errors {
156
163
command = command. process_lines ( & mut detect_error) ;
@@ -179,7 +186,7 @@ fn run_cargo<DB: WriteResults>(
179
186
pub ( super ) fn run_test < DB : WriteResults > (
180
187
action : & str ,
181
188
ctx : & TaskCtx < DB > ,
182
- test_fn : fn ( & TaskCtx < DB > , & Build , & HashSet < PackageId > ) -> Fallible < TestResult > ,
189
+ test_fn : fn ( & TaskCtx < DB > , & Build , & [ Package ] ) -> Fallible < TestResult > ,
183
190
) -> Fallible < ( ) > {
184
191
if let Some ( res) = ctx
185
192
. db
@@ -221,8 +228,8 @@ pub(super) fn run_test<DB: WriteResults>(
221
228
}
222
229
223
230
detect_broken ( build. run ( |build| {
224
- let local_packages_id = get_local_packages ( build) ?;
225
- test_fn ( ctx, build, & local_packages_id )
231
+ let local_packages = get_local_packages ( build) ?;
232
+ test_fn ( ctx, build, & local_packages )
226
233
} ) )
227
234
} ,
228
235
) ?;
@@ -233,21 +240,23 @@ pub(super) fn run_test<DB: WriteResults>(
233
240
fn build < DB : WriteResults > (
234
241
ctx : & TaskCtx < DB > ,
235
242
build_env : & Build ,
236
- local_packages_id : & HashSet < PackageId > ,
243
+ local_packages : & [ Package ] ,
237
244
) -> Fallible < ( ) > {
238
245
run_cargo (
239
246
ctx,
240
247
build_env,
241
248
& [ "build" , "--frozen" , "--message-format=json" ] ,
242
249
true ,
243
- local_packages_id,
250
+ local_packages,
251
+ HashMap :: default ( ) ,
244
252
) ?;
245
253
run_cargo (
246
254
ctx,
247
255
build_env,
248
256
& [ "test" , "--frozen" , "--no-run" , "--message-format=json" ] ,
249
257
true ,
250
- local_packages_id,
258
+ local_packages,
259
+ HashMap :: default ( ) ,
251
260
) ?;
252
261
Ok ( ( ) )
253
262
}
@@ -258,14 +267,15 @@ fn test<DB: WriteResults>(ctx: &TaskCtx<DB>, build_env: &Build) -> Fallible<()>
258
267
build_env,
259
268
& [ "test" , "--frozen" ] ,
260
269
false ,
261
- & HashSet :: new ( ) ,
270
+ & [ ] ,
271
+ HashMap :: default ( ) ,
262
272
)
263
273
}
264
274
265
275
pub ( super ) fn test_build_and_test < DB : WriteResults > (
266
276
ctx : & TaskCtx < DB > ,
267
277
build_env : & Build ,
268
- local_packages_id : & HashSet < PackageId > ,
278
+ local_packages_id : & [ Package ] ,
269
279
) -> Fallible < TestResult > {
270
280
let build_r = build ( ctx, build_env, local_packages_id) ;
271
281
let test_r = if build_r. is_ok ( ) {
@@ -285,7 +295,7 @@ pub(super) fn test_build_and_test<DB: WriteResults>(
285
295
pub ( super ) fn test_build_only < DB : WriteResults > (
286
296
ctx : & TaskCtx < DB > ,
287
297
build_env : & Build ,
288
- local_packages_id : & HashSet < PackageId > ,
298
+ local_packages_id : & [ Package ] ,
289
299
) -> Fallible < TestResult > {
290
300
if let Err ( err) = build ( ctx, build_env, local_packages_id) {
291
301
Ok ( TestResult :: BuildFail ( failure_reason ( & err) ) )
@@ -297,7 +307,7 @@ pub(super) fn test_build_only<DB: WriteResults>(
297
307
pub ( super ) fn test_check_only < DB : WriteResults > (
298
308
ctx : & TaskCtx < DB > ,
299
309
build_env : & Build ,
300
- local_packages_id : & HashSet < PackageId > ,
310
+ local_packages_id : & [ Package ] ,
301
311
) -> Fallible < TestResult > {
302
312
if let Err ( err) = run_cargo (
303
313
ctx,
@@ -311,6 +321,7 @@ pub(super) fn test_check_only<DB: WriteResults>(
311
321
] ,
312
322
true ,
313
323
local_packages_id,
324
+ HashMap :: default ( ) ,
314
325
) {
315
326
Ok ( TestResult :: BuildFail ( failure_reason ( & err) ) )
316
327
} else {
@@ -321,7 +332,7 @@ pub(super) fn test_check_only<DB: WriteResults>(
321
332
pub ( super ) fn test_clippy_only < DB : WriteResults > (
322
333
ctx : & TaskCtx < DB > ,
323
334
build_env : & Build ,
324
- local_packages_id : & HashSet < PackageId > ,
335
+ local_packages : & [ Package ] ,
325
336
) -> Fallible < TestResult > {
326
337
if let Err ( err) = run_cargo (
327
338
ctx,
@@ -334,7 +345,8 @@ pub(super) fn test_clippy_only<DB: WriteResults>(
334
345
"--message-format=json" ,
335
346
] ,
336
347
true ,
337
- local_packages_id,
348
+ local_packages,
349
+ HashMap :: default ( ) ,
338
350
) {
339
351
Ok ( TestResult :: BuildFail ( failure_reason ( & err) ) )
340
352
} else {
@@ -345,29 +357,64 @@ pub(super) fn test_clippy_only<DB: WriteResults>(
345
357
pub ( super ) fn test_rustdoc < DB : WriteResults > (
346
358
ctx : & TaskCtx < DB > ,
347
359
build_env : & Build ,
348
- local_packages_id : & HashSet < PackageId > ,
360
+ local_packages : & [ Package ] ,
349
361
) -> Fallible < TestResult > {
350
- let res = run_cargo (
351
- ctx,
352
- build_env,
362
+ let run = |cargo_args, env| {
363
+ let res = run_cargo ( ctx, build_env, cargo_args, true , local_packages, env) ;
364
+
365
+ // Make sure to remove the built documentation
366
+ // There is no point in storing it after the build is done
367
+ remove_dir_all ( & build_env. host_target_dir ( ) . join ( "doc" ) ) ?;
368
+
369
+ res
370
+ } ;
371
+
372
+ // first, run a normal `cargo doc`
373
+ let res = run (
353
374
& [
354
375
"doc" ,
355
376
"--frozen" ,
356
377
"--no-deps" ,
357
378
"--document-private-items" ,
358
379
"--message-format=json" ,
359
380
] ,
360
- true ,
361
- local_packages_id,
381
+ HashMap :: default ( ) ,
362
382
) ;
383
+ if let Err ( err) = res {
384
+ return Ok ( TestResult :: BuildFail ( failure_reason ( & err) ) ) ;
385
+ }
363
386
364
- // Make sure to remove the built documentation
365
- // There is no point in storing it after the build is done
366
- remove_dir_all ( & build_env. host_target_dir ( ) . join ( "doc" ) ) ?;
387
+ // next, if this is a library, run it with docs.rs metadata applied.
388
+ if local_packages
389
+ . iter ( )
390
+ . any ( |p| p. targets . iter ( ) . any ( is_library) )
391
+ {
392
+ let src = build_env. host_source_dir ( ) ;
393
+ let metadata = DocsrsMetadata :: from_crate_root ( src) ?;
394
+ let cargo_args = metadata. cargo_args (
395
+ & [ "--frozen" . into ( ) , "--message-format=json" . into ( ) ] ,
396
+ & [ "--document-private-items" . into ( ) ] ,
397
+ ) ;
398
+ assert_eq ! ( cargo_args[ 0 ] , "rustdoc" ) ;
399
+ let cargo_args: Vec < _ > = cargo_args. iter ( ) . map ( |s| s. as_str ( ) ) . collect ( ) ;
400
+ let mut env = metadata. environment_variables ( ) ;
401
+ // docsrs-metadata requires a nightly environment, but crater sometimes runs tests on beta and
402
+ // stable.
403
+ env. insert ( "RUSTC_BOOTSTRAP" , "1" . to_string ( ) ) ;
367
404
368
- if let Err ( err) = res {
369
- Ok ( TestResult :: BuildFail ( failure_reason ( & err) ) )
370
- } else {
371
- Ok ( TestResult :: TestPass )
405
+ if let Err ( err) = run ( & cargo_args, env) {
406
+ return Ok ( TestResult :: BuildFail ( failure_reason ( & err) ) ) ;
407
+ }
372
408
}
409
+
410
+ Ok ( TestResult :: TestPass )
411
+ }
412
+
413
+ fn is_library ( target : & Target ) -> bool {
414
+ // Some examples and tests can be libraries (e.g. if they use `cdylib`).
415
+ target. crate_types . iter ( ) . any ( |ty| ty != "bin" )
416
+ && target
417
+ . kind
418
+ . iter ( )
419
+ . all ( |k| ![ "example" , "test" , "bench" ] . contains ( & k. as_str ( ) ) )
373
420
}
0 commit comments