@@ -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 ( ) ,
@@ -743,20 +770,13 @@ impl FileSystem for DiskFileSystem {
743770 let create_directory = compare == FileComparison :: Create ;
744771 if create_directory {
745772 if let Some ( parent) = full_path. parent ( ) {
746- retry_blocking ( parent, |p| std:: fs:: create_dir_all ( p) )
747- . concurrency_limited ( & inner. semaphore )
748- . instrument ( tracing:: info_span!(
749- "create directory" ,
750- path = display( parent. display( ) )
751- ) )
752- . await
753- . with_context ( || {
754- format ! (
755- "failed to create directory {} for write to {}" ,
756- parent. display( ) ,
757- full_path. display( )
758- )
759- } ) ?;
773+ inner. create_directory ( parent) . await . with_context ( || {
774+ format ! (
775+ "failed to create directory {} for write to {}" ,
776+ parent. display( ) ,
777+ full_path. display( )
778+ )
779+ } ) ?;
760780 }
761781 }
762782 let full_path_to_write = full_path. clone ( ) ;
@@ -879,20 +899,13 @@ impl FileSystem for DiskFileSystem {
879899 let create_directory = old_content. is_none ( ) ;
880900 if create_directory {
881901 if let Some ( parent) = full_path. parent ( ) {
882- retry_blocking ( parent, |path| std:: fs:: create_dir_all ( path) )
883- . concurrency_limited ( & inner. semaphore )
884- . instrument ( tracing:: info_span!(
885- "create directory" ,
886- path = display( parent. display( ) )
887- ) )
888- . await
889- . with_context ( || {
890- format ! (
891- "failed to create directory {} for write to {}" ,
892- parent. display( ) ,
893- full_path. display( )
894- )
895- } ) ?;
902+ inner. create_directory ( parent) . await . with_context ( || {
903+ format ! (
904+ "failed to create directory {} for write link to {}" ,
905+ parent. display( ) ,
906+ full_path. display( )
907+ )
908+ } ) ?;
896909 }
897910 }
898911
0 commit comments