Skip to content

Commit

Permalink
Install to tmpdir then atomic move
Browse files Browse the repository at this point in the history
Refs #1100
  • Loading branch information
mxcl committed Feb 8, 2025
1 parent f5bc893 commit 7b5e998
Show file tree
Hide file tree
Showing 3 changed files with 51 additions and 11 deletions.
45 changes: 38 additions & 7 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions crates/lib/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ futures = "0.3.31"
lazy_static = "1.5.0"
nix = { version = "0.29.0", features = ["process"] }
fs2 = "0.4.3"
tempfile = "3.16.0"

[target.'cfg(not(target_os = "macos"))'.dependencies]
rusqlite = { version = "0.32.1", features = ["bundled"] }
16 changes: 12 additions & 4 deletions crates/lib/src/install.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ use async_compression::tokio::bufread::XzDecoder;
use fs2::FileExt;
use reqwest::Client;
use std::{error::Error, fs::OpenOptions, path::PathBuf};
use tempfile::{self, tempdir_in};
use tokio::task;
use tokio_tar::Archive;

Expand Down Expand Up @@ -53,9 +54,9 @@ where

let dst_path = cellar::dst(pkg, config);

// did another instance of pkx install us while we waited for the lock?
// did another instance of pkgx install us while we waited for the lock?
// if so, we’re good: eject
if fs::exists(dst_path.clone())? {
if dst_path.is_dir() {
FileExt::unlock(&shelf)?;
return Ok(Installation {
path: dst_path,
Expand Down Expand Up @@ -93,9 +94,16 @@ where
// Step 2: Create a XZ decoder
let decoder = XzDecoder::new(stream);

// Step 3: Extract the tar archive
// Step 3: Make a temporary directory to extract the tarball into
let temp_dir = tempdir_in(config.pkgx_dir.join(&pkg.project))?;

// Step 4: Extract the tar archive
let mut archive = Archive::new(decoder);
archive.unpack(&config.pkgx_dir).await?;
archive.unpack(&temp_dir).await?;

// Step 5: atomically move from temp dir to installation location
let partial_path = format!("{}/v{}", pkg.project, pkg.version.raw);
fs::rename(&temp_dir.into_path().join(&partial_path), &dst_path)?;

let installation = Installation {
path: dst_path,
Expand Down

0 comments on commit 7b5e998

Please sign in to comment.