From 35d6bd761b3a41bd7dca8a37824fc06e8a2022cb Mon Sep 17 00:00:00 2001 From: konsti Date: Mon, 30 Oct 2023 20:10:01 +0100 Subject: [PATCH] Fallback to copy if hardlinking failed (#237) --- crates/install-wheel-rs/src/linker.rs | 12 +++++++++++- crates/puffin-installer/src/installer.rs | 7 +++++-- 2 files changed, 16 insertions(+), 3 deletions(-) diff --git a/crates/install-wheel-rs/src/linker.rs b/crates/install-wheel-rs/src/linker.rs index 6856d8776..e702d98b5 100644 --- a/crates/install-wheel-rs/src/linker.rs +++ b/crates/install-wheel-rs/src/linker.rs @@ -361,6 +361,9 @@ fn hardlink_wheel_files( ) -> Result { let mut count = 0usize; + // Avoid causing the same error for every file + let mut use_copy_fallback = false; + // Walk over the directory. for entry in walkdir::WalkDir::new(&wheel) { let entry = entry?; @@ -375,8 +378,15 @@ fn hardlink_wheel_files( // Hardlink the file, unless it's the `RECORD` file, which we modify during installation. if entry.path().ends_with("RECORD") { fs::copy(entry.path(), &out_path)?; + } else if use_copy_fallback { + fs::copy(entry.path(), &out_path)?; } else { - fs::hard_link(entry.path(), &out_path)?; + let hard_link_result = fs::hard_link(entry.path(), &out_path); + // Once https://github.com/rust-lang/rust/issues/86442 is stable, use that + if hard_link_result.is_err() { + fs::copy(entry.path(), &out_path)?; + use_copy_fallback = true; + } } count += 1; diff --git a/crates/puffin-installer/src/installer.rs b/crates/puffin-installer/src/installer.rs index f8d7df607..b81b3fd43 100644 --- a/crates/puffin-installer/src/installer.rs +++ b/crates/puffin-installer/src/installer.rs @@ -1,4 +1,4 @@ -use anyhow::{Error, Result}; +use anyhow::{Context, Error, Result}; use rayon::iter::{IntoParallelRefIterator, ParallelIterator}; use pep440_rs::Version; @@ -47,7 +47,10 @@ impl<'a> Installer<'a> { self.venv.interpreter_info().simple_version(), ); - install_wheel_rs::linker::install_wheel(&location, wheel.path(), self.link_mode)?; + install_wheel_rs::linker::install_wheel(&location, wheel.path(), self.link_mode) + .with_context(|| { + format!("Failed to install {} {}", wheel.name(), wheel.version()) + })?; if let Some(reporter) = self.reporter.as_ref() { reporter.on_install_progress(wheel.name(), wheel.version());