From f52caa76f9204b1341b59adad3d6323f4ca35292 Mon Sep 17 00:00:00 2001 From: Ryan Levick Date: Tue, 16 Feb 2021 10:35:15 +0100 Subject: [PATCH 1/3] Do not delete bootstrap.exe on Windows during clean Windows does not allow deleting currently running executables --- src/bootstrap/clean.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/bootstrap/clean.rs b/src/bootstrap/clean.rs index 9b9df36e7dc0e..6026a000c3004 100644 --- a/src/bootstrap/clean.rs +++ b/src/bootstrap/clean.rs @@ -21,6 +21,9 @@ 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 { From e18c79a4a9c06ae8dc282f1b4aae560a3076d9cd Mon Sep 17 00:00:00 2001 From: Ryan Levick Date: Tue, 16 Feb 2021 16:50:45 +0100 Subject: [PATCH 2/3] Work around various issues cleaning up bootstrap on Windows --- src/bootstrap/clean.rs | 42 ++++++++++++++++++++++++++++++++++++------ 1 file changed, 36 insertions(+), 6 deletions(-) diff --git a/src/bootstrap/clean.rs b/src/bootstrap/clean.rs index 6026a000c3004..c2f01ecfd1ff9 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); From 5b0ed02bb9e0ee00c32cbf41eb2a12fe5476fe56 Mon Sep 17 00:00:00 2001 From: Ryan Levick Date: Tue, 16 Feb 2021 17:08:11 +0100 Subject: [PATCH 3/3] Delete symlinked directories --- src/bootstrap/clean.rs | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/bootstrap/clean.rs b/src/bootstrap/clean.rs index c2f01ecfd1ff9..3216c1af26730 100644 --- a/src/bootstrap/clean.rs +++ b/src/bootstrap/clean.rs @@ -99,15 +99,14 @@ where // 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| { - // Deleting symlinked directories on Windows is non-trivial. - // Skip doing so for now. + // Delete symlinked directories on Windows #[cfg(windows)] - if e.kind() == ErrorKind::PermissionDenied && path.is_dir() { - eprintln!("warning: failed to delete '{}'.", path.display()); + if m.file_type().is_symlink() && path.is_dir() && fs::remove_dir(path).is_ok() { return; } panic!("failed to {} {}: {}", desc, path.display(), e);