Skip to content

Commit 0a0fda5

Browse files
committed
Bootstrap: Retry copying/linking
1 parent 716752e commit 0a0fda5

File tree

2 files changed

+37
-12
lines changed

2 files changed

+37
-12
lines changed

src/bootstrap/src/lib.rs

+21-12
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ use filetime::FileTime;
3434
use sha2::digest::Digest;
3535
use termcolor::{ColorChoice, StandardStream, WriteColor};
3636
use utils::channel::GitInfo;
37-
use utils::helpers::hex_encode;
37+
use utils::helpers::{hex_encode, retry};
3838

3939
use crate::core::builder;
4040
use crate::core::builder::Kind;
@@ -1688,18 +1688,27 @@ impl Build {
16881688
return;
16891689
}
16901690
}
1691-
if let Ok(()) = fs::hard_link(&src, dst) {
1692-
// Attempt to "easy copy" by creating a hard link
1693-
// (symlinks don't work on windows), but if that fails
1694-
// just fall back to a slow `copy` operation.
1695-
} else {
1696-
if let Err(e) = fs::copy(&src, dst) {
1697-
panic!("failed to copy `{}` to `{}`: {}", src.display(), dst.display(), e)
1691+
// workaround for https://github.com/rust-lang/rust/issues/127126
1692+
// retry linking or copying up to 10 times or until success.
1693+
let result = retry(10, || {
1694+
if let Ok(()) = fs::hard_link(&src, dst) {
1695+
// Attempt to "easy copy" by creating a hard link
1696+
// (symlinks don't work on windows), but if that fails
1697+
// just fall back to a slow `copy` operation.
1698+
return Ok(());
1699+
} else {
1700+
if let Err(e) = fs::copy(&src, dst) {
1701+
return Err(e);
1702+
}
1703+
t!(fs::set_permissions(dst, metadata.permissions()));
1704+
let atime = FileTime::from_last_access_time(&metadata);
1705+
let mtime = FileTime::from_last_modification_time(&metadata);
1706+
t!(filetime::set_file_times(dst, atime, mtime));
1707+
return Ok(());
16981708
}
1699-
t!(fs::set_permissions(dst, metadata.permissions()));
1700-
let atime = FileTime::from_last_access_time(&metadata);
1701-
let mtime = FileTime::from_last_modification_time(&metadata);
1702-
t!(filetime::set_file_times(dst, atime, mtime));
1709+
});
1710+
if let Err(e) = result {
1711+
panic!("failed to copy `{}` to `{}`: {}", src.display(), dst.display(), e)
17031712
}
17041713
}
17051714

src/bootstrap/src/utils/helpers.rs

+16
Original file line numberDiff line numberDiff line change
@@ -517,3 +517,19 @@ pub fn git(source_dir: Option<&Path>) -> Command {
517517

518518
git
519519
}
520+
521+
/// Retry a function up to n times, returning the last call to fun.
522+
/// Stops early if the function returns `Ok`.
523+
pub fn retry<T, E>(n: usize, mut fun: impl FnMut() -> Result<T, E>) -> Result<T, E> {
524+
let mut retries = 0;
525+
loop {
526+
retries += 1;
527+
528+
let result = fun();
529+
if result.is_ok() || retries == n {
530+
return result;
531+
}
532+
// wait an arbitrary length of time.
533+
std::thread::sleep(std::time::Duration::from_secs(1));
534+
}
535+
}

0 commit comments

Comments
 (0)