From e7daf1ab77d22cb5c6c17b65afd6aa86a01253d1 Mon Sep 17 00:00:00 2001 From: Samuel Moelius Date: Mon, 26 Aug 2024 13:44:17 -0400 Subject: [PATCH] Eliminate "text file busy" errors --- crates/svm-rs/Cargo.toml | 1 + crates/svm-rs/src/error.rs | 2 ++ crates/svm-rs/src/install.rs | 17 ++++++++++++++--- 3 files changed, 17 insertions(+), 3 deletions(-) diff --git a/crates/svm-rs/Cargo.toml b/crates/svm-rs/Cargo.toml index fc71caa..4348b59 100644 --- a/crates/svm-rs/Cargo.toml +++ b/crates/svm-rs/Cargo.toml @@ -35,6 +35,7 @@ semver = { workspace = true, features = ["serde"] } serde = { workspace = true, features = ["derive"] } serde_json.workspace = true sha2 = "0.10" +tempfile = "3.10" thiserror = "1.0" url = "2.5" diff --git a/crates/svm-rs/src/error.rs b/crates/svm-rs/src/error.rs index b4fd47c..2156d4d 100644 --- a/crates/svm-rs/src/error.rs +++ b/crates/svm-rs/src/error.rs @@ -26,6 +26,8 @@ pub enum SvmError { #[error(transparent)] IoError(#[from] std::io::Error), #[error(transparent)] + PersistError(#[from] tempfile::PathPersistError), + #[error(transparent)] ReqwestError(#[from] reqwest::Error), #[error(transparent)] SemverError(#[from] semver::Error), diff --git a/crates/svm-rs/src/install.rs b/crates/svm-rs/src/install.rs index a01d95f..370e816 100644 --- a/crates/svm-rs/src/install.rs +++ b/crates/svm-rs/src/install.rs @@ -11,6 +11,7 @@ use std::{ process::Command, time::Duration, }; +use tempfile::NamedTempFile; #[cfg(target_family = "unix")] use std::{fs::Permissions, os::unix::fs::PermissionsExt}; @@ -159,17 +160,27 @@ struct Installer<'a> { impl Installer<'_> { /// Installs the solc version at the version specific destination and returns the path to the installed solc file. fn install(self) -> Result { - let solc_path = version_binary(&self.version.to_string()); + let named_temp_file = NamedTempFile::new_in(data_dir())?; + let (mut f, temp_path) = named_temp_file.into_parts(); - let mut f = fs::File::create(&solc_path)?; #[cfg(target_family = "unix")] f.set_permissions(Permissions::from_mode(0o755))?; f.write_all(self.binbytes)?; if platform::is_nixos() && *self.version >= NIXOS_MIN_PATCH_VERSION { - patch_for_nixos(&solc_path)?; + patch_for_nixos(&temp_path)?; + } + + let solc_path = version_binary(&self.version.to_string()); + + // Windows requires that the old file be moved out of the way first. + if cfg!(target_os = "windows") { + let temp_path = NamedTempFile::new_in(data_dir()).map(NamedTempFile::into_temp_path)?; + fs::rename(&solc_path, &temp_path).unwrap_or_default(); } + temp_path.persist(&solc_path)?; + Ok(solc_path) }