@@ -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 args = args. to_vec ( ) ;
88
92
if let Some ( ref tc_cargoflags) = ctx. toolchain . cargoflags {
89
93
args. extend ( tc_cargoflags. split ( ' ' ) ) ;
@@ -167,6 +171,9 @@ fn run_cargo<DB: WriteResults>(
167
171
. env ( "CARGO_INCREMENTAL" , "0" )
168
172
. env ( "RUST_BACKTRACE" , "full" )
169
173
. env ( rustflags_env, rustflags) ;
174
+ for ( var, data) in env {
175
+ command = command. env ( var, data) ;
176
+ }
170
177
171
178
if check_errors {
172
179
command = command. process_lines ( & mut detect_error) ;
@@ -197,7 +204,7 @@ fn run_cargo<DB: WriteResults>(
197
204
pub ( super ) fn run_test < DB : WriteResults > (
198
205
action : & str ,
199
206
ctx : & TaskCtx < DB > ,
200
- test_fn : fn ( & TaskCtx < DB > , & Build , & HashSet < PackageId > ) -> Fallible < TestResult > ,
207
+ test_fn : fn ( & TaskCtx < DB > , & Build , & [ Package ] ) -> Fallible < TestResult > ,
201
208
) -> Fallible < ( ) > {
202
209
if let Some ( res) = ctx
203
210
. db
@@ -239,8 +246,8 @@ pub(super) fn run_test<DB: WriteResults>(
239
246
}
240
247
241
248
detect_broken ( build. run ( |build| {
242
- let local_packages_id = get_local_packages ( build) ?;
243
- test_fn ( ctx, build, & local_packages_id )
249
+ let local_packages = get_local_packages ( build) ?;
250
+ test_fn ( ctx, build, & local_packages )
244
251
} ) )
245
252
} ,
246
253
) ?;
@@ -251,21 +258,23 @@ pub(super) fn run_test<DB: WriteResults>(
251
258
fn build < DB : WriteResults > (
252
259
ctx : & TaskCtx < DB > ,
253
260
build_env : & Build ,
254
- local_packages_id : & HashSet < PackageId > ,
261
+ local_packages : & [ Package ] ,
255
262
) -> Fallible < ( ) > {
256
263
run_cargo (
257
264
ctx,
258
265
build_env,
259
266
& [ "build" , "--frozen" , "--message-format=json" ] ,
260
267
true ,
261
- local_packages_id,
268
+ local_packages,
269
+ HashMap :: default ( ) ,
262
270
) ?;
263
271
run_cargo (
264
272
ctx,
265
273
build_env,
266
274
& [ "test" , "--frozen" , "--no-run" , "--message-format=json" ] ,
267
275
true ,
268
- local_packages_id,
276
+ local_packages,
277
+ HashMap :: default ( ) ,
269
278
) ?;
270
279
Ok ( ( ) )
271
280
}
@@ -276,14 +285,15 @@ fn test<DB: WriteResults>(ctx: &TaskCtx<DB>, build_env: &Build) -> Fallible<()>
276
285
build_env,
277
286
& [ "test" , "--frozen" ] ,
278
287
false ,
279
- & HashSet :: new ( ) ,
288
+ & [ ] ,
289
+ HashMap :: default ( ) ,
280
290
)
281
291
}
282
292
283
293
pub ( super ) fn test_build_and_test < DB : WriteResults > (
284
294
ctx : & TaskCtx < DB > ,
285
295
build_env : & Build ,
286
- local_packages_id : & HashSet < PackageId > ,
296
+ local_packages_id : & [ Package ] ,
287
297
) -> Fallible < TestResult > {
288
298
let build_r = build ( ctx, build_env, local_packages_id) ;
289
299
let test_r = if build_r. is_ok ( ) {
@@ -303,7 +313,7 @@ pub(super) fn test_build_and_test<DB: WriteResults>(
303
313
pub ( super ) fn test_build_only < DB : WriteResults > (
304
314
ctx : & TaskCtx < DB > ,
305
315
build_env : & Build ,
306
- local_packages_id : & HashSet < PackageId > ,
316
+ local_packages_id : & [ Package ] ,
307
317
) -> Fallible < TestResult > {
308
318
if let Err ( err) = build ( ctx, build_env, local_packages_id) {
309
319
Ok ( TestResult :: BuildFail ( failure_reason ( & err) ) )
@@ -315,7 +325,7 @@ pub(super) fn test_build_only<DB: WriteResults>(
315
325
pub ( super ) fn test_check_only < DB : WriteResults > (
316
326
ctx : & TaskCtx < DB > ,
317
327
build_env : & Build ,
318
- local_packages_id : & HashSet < PackageId > ,
328
+ local_packages_id : & [ Package ] ,
319
329
) -> Fallible < TestResult > {
320
330
if let Err ( err) = run_cargo (
321
331
ctx,
@@ -329,6 +339,7 @@ pub(super) fn test_check_only<DB: WriteResults>(
329
339
] ,
330
340
true ,
331
341
local_packages_id,
342
+ HashMap :: default ( ) ,
332
343
) {
333
344
Ok ( TestResult :: BuildFail ( failure_reason ( & err) ) )
334
345
} else {
@@ -339,7 +350,7 @@ pub(super) fn test_check_only<DB: WriteResults>(
339
350
pub ( super ) fn test_clippy_only < DB : WriteResults > (
340
351
ctx : & TaskCtx < DB > ,
341
352
build_env : & Build ,
342
- local_packages_id : & HashSet < PackageId > ,
353
+ local_packages : & [ Package ] ,
343
354
) -> Fallible < TestResult > {
344
355
if let Err ( err) = run_cargo (
345
356
ctx,
@@ -352,7 +363,8 @@ pub(super) fn test_clippy_only<DB: WriteResults>(
352
363
"--message-format=json" ,
353
364
] ,
354
365
true ,
355
- local_packages_id,
366
+ local_packages,
367
+ HashMap :: default ( ) ,
356
368
) {
357
369
Ok ( TestResult :: BuildFail ( failure_reason ( & err) ) )
358
370
} else {
@@ -363,29 +375,64 @@ pub(super) fn test_clippy_only<DB: WriteResults>(
363
375
pub ( super ) fn test_rustdoc < DB : WriteResults > (
364
376
ctx : & TaskCtx < DB > ,
365
377
build_env : & Build ,
366
- local_packages_id : & HashSet < PackageId > ,
378
+ local_packages : & [ Package ] ,
367
379
) -> Fallible < TestResult > {
368
- let res = run_cargo (
369
- ctx,
370
- build_env,
380
+ let run = |cargo_args, env| {
381
+ let res = run_cargo ( ctx, build_env, cargo_args, true , local_packages, env) ;
382
+
383
+ // Make sure to remove the built documentation
384
+ // There is no point in storing it after the build is done
385
+ remove_dir_all ( & build_env. host_target_dir ( ) . join ( "doc" ) ) ?;
386
+
387
+ res
388
+ } ;
389
+
390
+ // first, run a normal `cargo doc`
391
+ let res = run (
371
392
& [
372
393
"doc" ,
373
394
"--frozen" ,
374
395
"--no-deps" ,
375
396
"--document-private-items" ,
376
397
"--message-format=json" ,
377
398
] ,
378
- true ,
379
- local_packages_id,
399
+ HashMap :: default ( ) ,
380
400
) ;
401
+ if let Err ( err) = res {
402
+ return Ok ( TestResult :: BuildFail ( failure_reason ( & err) ) ) ;
403
+ }
381
404
382
- // Make sure to remove the built documentation
383
- // There is no point in storing it after the build is done
384
- remove_dir_all ( & build_env. host_target_dir ( ) . join ( "doc" ) ) ?;
405
+ // next, if this is a library, run it with docs.rs metadata applied.
406
+ if local_packages
407
+ . iter ( )
408
+ . any ( |p| p. targets . iter ( ) . any ( is_library) )
409
+ {
410
+ let src = build_env. host_source_dir ( ) ;
411
+ let metadata = DocsrsMetadata :: from_crate_root ( src) ?;
412
+ let cargo_args = metadata. cargo_args (
413
+ & [ "--frozen" . into ( ) , "--message-format=json" . into ( ) ] ,
414
+ & [ "--document-private-items" . into ( ) ] ,
415
+ ) ;
416
+ assert_eq ! ( cargo_args[ 0 ] , "rustdoc" ) ;
417
+ let cargo_args: Vec < _ > = cargo_args. iter ( ) . map ( |s| s. as_str ( ) ) . collect ( ) ;
418
+ let mut env = metadata. environment_variables ( ) ;
419
+ // docsrs-metadata requires a nightly environment, but crater sometimes runs tests on beta and
420
+ // stable.
421
+ env. insert ( "RUSTC_BOOTSTRAP" , "1" . to_string ( ) ) ;
385
422
386
- if let Err ( err) = res {
387
- Ok ( TestResult :: BuildFail ( failure_reason ( & err) ) )
388
- } else {
389
- Ok ( TestResult :: TestPass )
423
+ if let Err ( err) = run ( & cargo_args, env) {
424
+ return Ok ( TestResult :: BuildFail ( failure_reason ( & err) ) ) ;
425
+ }
390
426
}
427
+
428
+ Ok ( TestResult :: TestPass )
429
+ }
430
+
431
+ fn is_library ( target : & Target ) -> bool {
432
+ // Some examples and tests can be libraries (e.g. if they use `cdylib`).
433
+ target. crate_types . iter ( ) . any ( |ty| ty != "bin" )
434
+ && target
435
+ . kind
436
+ . iter ( )
437
+ . all ( |k| ![ "example" , "test" , "bench" ] . contains ( & k. as_str ( ) ) )
391
438
}
0 commit comments