From 008b19caa0a4cabf3a209c0c9d52c6faf927c511 Mon Sep 17 00:00:00 2001 From: Sebastian Ullrich Date: Wed, 7 Feb 2024 12:48:39 +0100 Subject: [PATCH] fix: create toolchain directory atomically --- src/elan-dist/src/manifestation.rs | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/src/elan-dist/src/manifestation.rs b/src/elan-dist/src/manifestation.rs index 1e79d06..67f2859 100644 --- a/src/elan-dist/src/manifestation.rs +++ b/src/elan-dist/src/manifestation.rs @@ -76,6 +76,9 @@ impl Manifestation { notify_handler(Notification::InstallingComponent("lean")); + // unpack into temporary place, then move atomically to guard against aborts during unpacking + let unpack_dir = prefix.with_extension("tmp"); + // Remove old files if utils::is_directory(prefix) { utils::remove_dir("toolchain directory", prefix, &|n| { @@ -83,21 +86,29 @@ impl Manifestation { })?; } - utils::ensure_dir_exists("toolchain directory", prefix, &|n| { + if utils::is_directory(&unpack_dir) { + utils::remove_dir("temp toolchain directory", &unpack_dir, &|n| { + (notify_handler)(n.into()) + })?; + } + + utils::ensure_dir_exists("temp toolchain directory", &unpack_dir, &|n| { (notify_handler)(n.into()) })?; // Extract new files if url.ends_with(".tar.gz") { - TarGzPackage::unpack_file(&installer_file, prefix)? + TarGzPackage::unpack_file(&installer_file, &unpack_dir)? } else if url.ends_with(".tar.zst") { - TarZstdPackage::unpack_file(&installer_file, prefix)? + TarZstdPackage::unpack_file(&installer_file, &unpack_dir)? } else if url.ends_with(".zip") { - ZipPackage::unpack_file(&installer_file, prefix)? + ZipPackage::unpack_file(&installer_file, &unpack_dir)? } else { return Err(format!("unsupported archive format: {}", url).into()) } + utils::rename_dir("temp toolchain directory", &unpack_dir, prefix)?; + Ok(()) } }