@@ -39,6 +39,7 @@ use std::{
39
39
use anyhow:: { anyhow, bail, Context , Result } ;
40
40
use auto_hash_map:: { AutoMap , AutoSet } ;
41
41
use bitflags:: bitflags;
42
+ use dashmap:: DashSet ;
42
43
use dunce:: simplified;
43
44
use glob:: Glob ;
44
45
use indexmap:: IndexSet ;
@@ -227,6 +228,10 @@ struct DiskFileSystemInner {
227
228
#[ turbo_tasks( debug_ignore, trace_ignore) ]
228
229
#[ serde( skip) ]
229
230
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 > ,
230
235
/// Semaphore to limit the maximum number of concurrent file operations.
231
236
#[ turbo_tasks( debug_ignore, trace_ignore) ]
232
237
#[ serde( skip, default = "create_semaphore" ) ]
@@ -394,6 +399,27 @@ impl DiskFileSystemInner {
394
399
395
400
Ok ( ( ) )
396
401
}
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
+ }
397
423
}
398
424
399
425
#[ turbo_tasks:: value( cell = "new" , eq = "manual" ) ]
@@ -500,6 +526,7 @@ impl DiskFileSystem {
500
526
invalidation_lock : Default :: default ( ) ,
501
527
invalidator_map : InvalidatorMap :: new ( ) ,
502
528
dir_invalidator_map : InvalidatorMap :: new ( ) ,
529
+ created_directories : Default :: default ( ) ,
503
530
semaphore : create_semaphore ( ) ,
504
531
watcher : DiskWatcher :: new (
505
532
ignored_subpaths. into_iter ( ) . map ( PathBuf :: from) . collect ( ) ,
@@ -743,20 +770,13 @@ impl FileSystem for DiskFileSystem {
743
770
let create_directory = compare == FileComparison :: Create ;
744
771
if create_directory {
745
772
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
+ } ) ?;
760
780
}
761
781
}
762
782
let full_path_to_write = full_path. clone ( ) ;
@@ -879,20 +899,13 @@ impl FileSystem for DiskFileSystem {
879
899
let create_directory = old_content. is_none ( ) ;
880
900
if create_directory {
881
901
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
+ } ) ?;
896
909
}
897
910
}
898
911
0 commit comments