mirror of
https://github.com/astral-sh/uv.git
synced 2025-09-14 14:35:10 +00:00
Refactor hardlink fallback to use an enum (#401)
Makes an invalid state unrepresentable (`first_try_hard_linking = true`, `use_copy_fallback` = true`).
This commit is contained in:
parent
ff4d079dc9
commit
56a4b51eb6
1 changed files with 28 additions and 15 deletions
|
@ -367,14 +367,20 @@ fn hardlink_wheel_files(
|
||||||
site_packages: impl AsRef<Path>,
|
site_packages: impl AsRef<Path>,
|
||||||
wheel: impl AsRef<Path>,
|
wheel: impl AsRef<Path>,
|
||||||
) -> Result<usize, Error> {
|
) -> Result<usize, Error> {
|
||||||
let mut count = 0usize;
|
|
||||||
|
|
||||||
// Hard linking might not be supported but we (afaik) can't detect this ahead of time, so we'll
|
// Hard linking might not be supported but we (afaik) can't detect this ahead of time, so we'll
|
||||||
// try hard linking the first file, if this succeeds we'll know later hard linking errors are
|
// try hard linking the first file, if this succeeds we'll know later hard linking errors are
|
||||||
// not due to lack of os/fs support, if it fails we'll switch to copying for the rest of the
|
// not due to lack of os/fs support, if it fails we'll switch to copying for the rest of the
|
||||||
// install
|
// install
|
||||||
let mut first_try_hard_linking = true;
|
#[derive(Debug, Default, Clone, Copy)]
|
||||||
let mut use_copy_fallback = false;
|
enum Attempt {
|
||||||
|
#[default]
|
||||||
|
Initial,
|
||||||
|
Subsequent,
|
||||||
|
UseCopyFallback,
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut attempt = Attempt::default();
|
||||||
|
let mut count = 0usize;
|
||||||
|
|
||||||
// Walk over the directory.
|
// Walk over the directory.
|
||||||
for entry in walkdir::WalkDir::new(&wheel) {
|
for entry in walkdir::WalkDir::new(&wheel) {
|
||||||
|
@ -387,23 +393,30 @@ fn hardlink_wheel_files(
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Hardlink the file, unless it's the `RECORD` file, which we modify during installation.
|
// The `RECORD` file is modified during installation, so we copy it instead of hard-linking.
|
||||||
if entry.path().ends_with("RECORD") {
|
if entry.path().ends_with("RECORD") {
|
||||||
fs::copy(entry.path(), &out_path)?;
|
fs::copy(entry.path(), &out_path)?;
|
||||||
} else if use_copy_fallback {
|
count += 1;
|
||||||
fs::copy(entry.path(), &out_path)?;
|
continue;
|
||||||
} else {
|
}
|
||||||
let hard_link_result = fs::hard_link(entry.path(), &out_path);
|
|
||||||
|
// Fallback to copying if hardlinks aren't supported for this installation.
|
||||||
|
match attempt {
|
||||||
|
Attempt::Initial => {
|
||||||
// Once https://github.com/rust-lang/rust/issues/86442 is stable, use that
|
// Once https://github.com/rust-lang/rust/issues/86442 is stable, use that
|
||||||
if let Err(err) = hard_link_result {
|
if fs::hard_link(entry.path(), &out_path).is_err() {
|
||||||
if first_try_hard_linking {
|
|
||||||
fs::copy(entry.path(), &out_path)?;
|
fs::copy(entry.path(), &out_path)?;
|
||||||
use_copy_fallback = true;
|
attempt = Attempt::UseCopyFallback;
|
||||||
} else {
|
} else {
|
||||||
return Err(err.into());
|
attempt = Attempt::Subsequent;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
first_try_hard_linking = false;
|
Attempt::Subsequent => {
|
||||||
|
fs::hard_link(entry.path(), &out_path)?;
|
||||||
|
}
|
||||||
|
Attempt::UseCopyFallback => {
|
||||||
|
fs::copy(entry.path(), &out_path)?;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
count += 1;
|
count += 1;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue