From de9e85978b73f70f3c94452ab12e96ec0ff98b3b Mon Sep 17 00:00:00 2001 From: konsti Date: Thu, 12 Oct 2023 20:47:38 +0200 Subject: [PATCH] Fix tempdir rename (#94) This fixes two bugs on linux: `/tmp` and `$HOME` are technically on two different partitions on my machine, which means that rename-as-atomic-dir-write doesn't work. The solution is to create the temp dir in the target directory. zip files may contain directory entries, we can't create files for them but need to create directories. We could skip them though because iirc they are not in the RECORD so they won't be uninstalled. --- crates/puffin-installer/src/cache.rs | 15 ++++++++++----- crates/puffin-installer/src/unzipper.rs | 6 +++++- 2 files changed, 15 insertions(+), 6 deletions(-) diff --git a/crates/puffin-installer/src/cache.rs b/crates/puffin-installer/src/cache.rs index 2ddb79d7b..b7d43e823 100644 --- a/crates/puffin-installer/src/cache.rs +++ b/crates/puffin-installer/src/cache.rs @@ -4,29 +4,34 @@ static WHEEL_CACHE: &str = "wheels-v0"; #[derive(Debug)] pub(crate) struct WheelCache { - path: PathBuf, + root: PathBuf, } impl WheelCache { /// Create a handle to the wheel cache. pub(crate) fn new(root: &Path) -> Self { Self { - path: root.join(WHEEL_CACHE), + root: root.join(WHEEL_CACHE), } } /// Return the path at which a given wheel would be stored. pub(crate) fn entry(&self, id: &str) -> PathBuf { - self.path.join(id) + self.root.join(id) } /// Initialize the wheel cache. pub(crate) async fn init(&self) -> std::io::Result<()> { - tokio::fs::create_dir_all(&self.path).await + tokio::fs::create_dir_all(&self.root).await } /// Returns a handle to the wheel cache directory. pub(crate) async fn read_dir(&self) -> std::io::Result { - tokio::fs::read_dir(&self.path).await + tokio::fs::read_dir(&self.root).await + } + + /// Returns the cache root. + pub(crate) fn root(&self) -> &Path { + &self.root } } diff --git a/crates/puffin-installer/src/unzipper.rs b/crates/puffin-installer/src/unzipper.rs index 810d38f40..cdf46c075 100644 --- a/crates/puffin-installer/src/unzipper.rs +++ b/crates/puffin-installer/src/unzipper.rs @@ -38,7 +38,7 @@ impl Unzipper { let wheel_cache = WheelCache::new(target); wheel_cache.init().await?; - let staging = tempfile::tempdir()?; + let staging = tempfile::tempdir_in(wheel_cache.root())?; // Unpack the wheels into the cache. let mut wheels = Vec::with_capacity(downloads.len()); @@ -101,6 +101,10 @@ fn unzip_wheel(wheel: InMemoryDistribution, target: &Path) -> Result<()> { // Create necessary parent directories. let path = target.join(file_path); + if file.is_dir() { + std::fs::create_dir_all(path)?; + return Ok(()); + } if let Some(parent) = path.parent() { std::fs::create_dir_all(parent)?; }