@@ -125,6 +125,21 @@ pub struct SharedContext {
125125 /// Warnings for the user if rendering would differ using different markdown
126126 /// parsers.
127127 pub markdown_warnings : RefCell < Vec < ( Span , String , Vec < html_diff:: Difference > ) > > ,
128+ /// The directories that have already been created in this doc run. Used to reduce the number
129+ /// of spurious `create_dir_all` calls.
130+ pub created_dirs : RefCell < FxHashSet < PathBuf > > ,
131+ }
132+
133+ impl SharedContext {
134+ fn ensure_dir ( & self , dst : & Path ) -> io:: Result < ( ) > {
135+ let mut dirs = self . created_dirs . borrow_mut ( ) ;
136+ if !dirs. contains ( dst) {
137+ fs:: create_dir_all ( dst) ?;
138+ dirs. insert ( dst. to_path_buf ( ) ) ;
139+ }
140+
141+ Ok ( ( ) )
142+ }
128143}
129144
130145/// Indicates where an external crate can be found.
@@ -463,6 +478,7 @@ pub fn run(mut krate: clean::Crate,
463478 } ,
464479 css_file_extension : css_file_extension. clone ( ) ,
465480 markdown_warnings : RefCell :: new ( vec ! [ ] ) ,
481+ created_dirs : RefCell :: new ( FxHashSet ( ) ) ,
466482 } ;
467483
468484 // If user passed in `--playground-url` arg, we fill in crate name here
@@ -794,7 +810,6 @@ fn write_shared(cx: &Context,
794810 // Write out the shared files. Note that these are shared among all rustdoc
795811 // docs placed in the output directory, so this needs to be a synchronized
796812 // operation with respect to all other rustdocs running around.
797- try_err ! ( fs:: create_dir_all( & cx. dst) , & cx. dst) ;
798813 let _lock = flock:: Lock :: panicking_new ( & cx. dst . join ( ".lock" ) , true , true , true ) ;
799814
800815 // Add all the static files. These may already exist, but we just
@@ -1518,8 +1533,8 @@ impl Context {
15181533 this. render_item ( & mut buf, & item, false ) . unwrap ( ) ;
15191534 // buf will be empty if the module is stripped and there is no redirect for it
15201535 if !buf. is_empty ( ) {
1536+ try_err ! ( this. shared. ensure_dir( & this. dst) , & this. dst) ;
15211537 let joint_dst = this. dst . join ( "index.html" ) ;
1522- try_err ! ( fs:: create_dir_all( & this. dst) , & this. dst) ;
15231538 let mut dst = try_err ! ( File :: create( & joint_dst) , & joint_dst) ;
15241539 try_err ! ( dst. write_all( & buf) , & joint_dst) ;
15251540 }
@@ -1553,18 +1568,19 @@ impl Context {
15531568 let name = item. name . as_ref ( ) . unwrap ( ) ;
15541569 let item_type = item. type_ ( ) ;
15551570 let file_name = & item_path ( item_type, name) ;
1571+ try_err ! ( self . shared. ensure_dir( & self . dst) , & self . dst) ;
15561572 let joint_dst = self . dst . join ( file_name) ;
1557- try_err ! ( fs:: create_dir_all( & self . dst) , & self . dst) ;
15581573 let mut dst = try_err ! ( File :: create( & joint_dst) , & joint_dst) ;
15591574 try_err ! ( dst. write_all( & buf) , & joint_dst) ;
15601575
15611576 // Redirect from a sane URL using the namespace to Rustdoc's
15621577 // URL for the page.
15631578 let redir_name = format ! ( "{}.{}.html" , name, item_type. name_space( ) ) ;
15641579 let redir_dst = self . dst . join ( redir_name) ;
1565- if let Ok ( mut redirect_out) = OpenOptions :: new ( ) . create_new ( true )
1580+ if let Ok ( redirect_out) = OpenOptions :: new ( ) . create_new ( true )
15661581 . write ( true )
15671582 . open ( & redir_dst) {
1583+ let mut redirect_out = BufWriter :: new ( redirect_out) ;
15681584 try_err ! ( layout:: redirect( & mut redirect_out, file_name) , & redir_dst) ;
15691585 }
15701586
@@ -1574,7 +1590,8 @@ impl Context {
15741590 if item_type == ItemType :: Macro {
15751591 let redir_name = format ! ( "{}.{}!.html" , item_type, name) ;
15761592 let redir_dst = self . dst . join ( redir_name) ;
1577- let mut redirect_out = try_err ! ( File :: create( & redir_dst) , & redir_dst) ;
1593+ let redirect_out = try_err ! ( File :: create( & redir_dst) , & redir_dst) ;
1594+ let mut redirect_out = BufWriter :: new ( redirect_out) ;
15781595 try_err ! ( layout:: redirect( & mut redirect_out, file_name) , & redir_dst) ;
15791596 }
15801597 }
0 commit comments