Skip to content

Commit

Permalink
Change ubi so it only creates the install directory once it's downloa…
Browse files Browse the repository at this point in the history
…ded an asset
  • Loading branch information
autarch committed Dec 26, 2024
1 parent b8a6381 commit bd5add3
Show file tree
Hide file tree
Showing 6 changed files with 64 additions and 24 deletions.
9 changes: 9 additions & 0 deletions Cargo.lock

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

2 changes: 2 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ binstall-tar = "0.4.42"
bzip2 = "0.5.0"
clap = { version = "4.5.23", features = ["wrap_help"] }
document-features = "0.2"
# Used in some test code which can't use test_log.
env_logger = "0.11.6"
fern = { version = "0.7.1", features = ["colored"] }
flate2 = "1.0.35"
itertools = "0.13.0"
Expand Down
4 changes: 4 additions & 0 deletions Changes.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@

- The `UbiBuilder::install_dir` method now takes `AsRef<Path>` instead of `PathBuf`, which should
make it more convenient to use.
- Previously, `ubi` would create the install directory very early in its process, well before it had
something to install. This meant that if it failed to find an asset, couldn't download the asset,
or other errors happened, it would leave this directory behind. Now it creates this directory
immediately before writing the executable it found to disk.

## 0.3.0 - 2024-12-26

Expand Down
1 change: 1 addition & 0 deletions ubi/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ native-tls-vendored = ["reqwest/native-tls-vendored"]
logging = ["dep:fern"]

[dev-dependencies]
env_logger.workspace = true
fern.workspace = true
mockito.workspace = true
test-case.workspace = true
Expand Down
2 changes: 0 additions & 2 deletions ubi/src/builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ use reqwest::{
};
use std::{
env,
fs::create_dir_all,
path::{Path, PathBuf},
str::FromStr,
};
Expand Down Expand Up @@ -292,7 +291,6 @@ fn install_path(install_dir: Option<PathBuf>, exe: &str) -> Result<PathBuf> {
i.push("bin");
i
};
create_dir_all(&path)?;
path.push(exe);
debug!("install path = {}", path.to_string_lossy());
Ok(path)
Expand Down
70 changes: 48 additions & 22 deletions ubi/src/installer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use bzip2::read::BzDecoder;
use flate2::read::GzDecoder;
use log::{debug, info};
use std::{
fs::File,
fs::{create_dir_all, File},
io::{Read, Write},
path::{Path, PathBuf},
};
Expand Down Expand Up @@ -75,8 +75,10 @@ impl Installer {
if path.ends_with(&self.exe) {
let mut buffer: Vec<u8> = Vec::with_capacity(usize::try_from(zf.size())?);
zf.read_to_end(&mut buffer)?;
let mut file = File::create(&self.install_path)?;
return file.write_all(&buffer).map_err(Into::into);
self.create_install_dir()?;
return File::create(&self.install_path)?
.write_all(&buffer)
.map_err(Into::into);
}
}

Expand Down Expand Up @@ -108,10 +110,9 @@ impl Installer {
"extracting tarball entry to {}",
self.install_path.to_string_lossy(),
);
return match entry.unpack(&self.install_path) {
Ok(_) => Ok(()),
Err(e) => Err(anyhow::Error::new(e)),
};
self.create_install_dir()?;
entry.unpack(&self.install_path).unwrap();
return Ok(());
}
}
}
Expand Down Expand Up @@ -143,6 +144,7 @@ impl Installer {
}

fn write_to_install_path(&self, mut reader: impl Read) -> Result<()> {
self.create_install_dir()?;
let mut writer = File::create(&self.install_path)
.with_context(|| format!("Cannot write to {}", self.install_path.to_string_lossy()))?;
std::io::copy(&mut reader, &mut writer)?;
Expand All @@ -151,11 +153,25 @@ impl Installer {

fn copy_executable(&self, exe_file: &Path) -> Result<()> {
debug!("copying binary to final location");
self.create_install_dir()?;
std::fs::copy(exe_file, &self.install_path)?;

Ok(())
}

fn create_install_dir(&self) -> Result<()> {
let Some(path) = self.install_path.parent() else {
return Err(anyhow!(
"install path at {} has no parent",
self.install_path.display()
));
};

debug!("creating directory at {}", path.display());
create_dir_all(&path)
.with_context(|| format!("could not create a directory at {}", path.display()))
}

fn make_binary_executable(&self) -> Result<()> {
#[cfg(target_family = "windows")]
return Ok(());
Expand Down Expand Up @@ -200,6 +216,7 @@ mod tests {
use super::*;
#[cfg(target_family = "unix")]
use std::os::unix::fs::PermissionsExt;
use std::sync::Once;
use tempfile::tempdir;
use test_case::test_case;

Expand All @@ -216,23 +233,32 @@ mod tests {
#[test_case("test-data/project.zip", "project")]
#[test_case("test-data/project", "project")]
fn install(archive_path: &str, exe: &str) -> Result<()> {
//crate::ubi::init_logger(log::LevelFilter::Debug)?;
static INIT_LOGGING: Once = Once::new();
INIT_LOGGING.call_once(|| {
use env_logger;
let _ = env_logger::builder().is_test(true).try_init();
});

let td = tempdir()?;
let mut install_path = td.path().to_path_buf();
install_path.push("project");
let installer = Installer::new(install_path.clone(), exe.to_string());
installer.install(&Download {
// It doesn't matter what we use here. We're not actually going to
// put anything in this temp dir.
_temp_dir: tempdir()?,
archive_path: PathBuf::from(archive_path),
})?;

assert!(install_path.exists());
assert!(install_path.is_file());
#[cfg(target_family = "unix")]
assert!(install_path.metadata()?.permissions().mode() & 0o111 != 0);
let mut path_without_subdir = td.path().to_path_buf();
path_without_subdir.push("project");
let mut path_with_subdir = td.path().to_path_buf();
path_with_subdir.extend(&["subdir", "project"]);

for install_path in [path_without_subdir, path_with_subdir] {
let installer = Installer::new(install_path.clone(), exe.to_string());
installer.install(&Download {
// It doesn't matter what we use here. We're not actually going to
// put anything in this temp dir.
_temp_dir: tempdir()?,
archive_path: PathBuf::from(archive_path),
})?;

assert!(install_path.exists());
assert!(install_path.is_file());
#[cfg(target_family = "unix")]
assert!(install_path.metadata()?.permissions().mode() & 0o111 != 0);
}

Ok(())
}
Expand Down

0 comments on commit bd5add3

Please sign in to comment.