@@ -2,6 +2,7 @@ use async_compression::tokio::bufread::XzDecoder;
22use fs2:: FileExt ;
33use reqwest:: Client ;
44use std:: { error:: Error , fs:: OpenOptions , path:: PathBuf } ;
5+ use tempfile:: tempdir_in;
56use tokio:: task;
67use tokio_tar:: Archive ;
78
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,
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