@@ -5,12 +5,13 @@ use crate::results::{BrokenReason, EncodingType, FailureReason, TestResult, Writ
55use crate :: runner:: tasks:: TaskCtx ;
66use crate :: runner:: OverrideResult ;
77use 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 ;
910use failure:: Error ;
1011use remove_dir_all:: remove_dir_all;
1112use rustwide:: cmd:: { CommandError , ProcessLinesActions , SandboxBuilder } ;
1213use rustwide:: { Build , PrepareError } ;
13- use std:: collections:: { BTreeSet , HashSet } ;
14+ use std:: collections:: { BTreeSet , HashMap , HashSet } ;
1415use std:: convert:: TryFrom ;
1516
1617fn failure_reason ( err : & Error ) -> FailureReason {
@@ -64,7 +65,7 @@ pub(super) fn detect_broken<T>(res: Result<T, Error>) -> Result<T, Error> {
6465 }
6566}
6667
67- fn get_local_packages ( build_env : & Build ) -> Fallible < HashSet < PackageId > > {
68+ fn get_local_packages ( build_env : & Build ) -> Fallible < Vec < Package > > {
6869 Ok ( build_env
6970 . cargo ( )
7071 . args ( & [ "metadata" , "--no-deps" , "--format-version=1" ] )
@@ -73,17 +74,20 @@ fn get_local_packages(build_env: &Build) -> Fallible<HashSet<PackageId>> {
7374 . stdout_lines ( )
7475 . iter ( )
7576 . 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 ( ) )
7879}
7980
8081fn run_cargo < DB : WriteResults > (
8182 ctx : & TaskCtx < DB > ,
8283 build_env : & Build ,
8384 args : & [ & str ] ,
8485 check_errors : bool ,
85- local_packages_id : & HashSet < PackageId > ,
86+ local_packages : & [ Package ] ,
87+ env : HashMap < & ' static str , String > ,
8688) -> Fallible < ( ) > {
89+ let local_packages_id: HashSet < _ > = local_packages. iter ( ) . map ( |p| & p. id ) . collect ( ) ;
90+
8791 let mut args = args. to_vec ( ) ;
8892 if let Some ( ref tc_cargoflags) = ctx. toolchain . cargoflags {
8993 args. extend ( tc_cargoflags. split ( ' ' ) ) ;
@@ -167,6 +171,9 @@ fn run_cargo<DB: WriteResults>(
167171 . env ( "CARGO_INCREMENTAL" , "0" )
168172 . env ( "RUST_BACKTRACE" , "full" )
169173 . env ( rustflags_env, rustflags) ;
174+ for ( var, data) in env {
175+ command = command. env ( var, data) ;
176+ }
170177
171178 if check_errors {
172179 command = command. process_lines ( & mut detect_error) ;
@@ -197,7 +204,7 @@ fn run_cargo<DB: WriteResults>(
197204pub ( super ) fn run_test < DB : WriteResults > (
198205 action : & str ,
199206 ctx : & TaskCtx < DB > ,
200- test_fn : fn ( & TaskCtx < DB > , & Build , & HashSet < PackageId > ) -> Fallible < TestResult > ,
207+ test_fn : fn ( & TaskCtx < DB > , & Build , & [ Package ] ) -> Fallible < TestResult > ,
201208) -> Fallible < ( ) > {
202209 if let Some ( res) = ctx
203210 . db
@@ -239,8 +246,8 @@ pub(super) fn run_test<DB: WriteResults>(
239246 }
240247
241248 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 )
244251 } ) )
245252 } ,
246253 ) ?;
@@ -251,21 +258,23 @@ pub(super) fn run_test<DB: WriteResults>(
251258fn build < DB : WriteResults > (
252259 ctx : & TaskCtx < DB > ,
253260 build_env : & Build ,
254- local_packages_id : & HashSet < PackageId > ,
261+ local_packages : & [ Package ] ,
255262) -> Fallible < ( ) > {
256263 run_cargo (
257264 ctx,
258265 build_env,
259266 & [ "build" , "--frozen" , "--message-format=json" ] ,
260267 true ,
261- local_packages_id,
268+ local_packages,
269+ HashMap :: default ( ) ,
262270 ) ?;
263271 run_cargo (
264272 ctx,
265273 build_env,
266274 & [ "test" , "--frozen" , "--no-run" , "--message-format=json" ] ,
267275 true ,
268- local_packages_id,
276+ local_packages,
277+ HashMap :: default ( ) ,
269278 ) ?;
270279 Ok ( ( ) )
271280}
@@ -276,14 +285,15 @@ fn test<DB: WriteResults>(ctx: &TaskCtx<DB>, build_env: &Build) -> Fallible<()>
276285 build_env,
277286 & [ "test" , "--frozen" ] ,
278287 false ,
279- & HashSet :: new ( ) ,
288+ & [ ] ,
289+ HashMap :: default ( ) ,
280290 )
281291}
282292
283293pub ( super ) fn test_build_and_test < DB : WriteResults > (
284294 ctx : & TaskCtx < DB > ,
285295 build_env : & Build ,
286- local_packages_id : & HashSet < PackageId > ,
296+ local_packages_id : & [ Package ] ,
287297) -> Fallible < TestResult > {
288298 let build_r = build ( ctx, build_env, local_packages_id) ;
289299 let test_r = if build_r. is_ok ( ) {
@@ -303,7 +313,7 @@ pub(super) fn test_build_and_test<DB: WriteResults>(
303313pub ( super ) fn test_build_only < DB : WriteResults > (
304314 ctx : & TaskCtx < DB > ,
305315 build_env : & Build ,
306- local_packages_id : & HashSet < PackageId > ,
316+ local_packages_id : & [ Package ] ,
307317) -> Fallible < TestResult > {
308318 if let Err ( err) = build ( ctx, build_env, local_packages_id) {
309319 Ok ( TestResult :: BuildFail ( failure_reason ( & err) ) )
@@ -315,7 +325,7 @@ pub(super) fn test_build_only<DB: WriteResults>(
315325pub ( super ) fn test_check_only < DB : WriteResults > (
316326 ctx : & TaskCtx < DB > ,
317327 build_env : & Build ,
318- local_packages_id : & HashSet < PackageId > ,
328+ local_packages_id : & [ Package ] ,
319329) -> Fallible < TestResult > {
320330 if let Err ( err) = run_cargo (
321331 ctx,
@@ -329,6 +339,7 @@ pub(super) fn test_check_only<DB: WriteResults>(
329339 ] ,
330340 true ,
331341 local_packages_id,
342+ HashMap :: default ( ) ,
332343 ) {
333344 Ok ( TestResult :: BuildFail ( failure_reason ( & err) ) )
334345 } else {
@@ -339,7 +350,7 @@ pub(super) fn test_check_only<DB: WriteResults>(
339350pub ( super ) fn test_clippy_only < DB : WriteResults > (
340351 ctx : & TaskCtx < DB > ,
341352 build_env : & Build ,
342- local_packages_id : & HashSet < PackageId > ,
353+ local_packages : & [ Package ] ,
343354) -> Fallible < TestResult > {
344355 if let Err ( err) = run_cargo (
345356 ctx,
@@ -352,7 +363,8 @@ pub(super) fn test_clippy_only<DB: WriteResults>(
352363 "--message-format=json" ,
353364 ] ,
354365 true ,
355- local_packages_id,
366+ local_packages,
367+ HashMap :: default ( ) ,
356368 ) {
357369 Ok ( TestResult :: BuildFail ( failure_reason ( & err) ) )
358370 } else {
@@ -363,29 +375,64 @@ pub(super) fn test_clippy_only<DB: WriteResults>(
363375pub ( super ) fn test_rustdoc < DB : WriteResults > (
364376 ctx : & TaskCtx < DB > ,
365377 build_env : & Build ,
366- local_packages_id : & HashSet < PackageId > ,
378+ local_packages : & [ Package ] ,
367379) -> 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 (
371392 & [
372393 "doc" ,
373394 "--frozen" ,
374395 "--no-deps" ,
375396 "--document-private-items" ,
376397 "--message-format=json" ,
377398 ] ,
378- true ,
379- local_packages_id,
399+ HashMap :: default ( ) ,
380400 ) ;
401+ if let Err ( err) = res {
402+ return Ok ( TestResult :: BuildFail ( failure_reason ( & err) ) ) ;
403+ }
381404
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 ( ) ) ;
385422
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+ }
390426 }
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 ( ) ) )
391438}
0 commit comments