about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/bootstrap/clean.rs42
1 files changed, 36 insertions, 6 deletions
diff --git a/src/bootstrap/clean.rs b/src/bootstrap/clean.rs
index 6026a000c30..c2f01ecfd1f 100644
--- a/src/bootstrap/clean.rs
+++ b/src/bootstrap/clean.rs
@@ -21,9 +21,6 @@ pub fn clean(build: &Build, all: bool) {
     } else {
         rm_rf(&build.out.join("tmp"));
         rm_rf(&build.out.join("dist"));
-        // Only delete the bootstrap executable on non-Windows systems
-        // Windows does not allow deleting a currently running executable
-        #[cfg(not(windows))]
         rm_rf(&build.out.join("bootstrap"));
 
         for host in &build.hosts {
@@ -54,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)
+                })
+            });
         }
     };
 }
@@ -80,8 +103,15 @@ where
             p.set_readonly(false);
             t!(fs::set_permissions(path, p));
             f(path).unwrap_or_else(|e| {
+                // Deleting symlinked directories on Windows is non-trivial.
+                // Skip doing so for now.
+                #[cfg(windows)]
+                if e.kind() == ErrorKind::PermissionDenied && path.is_dir() {
+                    eprintln!("warning: failed to delete '{}'.", path.display());
+                    return;
+                }
                 panic!("failed to {} {}: {}", desc, path.display(), e);
-            })
+            });
         }
         Err(e) => {
             panic!("failed to {} {}: {}", desc, path.display(), e);