]> git.lizzy.rs Git - rust.git/blobdiff - src/bootstrap/clean.rs
Rollup merge of #89255 - FabianWolff:issue-88806, r=cjgillot
[rust.git] / src / bootstrap / clean.rs
index 9b9df36e7dc0e4d8a459ab33acf316bdc9c139c6..3216c1af267306cadb87043f9a9cfa9c5ed9f236 100644 (file)
@@ -51,14 +51,40 @@ fn rm_rf(path: &Path) {
         }
         Ok(metadata) => {
             if metadata.file_type().is_file() || metadata.file_type().is_symlink() {
-                do_op(path, "remove file", |p| fs::remove_file(p));
+                do_op(path, "remove file", |p| {
+                    fs::remove_file(p).or_else(|e| {
+                        // Work around the fact that we cannot
+                        // delete an executable while it runs on Windows.
+                        #[cfg(windows)]
+                        if e.kind() == std::io::ErrorKind::PermissionDenied
+                            && p.file_name().and_then(std::ffi::OsStr::to_str)
+                                == Some("bootstrap.exe")
+                        {
+                            eprintln!("warning: failed to delete '{}'.", p.display());
+                            return Ok(());
+                        }
+                        Err(e)
+                    })
+                });
                 return;
             }
 
             for file in t!(fs::read_dir(path)) {
                 rm_rf(&t!(file).path());
             }
-            do_op(path, "remove dir", |p| fs::remove_dir(p));
+            do_op(path, "remove dir", |p| {
+                fs::remove_dir(p).or_else(|e| {
+                    // Check for dir not empty on Windows
+                    #[cfg(windows)]
+                    if matches!(e.kind(), std::io::ErrorKind::Other)
+                        && e.raw_os_error() == Some(145)
+                    {
+                        return Ok(());
+                    }
+
+                    Err(e)
+                })
+            });
         }
     };
 }
@@ -73,12 +99,18 @@ fn do_op<F>(path: &Path, desc: &str, mut f: F)
         // As a result, we have some special logic to remove readonly files on windows.
         // This is also the reason that we can't use things like fs::remove_dir_all().
         Err(ref e) if cfg!(windows) && e.kind() == ErrorKind::PermissionDenied => {
-            let mut p = t!(path.symlink_metadata()).permissions();
+            let m = t!(path.symlink_metadata());
+            let mut p = m.permissions();
             p.set_readonly(false);
             t!(fs::set_permissions(path, p));
             f(path).unwrap_or_else(|e| {
+                // Delete symlinked directories on Windows
+                #[cfg(windows)]
+                if m.file_type().is_symlink() && path.is_dir() && fs::remove_dir(path).is_ok() {
+                    return;
+                }
                 panic!("failed to {} {}: {}", desc, path.display(), e);
-            })
+            });
         }
         Err(e) => {
             panic!("failed to {} {}: {}", desc, path.display(), e);