@@ -31,25 +31,47 @@ where
31
31
///
32
32
/// FIXME: this implementation is insufficiently robust to replace bootstrap's clean `rm_rf`
33
33
/// implementation:
34
- ///
35
- /// - This implementation currently does not perform retries.
36
34
#[ track_caller]
37
35
pub fn recursive_remove < P : AsRef < Path > > ( path : P ) -> io:: Result < ( ) > {
38
36
let path = path. as_ref ( ) ;
39
- let metadata = fs:: symlink_metadata ( path) ?;
40
- #[ cfg( windows) ]
41
- let is_dir_like = |meta : & fs:: Metadata | {
42
- use std:: os:: windows:: fs:: FileTypeExt ;
43
- meta. is_dir ( ) || meta. file_type ( ) . is_symlink_dir ( )
44
- } ;
45
- #[ cfg( not( windows) ) ]
46
- let is_dir_like = fs:: Metadata :: is_dir;
47
37
48
- if is_dir_like ( & metadata) {
49
- fs:: remove_dir_all ( path)
50
- } else {
51
- try_remove_op_set_perms ( fs:: remove_file, path, metadata)
38
+ for retry in 0 ..5 {
39
+ match fs:: symlink_metadata ( path) {
40
+ Ok ( metadata) => {
41
+ #[ cfg( windows) ]
42
+ let is_dir_like = |meta : & fs:: Metadata | {
43
+ use std:: os:: windows:: fs:: FileTypeExt ;
44
+ meta. is_dir ( ) || meta. file_type ( ) . is_symlink_dir ( )
45
+ } ;
46
+ #[ cfg( not( windows) ) ]
47
+ let is_dir_like = fs:: Metadata :: is_dir;
48
+
49
+ let result = if is_dir_like ( & metadata) {
50
+ fs:: remove_dir_all ( path)
51
+ } else {
52
+ try_remove_op_set_perms ( fs:: remove_file, path, metadata)
53
+ } ;
54
+
55
+ match result {
56
+ Ok ( ( ) ) => return Ok ( ( ) ) ,
57
+ Err ( _) if retry < 4 => {
58
+ continue ;
59
+ }
60
+ Err ( e) => return Err ( e) ,
61
+ }
62
+ }
63
+
64
+ Err ( e) if e. kind ( ) == io:: ErrorKind :: NotFound => return Ok ( ( ) ) ,
65
+
66
+ Err ( _) if retry < 4 => {
67
+ continue ;
68
+ }
69
+
70
+ Err ( e) => return Err ( e) ,
71
+ }
52
72
}
73
+
74
+ Ok ( ( ) )
53
75
}
54
76
55
77
fn try_remove_op_set_perms < ' p , Op > ( mut op : Op , path : & ' p Path , metadata : Metadata ) -> io:: Result < ( ) >
0 commit comments