Skip to content

Commit dd18b56

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

File tree

4 files changed

+32
-1
lines changed

4 files changed

+32
-1
lines changed

Diff for: 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
]

Diff for: 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"

Diff for: 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"

Diff for: src/build_helper/src/fs/mod.rs

+23-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,27 @@ 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 rand_suffix = [fastrand::alphanumeric() as u8; 8];
122+
// SAFETY: `fastrand::alphanumeric` only returns valid ascii.
123+
// Since an `OsStr` is a superset of UTF-8, ascii must be a valid `OsStr`.
124+
let ascii = unsafe { OsStr::from_encoded_bytes_unchecked(&rand_suffix) };
125+
name.push(ascii);
126+
name
127+
}

0 commit comments

Comments
 (0)