}
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)
+ })
+ });
}
};
}
// 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);