Skip to content

Commit 605af72

Browse files
committed
build_helper: try to rename dir before delete
1 parent 49e5e4e commit 605af72

File tree

4 files changed

+35
-1
lines changed

4 files changed

+35
-1
lines changed

Cargo.lock

+1
Original file line numberDiff line numberDiff line change
@@ -332,6 +332,7 @@ dependencies = [
332332
name = "build_helper"
333333
version = "0.1.0"
334334
dependencies = [
335+
"fastrand",
335336
"serde",
336337
"serde_derive",
337338
]

src/bootstrap/Cargo.lock

+7
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,7 @@ dependencies = [
8282
name = "build_helper"
8383
version = "0.1.0"
8484
dependencies = [
85+
"fastrand",
8586
"serde",
8687
"serde_derive",
8788
]
@@ -233,6 +234,12 @@ dependencies = [
233234
"windows-sys 0.52.0",
234235
]
235236

237+
[[package]]
238+
name = "fastrand"
239+
version = "2.3.0"
240+
source = "registry+https://github.com/rust-lang/crates.io-index"
241+
checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be"
242+
236243
[[package]]
237244
name = "fd-lock"
238245
version = "4.0.2"

src/build_helper/Cargo.toml

+1
Original file line numberDiff line numberDiff line change
@@ -6,5 +6,6 @@ edition = "2021"
66
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
77

88
[dependencies]
9+
fastrand = "2.3.0"
910
serde = "1"
1011
serde_derive = "1"

src/build_helper/src/fs/mod.rs

+26-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
//! Misc filesystem related helpers for use by bootstrap and tools.
2+
use std::ffi::{OsStr, OsString};
23
use std::fs::Metadata;
34
use std::path::Path;
45
use std::{fs, io};
@@ -100,6 +101,30 @@ where
100101

101102
pub fn remove_and_create_dir_all<P: AsRef<Path>>(path: P) -> io::Result<()> {
102103
let path = path.as_ref();
103-
recursive_remove(path)?;
104+
105+
// Attempt to rename the directory in case removing fails.
106+
// We allow either the rename to fail or the remove to fail but not both.
107+
let rm_path = rand_name(path.as_os_str());
108+
if fs::rename(path, &rm_path).is_err() {
109+
// Rename failed, try to remove the original path
110+
recursive_remove(&path)?;
111+
} else {
112+
// Rename succeeded, try to remove the renamed path
113+
let _ = recursive_remove(&rm_path);
114+
}
104115
fs::create_dir_all(path)
105116
}
117+
118+
fn rand_name(prefix: &OsStr) -> OsString {
119+
let mut name: OsString = prefix.into();
120+
name.push("-");
121+
let mut rand_suffix = [0; 8];
122+
for n in rand_suffix.iter_mut() {
123+
*n = fastrand::alphanumeric() as u8;
124+
}
125+
// SAFETY: `fastrand::alphanumeric` only returns valid ascii.
126+
// Since an `OsStr` is a superset of UTF-8, ascii must be a valid `OsStr`.
127+
let ascii = unsafe { OsStr::from_encoded_bytes_unchecked(&rand_suffix) };
128+
name.push(ascii);
129+
name
130+
}

0 commit comments

Comments
 (0)