@@ -39,6 +39,7 @@ use std::{
3939use anyhow:: { anyhow, bail, Context , Result } ;
4040use auto_hash_map:: { AutoMap , AutoSet } ;
4141use bitflags:: bitflags;
42+ use dashmap:: DashSet ;
4243use dunce:: simplified;
4344use glob:: Glob ;
4445use indexmap:: IndexSet ;
@@ -227,6 +228,10 @@ struct DiskFileSystemInner {
227228 #[ turbo_tasks( debug_ignore, trace_ignore) ]
228229 #[ serde( skip) ]
229230 invalidation_lock : RwLock < ( ) > ,
231+ /// A cache of already created directories to avoid creating them multiple times.
232+ #[ turbo_tasks( debug_ignore, trace_ignore) ]
233+ #[ serde( skip) ]
234+ created_directories : DashSet < PathBuf > ,
230235 /// Semaphore to limit the maximum number of concurrent file operations.
231236 #[ turbo_tasks( debug_ignore, trace_ignore) ]
232237 #[ serde( skip, default = "create_semaphore" ) ]
@@ -394,6 +399,27 @@ impl DiskFileSystemInner {
394399
395400 Ok ( ( ) )
396401 }
402+
403+ async fn create_directory ( self : & Arc < Self > , directory : & Path ) -> Result < ( ) > {
404+ if !self . created_directories . contains ( directory) {
405+ let func = {
406+ let inner = self . clone ( ) ;
407+ move |p : & Path | -> io:: Result < ( ) > {
408+ std:: fs:: create_dir_all ( p) ?;
409+ inner. created_directories . insert ( p. to_path_buf ( ) ) ;
410+ Ok ( ( ) )
411+ }
412+ } ;
413+ retry_blocking ( directory, func)
414+ . concurrency_limited ( & self . semaphore )
415+ . instrument ( tracing:: info_span!(
416+ "create directory" ,
417+ path = display( directory. display( ) )
418+ ) )
419+ . await ?;
420+ }
421+ Ok ( ( ) )
422+ }
397423}
398424
399425#[ turbo_tasks:: value( cell = "new" , eq = "manual" ) ]
@@ -500,6 +526,7 @@ impl DiskFileSystem {
500526 invalidation_lock : Default :: default ( ) ,
501527 invalidator_map : InvalidatorMap :: new ( ) ,
502528 dir_invalidator_map : InvalidatorMap :: new ( ) ,
529+ created_directories : Default :: default ( ) ,
503530 semaphore : create_semaphore ( ) ,
504531 watcher : DiskWatcher :: new (
505532 ignored_subpaths. into_iter ( ) . map ( PathBuf :: from) . collect ( ) ,
@@ -744,20 +771,13 @@ impl FileSystem for DiskFileSystem {
744771 let create_directory = compare == FileComparison :: Create ;
745772 if create_directory {
746773 if let Some ( parent) = full_path. parent ( ) {
747- retry_blocking ( parent, |p| std:: fs:: create_dir_all ( p) )
748- . concurrency_limited ( & inner. semaphore )
749- . instrument ( tracing:: info_span!(
750- "create directory" ,
751- path = display( parent. display( ) )
752- ) )
753- . await
754- . with_context ( || {
755- format ! (
756- "failed to create directory {} for write to {}" ,
757- parent. display( ) ,
758- full_path. display( )
759- )
760- } ) ?;
774+ inner. create_directory ( parent) . await . with_context ( || {
775+ format ! (
776+ "failed to create directory {} for write to {}" ,
777+ parent. display( ) ,
778+ full_path. display( )
779+ )
780+ } ) ?;
761781 }
762782 }
763783 let full_path_to_write = full_path. clone ( ) ;
@@ -881,20 +901,13 @@ impl FileSystem for DiskFileSystem {
881901 let create_directory = old_content. is_none ( ) ;
882902 if create_directory {
883903 if let Some ( parent) = full_path. parent ( ) {
884- retry_blocking ( parent, |path| std:: fs:: create_dir_all ( path) )
885- . concurrency_limited ( & inner. semaphore )
886- . instrument ( tracing:: info_span!(
887- "create directory" ,
888- path = display( parent. display( ) )
889- ) )
890- . await
891- . with_context ( || {
892- format ! (
893- "failed to create directory {} for write to {}" ,
894- parent. display( ) ,
895- full_path. display( )
896- )
897- } ) ?;
904+ inner. create_directory ( parent) . await . with_context ( || {
905+ format ! (
906+ "failed to create directory {} for write link to {}" ,
907+ parent. display( ) ,
908+ full_path. display( )
909+ )
910+ } ) ?;
898911 }
899912 }
900913
0 commit comments