@@ -3,7 +3,8 @@ use super::Metadata;
3
3
use crate :: db:: blacklist:: is_blacklisted;
4
4
use crate :: db:: file:: add_path_into_database;
5
5
use crate :: db:: {
6
- add_build_into_database, add_package_into_database, update_crate_data_in_database, Pool ,
6
+ add_build_into_database, add_doc_coverage, add_package_into_database,
7
+ update_crate_data_in_database, Pool ,
7
8
} ;
8
9
use crate :: docbuilder:: { crates:: crates_from_path, Limits } ;
9
10
use crate :: error:: Result ;
@@ -428,6 +429,12 @@ impl RustwideBuilder {
428
429
algs,
429
430
) ?;
430
431
432
+ if let ( Some ( total) , Some ( documented) ) =
433
+ ( res. result . total_items , res. result . documented_items )
434
+ {
435
+ add_doc_coverage ( & mut conn, release_id, total, documented) ?;
436
+ }
437
+
431
438
add_build_into_database ( & mut conn, release_id, & res. result ) ?;
432
439
433
440
// Some crates.io crate data is mutable, so we proactively update it during a release
@@ -469,6 +476,106 @@ impl RustwideBuilder {
469
476
Ok ( ( ) )
470
477
}
471
478
479
+ fn get_coverage (
480
+ & self ,
481
+ target : & str ,
482
+ build : & Build ,
483
+ metadata : & Metadata ,
484
+ limits : & Limits ,
485
+ ) -> Option < ( i32 , i32 ) > {
486
+ let rustdoc_flags: Vec < String > = vec ! [
487
+ "-Z" . to_string( ) ,
488
+ "unstable-options" . to_string( ) ,
489
+ "--static-root-path" . to_string( ) ,
490
+ "/" . to_string( ) ,
491
+ "--cap-lints" . to_string( ) ,
492
+ "warn" . to_string( ) ,
493
+ "--output-format" . to_string( ) ,
494
+ "json" . to_string( ) ,
495
+ "--show-coverage" . to_string( ) ,
496
+ ] ;
497
+
498
+ let mut cargo_args = vec ! [ "doc" , "--lib" , "--no-deps" ] ;
499
+ if target != HOST_TARGET {
500
+ // If the explicit target is not a tier one target, we need to install it.
501
+ if !TARGETS . contains ( & target) {
502
+ // This is a no-op if the target is already installed.
503
+ self . toolchain . add_target ( & self . workspace , target) . ok ( ) ?;
504
+ }
505
+ cargo_args. push ( "--target" ) ;
506
+ cargo_args. push ( target) ;
507
+ } ;
508
+
509
+ let tmp_jobs;
510
+ if let Some ( cpu_limit) = self . cpu_limit {
511
+ tmp_jobs = format ! ( "-j{}" , cpu_limit) ;
512
+ cargo_args. push ( & tmp_jobs) ;
513
+ }
514
+
515
+ let tmp;
516
+ if let Some ( features) = & metadata. features {
517
+ cargo_args. push ( "--features" ) ;
518
+ tmp = features. join ( " " ) ;
519
+ cargo_args. push ( & tmp) ;
520
+ }
521
+ if metadata. all_features {
522
+ cargo_args. push ( "--all-features" ) ;
523
+ }
524
+ if metadata. no_default_features {
525
+ cargo_args. push ( "--no-default-features" ) ;
526
+ }
527
+
528
+ let mut storage = LogStorage :: new ( LevelFilter :: Info ) ;
529
+ storage. set_max_size ( limits. max_log_size ( ) ) ;
530
+
531
+ let mut json = String :: new ( ) ;
532
+ if build
533
+ . cargo ( )
534
+ . timeout ( Some ( limits. timeout ( ) ) )
535
+ . no_output_timeout ( None )
536
+ . env (
537
+ "RUSTFLAGS" ,
538
+ metadata
539
+ . rustc_args
540
+ . as_ref ( )
541
+ . map ( |args| args. join ( " " ) )
542
+ . unwrap_or_default ( ) ,
543
+ )
544
+ . env ( "RUSTDOCFLAGS" , rustdoc_flags. join ( " " ) )
545
+ // For docs.rs detection from build script:
546
+ // https://github.com/rust-lang/docs.rs/issues/147
547
+ . env ( "DOCS_RS" , "1" )
548
+ . args ( & cargo_args)
549
+ . log_output ( false )
550
+ . process_lines ( & mut |line, _| {
551
+ if line. starts_with ( '{' ) && line. ends_with ( '}' ) {
552
+ json = line. to_owned ( ) ;
553
+ }
554
+ } )
555
+ . run ( )
556
+ . is_ok ( )
557
+ {
558
+ match serde_json:: from_str ( & json) . expect ( "conversion failed..." ) {
559
+ Value :: Object ( m) => {
560
+ let mut total = 0 ;
561
+ let mut documented = 0 ;
562
+ for entry in m. values ( ) {
563
+ if let Some ( Value :: Number ( n) ) = entry. get ( "total" ) {
564
+ total += n. as_i64 ( ) . unwrap_or ( 0 ) as i32 ;
565
+ }
566
+ if let Some ( Value :: Number ( n) ) = entry. get ( "with_docs" ) {
567
+ documented += n. as_i64 ( ) . unwrap_or ( 0 ) as i32 ;
568
+ }
569
+ }
570
+ Some ( ( total, documented) )
571
+ }
572
+ _ => None ,
573
+ }
574
+ } else {
575
+ None
576
+ }
577
+ }
578
+
472
579
fn execute_build (
473
580
& self ,
474
581
target : & str ,
@@ -556,6 +663,14 @@ impl RustwideBuilder {
556
663
. run ( )
557
664
. is_ok ( )
558
665
} ) ;
666
+ let mut total_items = None ;
667
+ let mut documented_items = None ;
668
+ if successful {
669
+ if let Some ( ( total, documented) ) = self . get_coverage ( target, build, metadata, limits) {
670
+ total_items = Some ( total) ;
671
+ documented_items = Some ( documented) ;
672
+ }
673
+ }
559
674
// If we're passed a default_target which requires a cross-compile,
560
675
// cargo will put the output in `target/<target>/doc`.
561
676
// However, if this is the default build, we don't want it there,
@@ -575,6 +690,8 @@ impl RustwideBuilder {
575
690
rustc_version : self . rustc_version . clone ( ) ,
576
691
docsrs_version : format ! ( "docsrs {}" , crate :: BUILD_VERSION ) ,
577
692
successful,
693
+ total_items,
694
+ documented_items,
578
695
} ,
579
696
cargo_metadata,
580
697
target : target. to_string ( ) ,
@@ -631,4 +748,7 @@ pub(crate) struct BuildResult {
631
748
pub ( crate ) docsrs_version : String ,
632
749
pub ( crate ) build_log : String ,
633
750
pub ( crate ) successful : bool ,
751
+ // The two next fields are used for the doc coverage.
752
+ pub ( crate ) total_items : Option < i32 > ,
753
+ pub ( crate ) documented_items : Option < i32 > ,
634
754
}
0 commit comments