6
6
//! directory unless the `--all` flag is present.
7
7
8
8
use std::fs;
9
- use std::io::{self, ErrorKind};
10
9
use std::path::Path;
11
10
12
11
use crate::core::builder::{crate_description, Builder, RunConfig, ShouldRun, Step};
@@ -101,11 +100,11 @@ fn clean(build: &Build, all: bool, stage: Option<u32>) {
101
100
return;
102
101
}
103
102
104
- rm_rf ("tmp".as_ref() );
103
+ remove_dir_recursive ("tmp");
105
104
106
105
// Clean the entire build directory
107
106
if all {
108
- rm_rf (&build.out);
107
+ remove_dir_recursive (&build.out);
109
108
return;
110
109
}
111
110
@@ -136,17 +135,17 @@ fn clean_specific_stage(build: &Build, stage: u32) {
136
135
}
137
136
138
137
let path = t!(entry.path().canonicalize());
139
- rm_rf (&path);
138
+ remove_dir_recursive (&path);
140
139
}
141
140
}
142
141
}
143
142
144
143
fn clean_default(build: &Build) {
145
- rm_rf(& build.out.join("tmp"));
146
- rm_rf(& build.out.join("dist"));
147
- rm_rf(& build.out.join("bootstrap").join(".last-warned-change-id"));
148
- rm_rf(& build.out.join("bootstrap-shims-dump"));
149
- rm_rf(& build.out.join("rustfmt.stamp"));
144
+ remove_dir_recursive( build.out.join("tmp"));
145
+ remove_dir_recursive( build.out.join("dist"));
146
+ remove_dir_recursive( build.out.join("bootstrap").join(".last-warned-change-id"));
147
+ remove_dir_recursive( build.out.join("bootstrap-shims-dump"));
148
+ remove_dir_recursive( build.out.join("rustfmt.stamp"));
150
149
151
150
let mut hosts: Vec<_> = build.hosts.iter().map(|t| build.out.join(t)).collect();
152
151
// After cross-compilation, artifacts of the host architecture (which may differ from build.host)
@@ -166,78 +165,16 @@ fn clean_default(build: &Build) {
166
165
continue;
167
166
}
168
167
let path = t!(entry.path().canonicalize());
169
- rm_rf (&path);
168
+ remove_dir_recursive (&path);
170
169
}
171
170
}
172
171
}
173
172
174
- fn rm_rf(path: &Path) {
175
- match path.symlink_metadata() {
176
- Err(e) => {
177
- if e.kind() == ErrorKind::NotFound {
178
- return;
179
- }
180
- panic!("failed to get metadata for file {}: {}", path.display(), e);
181
- }
182
- Ok(metadata) => {
183
- if metadata.file_type().is_file() || metadata.file_type().is_symlink() {
184
- do_op(path, "remove file", |p| match fs::remove_file(p) {
185
- #[cfg(windows)]
186
- Err(e)
187
- if e.kind() == std::io::ErrorKind::PermissionDenied
188
- && p.file_name().and_then(std::ffi::OsStr::to_str)
189
- == Some("bootstrap.exe") =>
190
- {
191
- eprintln!("WARNING: failed to delete '{}'.", p.display());
192
- Ok(())
193
- }
194
- r => r,
195
- });
196
-
197
- return;
198
- }
199
-
200
- for file in t!(fs::read_dir(path)) {
201
- rm_rf(&t!(file).path());
202
- }
203
-
204
- do_op(path, "remove dir", |p| match fs::remove_dir(p) {
205
- // Check for dir not empty on Windows
206
- // FIXME: Once `ErrorKind::DirectoryNotEmpty` is stabilized,
207
- // match on `e.kind()` instead.
208
- #[cfg(windows)]
209
- Err(e) if e.raw_os_error() == Some(145) => Ok(()),
210
- r => r,
211
- });
212
- }
213
- };
214
- }
215
-
216
- fn do_op<F>(path: &Path, desc: &str, mut f: F)
217
- where
218
- F: FnMut(&Path) -> io::Result<()>,
219
- {
220
- match f(path) {
221
- Ok(()) => {}
222
- // On windows we can't remove a readonly file, and git will often clone files as readonly.
223
- // As a result, we have some special logic to remove readonly files on windows.
224
- // This is also the reason that we can't use things like fs::remove_dir_all().
225
- #[cfg(windows)]
226
- Err(ref e) if e.kind() == ErrorKind::PermissionDenied => {
227
- let m = t!(path.symlink_metadata());
228
- let mut p = m.permissions();
229
- p.set_readonly(false);
230
- t!(fs::set_permissions(path, p));
231
- f(path).unwrap_or_else(|e| {
232
- // Delete symlinked directories on Windows
233
- if m.file_type().is_symlink() && path.is_dir() && fs::remove_dir(path).is_ok() {
234
- return;
235
- }
236
- panic!("failed to {} {}: {}", desc, path.display(), e);
237
- });
238
- }
239
- Err(e) => {
240
- panic!("failed to {} {}: {}", desc, path.display(), e);
241
- }
173
+ /// Wrapper for [`std::fs::remove_dir_all`] that panics on failure and prints the `path` we failed
174
+ /// on.
175
+ fn remove_dir_recursive<P: AsRef<Path>>(path: P) {
176
+ let path = path.as_ref();
177
+ if let Err(e) = fs::remove_dir_all(path) {
178
+ panic!("failed to `remove_dir_all` at `{}`: {e}", path.display());
242
179
}
243
180
}
0 commit comments