@@ -20,7 +20,7 @@ use rustwide::toolchain::ToolchainError;
20
20
use rustwide:: { Build , Crate , Toolchain , Workspace , WorkspaceBuilder } ;
21
21
use serde_json:: Value ;
22
22
use std:: borrow:: Cow ;
23
- use std:: collections:: HashSet ;
23
+ use std:: collections:: { HashMap , HashSet } ;
24
24
use std:: path:: Path ;
25
25
use std:: sync:: Arc ;
26
26
@@ -69,84 +69,6 @@ const ESSENTIAL_FILES_UNVERSIONED: &[&str] = &[
69
69
const DUMMY_CRATE_NAME : & str = "empty-library" ;
70
70
const DUMMY_CRATE_VERSION : & str = "1.0.0" ;
71
71
72
- // This macro exists because of lifetimes issues surrounding the `Command::process_lines` method:
73
- // it expects a mutable reference to a closure, in which we capture a variable in order to store
74
- // the JSON output. Unfortunately, we *need* to create the command in the same scope level otherwise
75
- // rustc becomes very grumpy about the fact that the variable needs to be static because it is
76
- // captured in a mutably referenced closure.
77
- //
78
- // So either you create a function with a callback in which you pass the `Command` as an argument,
79
- // or you create a function returning a `Command`, it's very unhappy in both cases.
80
- //
81
- // TODO: make `Command::process_lines` take the closure by value rather than a mutable reference.
82
- macro_rules! config_command {
83
- ( $obj: ident, $build: expr, $target: expr, $metadata: expr, $limits: expr, $rustdoc_flags_extras: expr, $( $extra: tt) +) => { {
84
- let mut cargo_args = vec![ "doc" , "--lib" , "--no-deps" ] ;
85
- if $target != HOST_TARGET {
86
- // If the explicit target is not a tier one target, we need to install it.
87
- if !TARGETS . contains( & $target) {
88
- // This is a no-op if the target is already installed.
89
- $obj. toolchain. add_target( & $obj. workspace, $target) ?;
90
- }
91
- cargo_args. push( "--target" ) ;
92
- cargo_args. push( $target) ;
93
- } ;
94
-
95
- let tmp;
96
- if let Some ( cpu_limit) = $obj. cpu_limit {
97
- tmp = format!( "-j{}" , cpu_limit) ;
98
- cargo_args. push( & tmp) ;
99
- }
100
-
101
- let tmp;
102
- if let Some ( features) = & $metadata. features {
103
- cargo_args. push( "--features" ) ;
104
- tmp = features. join( " " ) ;
105
- cargo_args. push( & tmp) ;
106
- }
107
- if $metadata. all_features {
108
- cargo_args. push( "--all-features" ) ;
109
- }
110
- if $metadata. no_default_features {
111
- cargo_args. push( "--no-default-features" ) ;
112
- }
113
-
114
- let mut rustdoc_flags = vec![
115
- "-Z" . to_string( ) ,
116
- "unstable-options" . to_string( ) ,
117
- "--static-root-path" . to_string( ) ,
118
- "/" . to_string( ) ,
119
- "--cap-lints" . to_string( ) ,
120
- "warn" . to_string( ) ,
121
- ] ;
122
-
123
- if let Some ( package_rustdoc_args) = & $metadata. rustdoc_args {
124
- rustdoc_flags. append( & mut package_rustdoc_args. clone( ) ) ;
125
- }
126
-
127
- rustdoc_flags. extend( $rustdoc_flags_extras) ;
128
-
129
- $build
130
- . cargo( )
131
- . timeout( Some ( $limits. timeout( ) ) )
132
- . no_output_timeout( None )
133
- . env(
134
- "RUSTFLAGS" ,
135
- $metadata
136
- . rustc_args
137
- . as_ref( )
138
- . map( |args| args. join( " " ) )
139
- . unwrap_or_default( ) ,
140
- )
141
- . env( "RUSTDOCFLAGS" , rustdoc_flags. join( " " ) )
142
- // For docs.rs detection from build script:
143
- // https://github.com/rust-lang/docs.rs/issues/147
144
- . env( "DOCS_RS" , "1" )
145
- . args( & cargo_args)
146
- $( $extra) +
147
- } }
148
- }
149
-
150
72
pub struct RustwideBuilder {
151
73
workspace : Workspace ,
152
74
toolchain : Toolchain ,
@@ -558,41 +480,46 @@ impl RustwideBuilder {
558
480
metadata : & Metadata ,
559
481
limits : & Limits ,
560
482
) -> Result < Option < DocCoverage > > {
561
- let mut doc_coverage_json = None ;
562
-
563
483
let rustdoc_flags = vec ! [
564
484
"--output-format" . to_string( ) ,
565
485
"json" . to_string( ) ,
566
486
"--show-coverage" . to_string( ) ,
567
487
] ;
568
- config_command ! ( self , build, target, metadata, limits, rustdoc_flags,
488
+
489
+ #[ derive( serde:: Deserialize ) ]
490
+ struct FileCoverage {
491
+ total : i32 ,
492
+ with_docs : i32 ,
493
+ }
494
+
495
+ let mut coverage = DocCoverage {
496
+ total_items : 0 ,
497
+ documented_items : 0 ,
498
+ } ;
499
+
500
+ self . prepare_command ( build, target, metadata, limits, rustdoc_flags) ?
569
501
. process_lines ( & mut |line, _| {
570
502
if line. starts_with ( '{' ) && line. ends_with ( '}' ) {
571
- doc_coverage_json = Some ( line. to_owned( ) ) ;
503
+ let parsed = match serde_json:: from_str :: < HashMap < String , FileCoverage > > ( line) {
504
+ Ok ( parsed) => parsed,
505
+ Err ( _) => return ,
506
+ } ;
507
+ for file in parsed. values ( ) {
508
+ coverage. total_items += file. total ;
509
+ coverage. documented_items += file. with_docs ;
510
+ }
572
511
}
573
512
} )
574
513
. log_output ( false )
575
514
. run ( ) ?;
576
- ) ;
577
-
578
- if let Some ( json) = doc_coverage_json {
579
- if let Ok ( Value :: Object ( m) ) = serde_json:: from_str ( & json) {
580
- let ( mut total_items, mut documented_items) = ( 0 , 0 ) ;
581
- for entry in m. values ( ) {
582
- if let Some ( Value :: Number ( n) ) = entry. get ( "total" ) {
583
- total_items += n. as_i64 ( ) . unwrap_or ( 0 ) as i32 ;
584
- }
585
- if let Some ( Value :: Number ( n) ) = entry. get ( "with_docs" ) {
586
- documented_items += n. as_i64 ( ) . unwrap_or ( 0 ) as i32 ;
587
- }
588
- }
589
- return Ok ( Some ( DocCoverage {
590
- total_items,
591
- documented_items,
592
- } ) ) ;
593
- }
594
- }
595
- Ok ( None )
515
+
516
+ Ok (
517
+ if coverage. total_items == 0 && coverage. documented_items == 0 {
518
+ None
519
+ } else {
520
+ Some ( coverage)
521
+ } ,
522
+ )
596
523
}
597
524
598
525
fn execute_build (
@@ -627,12 +554,9 @@ impl RustwideBuilder {
627
554
storage. set_max_size ( limits. max_log_size ( ) ) ;
628
555
629
556
let successful = logging:: capture ( & storage, || {
630
- let wrap = || {
631
- config_command ! ( self , build, target, metadata, limits, rustdoc_flags,
632
- . run( )
633
- )
634
- } ;
635
- wrap ( ) . is_ok ( )
557
+ self . prepare_command ( build, target, metadata, limits, rustdoc_flags)
558
+ . and_then ( |command| command. run ( ) . map_err ( failure:: Error :: from) )
559
+ . is_ok ( )
636
560
} ) ;
637
561
let doc_coverage = if successful {
638
562
self . get_coverage ( target, build, metadata, limits) ?
@@ -665,6 +589,80 @@ impl RustwideBuilder {
665
589
} )
666
590
}
667
591
592
+ fn prepare_command < ' ws , ' pl > (
593
+ & self ,
594
+ build : & ' ws Build ,
595
+ target : & str ,
596
+ metadata : & Metadata ,
597
+ limits : & Limits ,
598
+ rustdoc_flags_extras : Vec < String > ,
599
+ ) -> Result < Command < ' ws , ' pl > > {
600
+ let mut cargo_args = vec ! [ "doc" , "--lib" , "--no-deps" ] ;
601
+ if target != HOST_TARGET {
602
+ // If the explicit target is not a tier one target, we need to install it.
603
+ if !TARGETS . contains ( & target) {
604
+ // This is a no-op if the target is already installed.
605
+ self . toolchain . add_target ( & self . workspace , target) ?;
606
+ }
607
+ cargo_args. push ( "--target" ) ;
608
+ cargo_args. push ( target) ;
609
+ } ;
610
+
611
+ let tmp;
612
+ if let Some ( cpu_limit) = self . cpu_limit {
613
+ tmp = format ! ( "-j{}" , cpu_limit) ;
614
+ cargo_args. push ( & tmp) ;
615
+ }
616
+
617
+ let tmp;
618
+ if let Some ( features) = & metadata. features {
619
+ cargo_args. push ( "--features" ) ;
620
+ tmp = features. join ( " " ) ;
621
+ cargo_args. push ( & tmp) ;
622
+ }
623
+ if metadata. all_features {
624
+ cargo_args. push ( "--all-features" ) ;
625
+ }
626
+ if metadata. no_default_features {
627
+ cargo_args. push ( "--no-default-features" ) ;
628
+ }
629
+
630
+ let mut rustdoc_flags = vec ! [
631
+ "-Z" . to_string( ) ,
632
+ "unstable-options" . to_string( ) ,
633
+ "--static-root-path" . to_string( ) ,
634
+ "/" . to_string( ) ,
635
+ "--cap-lints" . to_string( ) ,
636
+ "warn" . to_string( ) ,
637
+ ] ;
638
+
639
+ if let Some ( package_rustdoc_args) = & metadata. rustdoc_args {
640
+ rustdoc_flags. append ( & mut package_rustdoc_args. clone ( ) ) ;
641
+ }
642
+
643
+ rustdoc_flags. extend ( rustdoc_flags_extras) ;
644
+
645
+ let command = build
646
+ . cargo ( )
647
+ . timeout ( Some ( limits. timeout ( ) ) )
648
+ . no_output_timeout ( None )
649
+ . env (
650
+ "RUSTFLAGS" ,
651
+ metadata
652
+ . rustc_args
653
+ . as_ref ( )
654
+ . map ( |args| args. join ( " " ) )
655
+ . unwrap_or_default ( ) ,
656
+ )
657
+ . env ( "RUSTDOCFLAGS" , rustdoc_flags. join ( " " ) )
658
+ // For docs.rs detection from build script:
659
+ // https://github.com/rust-lang/docs.rs/issues/147
660
+ . env ( "DOCS_RS" , "1" )
661
+ . args ( & cargo_args) ;
662
+
663
+ Ok ( command)
664
+ }
665
+
668
666
fn copy_docs (
669
667
& self ,
670
668
target_dir : & Path ,
0 commit comments