Skip to content

Commit 4cb6d60

Browse files
authored
Merge pull request #1116 from pkgxdev/install-to-tmp
Install to tmpdir then atomic move
2 parents f5bc893 + 2c7ad18 commit 4cb6d60

File tree

3 files changed

+51
-11
lines changed

3 files changed

+51
-11
lines changed

Cargo.lock

Lines changed: 38 additions & 7 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

crates/lib/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ futures = "0.3.31"
3030
lazy_static = "1.5.0"
3131
nix = { version = "0.29.0", features = ["process"] }
3232
fs2 = "0.4.3"
33+
tempfile = "3.16.0"
3334

3435
[target.'cfg(not(target_os = "macos"))'.dependencies]
3536
rusqlite = { version = "0.32.1", features = ["bundled"] }

crates/lib/src/install.rs

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ use async_compression::tokio::bufread::XzDecoder;
22
use fs2::FileExt;
33
use reqwest::Client;
44
use std::{error::Error, fs::OpenOptions, path::PathBuf};
5+
use tempfile::tempdir_in;
56
use tokio::task;
67
use tokio_tar::Archive;
78

@@ -53,9 +54,9 @@ where
5354

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

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

96-
// Step 3: Extract the tar archive
97+
// Step 3: Make a temporary directory to extract the tarball into
98+
let temp_dir = tempdir_in(config.pkgx_dir.join(&pkg.project))?;
99+
100+
// Step 4: Extract the tar archive
97101
let mut archive = Archive::new(decoder);
98-
archive.unpack(&config.pkgx_dir).await?;
102+
archive.unpack(&temp_dir).await?;
103+
104+
// Step 5: atomically move from temp dir to installation location
105+
let partial_path = format!("{}/v{}", pkg.project, pkg.version.raw);
106+
fs::rename(temp_dir.into_path().join(&partial_path), &dst_path)?;
99107

100108
let installation = Installation {
101109
path: dst_path,

0 commit comments

Comments
 (0)