use sha2::{Digest, Sha256};
use std::io::Write;
use std::path::{Path, PathBuf};
use std::sync::OnceLock;
pub const BUNDLED_VERSION: &str = env!("BOMBADIL_UV_VERSION");
pub const UV_LICENSE: &str = include_str!("../UV-LICENSE-APACHE");
const EXE_NAME: &str = env!("BOMBADIL_UV_EXE_NAME");
const UV_BYTES: &[u8] = include_bytes!(concat!(env!("OUT_DIR"), "/", env!("BOMBADIL_UV_EXE_NAME")));
#[derive(Debug, thiserror::Error)]
pub enum ExtractError {
#[error("could not write the bundled uv to {path}: {source}")]
Io {
path: PathBuf,
#[source]
source: std::io::Error,
},
}
fn hex(bytes: &[u8]) -> String {
bytes.iter().map(|b| format!("{b:02x}")).collect()
}
fn embedded_digest() -> &'static [u8] {
static DIGEST: OnceLock<Vec<u8>> = OnceLock::new();
DIGEST.get_or_init(|| Sha256::digest(UV_BYTES).to_vec())
}
pub fn extraction_path(data_dir: &Path) -> PathBuf {
let digest = hex(embedded_digest());
data_dir
.join("uv")
.join(format!("{BUNDLED_VERSION}-{}", &digest[..12]))
.join(EXE_NAME)
}
pub fn ensure_extracted(data_dir: &Path) -> Result<PathBuf, ExtractError> {
let path = extraction_path(data_dir);
if let Ok(existing) = std::fs::read(&path)
&& Sha256::digest(&existing).as_slice() == embedded_digest()
{
return Ok(path);
}
let parent = path.parent().expect("extraction path always has a parent");
std::fs::create_dir_all(parent).map_err(|source| ExtractError::Io {
path: parent.to_path_buf(),
source,
})?;
let mut tmp = tempfile::NamedTempFile::new_in(parent).map_err(|source| ExtractError::Io {
path: parent.to_path_buf(),
source,
})?;
let tmp_path = tmp.path().to_path_buf();
tmp.write_all(UV_BYTES).map_err(|source| ExtractError::Io {
path: tmp_path.clone(),
source,
})?;
#[cfg(unix)]
{
use std::os::unix::fs::PermissionsExt;
tmp.as_file()
.set_permissions(std::fs::Permissions::from_mode(0o755))
.map_err(|source| ExtractError::Io {
path: tmp_path.clone(),
source,
})?;
}
tmp.persist(&path).map_err(|e| ExtractError::Io {
path: tmp_path,
source: e.error,
})?;
Ok(path)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn the_embedded_binary_is_not_empty() {
assert!(UV_BYTES.len() > 1_000_000, "got {} bytes", UV_BYTES.len());
}
#[test]
fn the_uv_license_is_present_and_looks_like_apache_2() {
assert!(!UV_LICENSE.is_empty());
assert!(UV_LICENSE.contains("Apache License"), "got:\n{UV_LICENSE}");
}
#[test]
fn extraction_writes_a_runnable_file() {
let dir = tempfile::tempdir().unwrap();
let path = ensure_extracted(dir.path()).unwrap();
assert!(path.exists());
assert_eq!(std::fs::read(&path).unwrap().len(), UV_BYTES.len());
#[cfg(unix)]
{
use std::os::unix::fs::PermissionsExt;
let mode = std::fs::metadata(&path).unwrap().permissions().mode();
assert_eq!(mode & 0o111, 0o111, "extracted uv must be executable");
}
}
#[test]
fn a_second_extraction_reuses_the_first() {
let dir = tempfile::tempdir().unwrap();
let first = ensure_extracted(dir.path()).unwrap();
let second = ensure_extracted(dir.path()).unwrap();
assert_eq!(first, second);
}
#[test]
fn extraction_is_atomic_no_temp_file_survives_and_permissions_are_already_set() {
let dir = tempfile::tempdir().unwrap();
let path = ensure_extracted(dir.path()).unwrap();
assert!(path.exists());
#[cfg(unix)]
{
use std::os::unix::fs::PermissionsExt;
let mode = std::fs::metadata(&path).unwrap().permissions().mode();
assert_eq!(mode & 0o111, 0o111, "extracted uv must be executable");
}
let extraction_dir = path.parent().unwrap();
let entries: Vec<_> = std::fs::read_dir(extraction_dir)
.unwrap()
.map(|e| e.unwrap().file_name())
.collect();
assert_eq!(
entries.len(),
1,
"expected only the extracted binary, found {entries:?}"
);
}
#[test]
fn a_corrupted_extraction_is_repaired() {
let dir = tempfile::tempdir().unwrap();
let path = ensure_extracted(dir.path()).unwrap();
std::fs::write(&path, b"truncated").unwrap();
ensure_extracted(dir.path()).unwrap();
assert_eq!(std::fs::read(&path).unwrap().len(), UV_BYTES.len());
}
}