@@ -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 rustflags = format ! ( "--cap-lints={}" , ctx. experiment. cap_lints. to_str( ) ) ;
8892 if let Some ( ref tc_rustflags) = ctx. toolchain . rustflags {
8993 rustflags. push ( ' ' ) ;
@@ -151,6 +155,9 @@ fn run_cargo<DB: WriteResults>(
151155 . env ( "CARGO_INCREMENTAL" , "0" )
152156 . env ( "RUST_BACKTRACE" , "full" )
153157 . env ( rustflags_env, rustflags) ;
158+ for ( var, data) in env {
159+ command = command. env ( var, data) ;
160+ }
154161
155162 if check_errors {
156163 command = command. process_lines ( & mut detect_error) ;
@@ -179,7 +186,7 @@ fn run_cargo<DB: WriteResults>(
179186pub ( super ) fn run_test < DB : WriteResults > (
180187 action : & str ,
181188 ctx : & TaskCtx < DB > ,
182- test_fn : fn ( & TaskCtx < DB > , & Build , & HashSet < PackageId > ) -> Fallible < TestResult > ,
189+ test_fn : fn ( & TaskCtx < DB > , & Build , & [ Package ] ) -> Fallible < TestResult > ,
183190) -> Fallible < ( ) > {
184191 if let Some ( res) = ctx
185192 . db
@@ -221,8 +228,8 @@ pub(super) fn run_test<DB: WriteResults>(
221228 }
222229
223230 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 )
226233 } ) )
227234 } ,
228235 ) ?;
@@ -233,21 +240,23 @@ pub(super) fn run_test<DB: WriteResults>(
233240fn build < DB : WriteResults > (
234241 ctx : & TaskCtx < DB > ,
235242 build_env : & Build ,
236- local_packages_id : & HashSet < PackageId > ,
243+ local_packages : & [ Package ] ,
237244) -> Fallible < ( ) > {
238245 run_cargo (
239246 ctx,
240247 build_env,
241248 & [ "build" , "--frozen" , "--message-format=json" ] ,
242249 true ,
243- local_packages_id,
250+ local_packages,
251+ HashMap :: default ( ) ,
244252 ) ?;
245253 run_cargo (
246254 ctx,
247255 build_env,
248256 & [ "test" , "--frozen" , "--no-run" , "--message-format=json" ] ,
249257 true ,
250- local_packages_id,
258+ local_packages,
259+ HashMap :: default ( ) ,
251260 ) ?;
252261 Ok ( ( ) )
253262}
@@ -258,14 +267,15 @@ fn test<DB: WriteResults>(ctx: &TaskCtx<DB>, build_env: &Build) -> Fallible<()>
258267 build_env,
259268 & [ "test" , "--frozen" ] ,
260269 false ,
261- & HashSet :: new ( ) ,
270+ & [ ] ,
271+ HashMap :: default ( ) ,
262272 )
263273}
264274
265275pub ( super ) fn test_build_and_test < DB : WriteResults > (
266276 ctx : & TaskCtx < DB > ,
267277 build_env : & Build ,
268- local_packages_id : & HashSet < PackageId > ,
278+ local_packages_id : & [ Package ] ,
269279) -> Fallible < TestResult > {
270280 let build_r = build ( ctx, build_env, local_packages_id) ;
271281 let test_r = if build_r. is_ok ( ) {
@@ -285,7 +295,7 @@ pub(super) fn test_build_and_test<DB: WriteResults>(
285295pub ( super ) fn test_build_only < DB : WriteResults > (
286296 ctx : & TaskCtx < DB > ,
287297 build_env : & Build ,
288- local_packages_id : & HashSet < PackageId > ,
298+ local_packages_id : & [ Package ] ,
289299) -> Fallible < TestResult > {
290300 if let Err ( err) = build ( ctx, build_env, local_packages_id) {
291301 Ok ( TestResult :: BuildFail ( failure_reason ( & err) ) )
@@ -297,7 +307,7 @@ pub(super) fn test_build_only<DB: WriteResults>(
297307pub ( super ) fn test_check_only < DB : WriteResults > (
298308 ctx : & TaskCtx < DB > ,
299309 build_env : & Build ,
300- local_packages_id : & HashSet < PackageId > ,
310+ local_packages_id : & [ Package ] ,
301311) -> Fallible < TestResult > {
302312 if let Err ( err) = run_cargo (
303313 ctx,
@@ -311,6 +321,7 @@ pub(super) fn test_check_only<DB: WriteResults>(
311321 ] ,
312322 true ,
313323 local_packages_id,
324+ HashMap :: default ( ) ,
314325 ) {
315326 Ok ( TestResult :: BuildFail ( failure_reason ( & err) ) )
316327 } else {
@@ -321,7 +332,7 @@ pub(super) fn test_check_only<DB: WriteResults>(
321332pub ( super ) fn test_clippy_only < DB : WriteResults > (
322333 ctx : & TaskCtx < DB > ,
323334 build_env : & Build ,
324- local_packages_id : & HashSet < PackageId > ,
335+ local_packages : & [ Package ] ,
325336) -> Fallible < TestResult > {
326337 if let Err ( err) = run_cargo (
327338 ctx,
@@ -334,7 +345,8 @@ pub(super) fn test_clippy_only<DB: WriteResults>(
334345 "--message-format=json" ,
335346 ] ,
336347 true ,
337- local_packages_id,
348+ local_packages,
349+ HashMap :: default ( ) ,
338350 ) {
339351 Ok ( TestResult :: BuildFail ( failure_reason ( & err) ) )
340352 } else {
@@ -345,29 +357,64 @@ pub(super) fn test_clippy_only<DB: WriteResults>(
345357pub ( super ) fn test_rustdoc < DB : WriteResults > (
346358 ctx : & TaskCtx < DB > ,
347359 build_env : & Build ,
348- local_packages_id : & HashSet < PackageId > ,
360+ local_packages : & [ Package ] ,
349361) -> 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 (
353374 & [
354375 "doc" ,
355376 "--frozen" ,
356377 "--no-deps" ,
357378 "--document-private-items" ,
358379 "--message-format=json" ,
359380 ] ,
360- true ,
361- local_packages_id,
381+ HashMap :: default ( ) ,
362382 ) ;
383+ if let Err ( err) = res {
384+ return Ok ( TestResult :: BuildFail ( failure_reason ( & err) ) ) ;
385+ }
363386
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 ( ) ) ;
367404
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+ }
372408 }
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 ( ) ) )
373420}
0 commit comments