diff --git a/.github/workflows/run-dev-tests.yml b/.github/workflows/run-dev-tests.yml index 4fc4c386..bc11211c 100644 --- a/.github/workflows/run-dev-tests.yml +++ b/.github/workflows/run-dev-tests.yml @@ -5,6 +5,7 @@ on: branches: [main] paths: - cpp-linter/** + - clang-installer/** - Cargo.toml - Cargo.lock - .github/workflows/run-dev-tests.yml @@ -12,6 +13,7 @@ on: branches: [main] paths: - cpp-linter/** + - clang-installer/** - Cargo.toml - Cargo.lock - .github/workflows/run-dev-tests.yml diff --git a/clang-installer/Cargo.toml b/clang-installer/Cargo.toml index 8282c370..917c7f9a 100644 --- a/clang-installer/Cargo.toml +++ b/clang-installer/Cargo.toml @@ -36,12 +36,12 @@ tokio = { workspace = true, features = ["macros"], optional = true } url = "2.5.8" which = "8.0.2" zip = { version = "8.6.0", default-features = false, features = ["deflate"] } -tempfile = { workspace = true } [dev-dependencies] colored = { workspace = true } mockito = { workspace = true } reqwest = { workspace = true, features = ["default-tls"] } +tempfile = { workspace = true } tokio = { workspace = true, features = ["macros", "rt-multi-thread"] } [features] diff --git a/clang-installer/src/downloader/mod.rs b/clang-installer/src/downloader/mod.rs index 78de368f..a288548d 100644 --- a/clang-installer/src/downloader/mod.rs +++ b/clang-installer/src/downloader/mod.rs @@ -31,9 +31,9 @@ pub enum DownloadError { #[error("Hash mismatch for downloaded file. Expected: {expected}, Actual: {actual}")] HashMismatch { expected: String, actual: String }, - /// An error that occurred while moving/persisting a temporary file into a cache path. - #[error("Error persisting temporary file: {0}")] - TempFilePersistence(#[from] tempfile::PersistError), + /// An error that occurred while creating or persisting a temporary file into a cache path. + #[error("Error when {0}: {1}")] + TempFile(&'static str, #[source] std::io::Error), } /// Downloads data from the specified URL and returns the response. @@ -58,7 +58,15 @@ async fn download(url: &Url, cache_path: &Path, timeout: u64) -> Result<(), Down } return Err(e.into()); } - let mut tmp_file = tempfile::NamedTempFile::new()?; + let tmp_file_path = cache_path.with_extension("tmp"); + let mut tmp_file = fs::OpenOptions::new() + .write(true) + .truncate(true) + .create(true) + .open(&tmp_file_path) + .map_err(|e| { + DownloadError::TempFile("creating temporary file for download placeholder", e) + })?; let content_len = response.content_length().and_then(NonZero::new); let mut progress_bar = ProgressBar::new( content_len, @@ -79,8 +87,10 @@ async fn download(url: &Url, cache_path: &Path, timeout: u64) -> Result<(), Down } progress_bar.finish()?; tmp_file.flush()?; - tmp_file.as_file_mut().set_modified(SystemTime::now())?; - tmp_file.persist(cache_path)?; + tmp_file.set_modified(SystemTime::now())?; + drop(tmp_file); // ensure the file is closed before renaming + fs::rename(tmp_file_path, cache_path) + .map_err(|e| DownloadError::TempFile("renaming temporary file after download", e))?; Ok(()) }