Skip to content

Commit

Permalink
Merge pull request #115 from theseus-rs/archive-extract-signature
Browse files Browse the repository at this point in the history
refactor!: return list of files from archive extract function
  • Loading branch information
brianheineman authored Aug 4, 2024
2 parents 0c892df + 2b0fc97 commit 458c9c7
Show file tree
Hide file tree
Showing 9 changed files with 50 additions and 30 deletions.
4 changes: 2 additions & 2 deletions postgresql_archive/src/archive.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
use crate::error::Result;
use crate::{extractor, repository};
use semver::{Version, VersionReq};
use std::path::Path;
use std::path::{Path, PathBuf};
use tracing::instrument;

/// Gets the version for the specified [version requirement](VersionReq). If a version for the
Expand Down Expand Up @@ -41,7 +41,7 @@ pub async fn get_archive(url: &str, version_req: &VersionReq) -> Result<(Version
/// Returns an error if the extraction fails.
#[allow(clippy::cast_precision_loss)]
#[instrument(skip(bytes))]
pub async fn extract(url: &str, bytes: &Vec<u8>, out_dir: &Path) -> Result<()> {
pub async fn extract(url: &str, bytes: &Vec<u8>, out_dir: &Path) -> Result<Vec<PathBuf>> {
let extractor_fn = extractor::registry::get(url)?;
extractor_fn(bytes, out_dir)
}
Expand Down
4 changes: 2 additions & 2 deletions postgresql_archive/src/blocking/archive.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use crate::{Version, VersionReq};
use std::path::Path;
use std::path::{Path, PathBuf};
use std::sync::LazyLock;
use tokio::runtime::Runtime;

Expand Down Expand Up @@ -33,7 +33,7 @@ pub fn get_archive(url: &str, version_req: &VersionReq) -> crate::Result<(Versio
///
/// # Errors
/// Returns an error if the extraction fails.
pub fn extract(url: &str, bytes: &Vec<u8>, out_dir: &Path) -> crate::Result<()> {
pub fn extract(url: &str, bytes: &Vec<u8>, out_dir: &Path) -> crate::Result<Vec<PathBuf>> {
RUNTIME
.handle()
.block_on(async move { crate::extract(url, bytes, out_dir).await })
Expand Down
17 changes: 9 additions & 8 deletions postgresql_archive/src/configuration/theseus/extractor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,11 @@ use tracing::{debug, instrument, warn};
/// Returns an error if the extraction fails.
#[allow(clippy::cast_precision_loss)]
#[instrument(skip(bytes))]
pub fn extract(bytes: &Vec<u8>, out_dir: &Path) -> Result<()> {
pub fn extract(bytes: &Vec<u8>, out_dir: &Path) -> Result<Vec<PathBuf>> {
let mut files = Vec::new();
let input = BufReader::new(Cursor::new(bytes));
let decoder = GzDecoder::new(input);
let mut archive = Archive::new(decoder);
let mut files = 0;
let mut extracted_bytes = 0;

let parent_dir = if let Some(parent) = out_dir.parent() {
Expand All @@ -42,7 +42,7 @@ pub fn extract(bytes: &Vec<u8>, out_dir: &Path) -> Result<()> {
out_dir.to_string_lossy()
);
remove_file(&lock_file)?;
return Ok(());
return Ok(files);
}

let extract_dir = tempfile::tempdir_in(parent_dir)?.into_path();
Expand Down Expand Up @@ -74,20 +74,20 @@ pub fn extract(bytes: &Vec<u8>, out_dir: &Path) -> Result<()> {
} else if entry_type.is_file() {
let mut output_file = File::create(&entry_name)?;
copy(&mut entry, &mut output_file)?;

files += 1;
extracted_bytes += entry_size;

#[cfg(unix)]
{
use std::os::unix::fs::PermissionsExt;
output_file.set_permissions(std::fs::Permissions::from_mode(file_mode))?;
}
files.push(entry_name);
} else if entry_type.is_symlink() {
#[cfg(unix)]
if let Some(symlink_target) = entry.link_name()? {
let symlink_path = entry_name;
let symlink_path = entry_name.clone();
std::os::unix::fs::symlink(symlink_target.as_ref(), symlink_path)?;
files.push(entry_name);
}
}
}
Expand All @@ -113,13 +113,14 @@ pub fn extract(bytes: &Vec<u8>, out_dir: &Path) -> Result<()> {
remove_file(lock_file)?;
}

let number_of_files = files.len();
debug!(
"Extracting {} files totalling {}",
files.to_formatted_string(&Locale::en),
number_of_files.to_formatted_string(&Locale::en),
human_bytes(extracted_bytes as f64)
);

Ok(())
Ok(files)
}

/// Acquires a lock file in the [out_dir](Path) to prevent multiple processes from extracting the
Expand Down
17 changes: 9 additions & 8 deletions postgresql_archive/src/configuration/zonky/extractor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,8 @@ use zip::ZipArchive;
#[allow(clippy::case_sensitive_file_extension_comparisons)]
#[allow(clippy::cast_precision_loss)]
#[instrument(skip(bytes))]
pub fn extract(bytes: &Vec<u8>, out_dir: &Path) -> Result<()> {
pub fn extract(bytes: &Vec<u8>, out_dir: &Path) -> Result<Vec<PathBuf>> {
let mut files = Vec::new();
let parent_dir = if let Some(parent) = out_dir.parent() {
parent
} else {
Expand All @@ -38,7 +39,7 @@ pub fn extract(bytes: &Vec<u8>, out_dir: &Path) -> Result<()> {
out_dir.to_string_lossy()
);
remove_file(&lock_file)?;
return Ok(());
return Ok(files);
}

let extract_dir = tempfile::tempdir_in(parent_dir)?.into_path();
Expand Down Expand Up @@ -66,7 +67,6 @@ pub fn extract(bytes: &Vec<u8>, out_dir: &Path) -> Result<()> {
let input = BufReader::new(Cursor::new(archive_bytes));
let decoder = XzDecoder::new(input);
let mut archive = Archive::new(decoder);
let mut files = 0;
let mut extracted_bytes = 0;

for archive_entry in archive.entries()? {
Expand All @@ -92,20 +92,20 @@ pub fn extract(bytes: &Vec<u8>, out_dir: &Path) -> Result<()> {
} else if entry_type.is_file() {
let mut output_file = File::create(&entry_name)?;
copy(&mut entry, &mut output_file)?;

files += 1;
extracted_bytes += entry_size;

#[cfg(unix)]
{
use std::os::unix::fs::PermissionsExt;
output_file.set_permissions(std::fs::Permissions::from_mode(file_mode))?;
}
files.push(entry_name);
} else if entry_type.is_symlink() {
#[cfg(unix)]
if let Some(symlink_target) = entry.link_name()? {
let symlink_path = entry_name;
let symlink_path = entry_name.clone();
std::os::unix::fs::symlink(symlink_target.as_ref(), symlink_path)?;
files.push(entry_name);
}
}
}
Expand All @@ -131,13 +131,14 @@ pub fn extract(bytes: &Vec<u8>, out_dir: &Path) -> Result<()> {
remove_file(lock_file)?;
}

let number_of_files = files.len();
debug!(
"Extracting {} files totalling {}",
files.to_formatted_string(&Locale::en),
number_of_files.to_formatted_string(&Locale::en),
human_bytes(extracted_bytes as f64)
);

Ok(())
Ok(files)
}

/// Acquires a lock file in the [out_dir](Path) to prevent multiple processes from extracting the
Expand Down
6 changes: 3 additions & 3 deletions postgresql_archive/src/extractor/registry.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,14 @@ use crate::configuration::theseus;
use crate::configuration::zonky;
use crate::Error::{PoisonedLock, UnsupportedExtractor};
use crate::Result;
use std::path::Path;
use std::path::{Path, PathBuf};
use std::sync::{Arc, LazyLock, Mutex, RwLock};

static REGISTRY: LazyLock<Arc<Mutex<RepositoryRegistry>>> =
LazyLock::new(|| Arc::new(Mutex::new(RepositoryRegistry::default())));

type SupportsFn = fn(&str) -> Result<bool>;
type ExtractFn = fn(&Vec<u8>, &Path) -> Result<()>;
type ExtractFn = fn(&Vec<u8>, &Path) -> Result<Vec<PathBuf>>;

/// Singleton struct to store extractors
#[allow(clippy::type_complexity)]
Expand Down Expand Up @@ -102,7 +102,7 @@ mod tests {

#[test]
fn test_register() -> Result<()> {
register(|url| Ok(url == "https://foo.com"), |_, _| Ok(()))?;
register(|url| Ok(url == "https://foo.com"), |_, _| Ok(Vec::new()))?;
let url = "https://foo.com";
let extractor = get(url)?;
assert!(extractor(&Vec::new(), Path::new("foo")).is_ok());
Expand Down
3 changes: 2 additions & 1 deletion postgresql_archive/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,8 @@
//! let url = theseus::URL;
//! let (archive_version, archive) = get_archive(url, &VersionReq::STAR).await?;
//! let out_dir = std::env::temp_dir();
//! extract(url, &archive, &out_dir).await
//! let files = extract(url, &archive, &out_dir).await?;
//! Ok(())
//! }
//! ```
//!
Expand Down
12 changes: 10 additions & 2 deletions postgresql_archive/tests/archive.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,13 +26,21 @@ async fn test_get_version() -> anyhow::Result<()> {
#[test(tokio::test)]
async fn test_get_archive_and_extract() -> anyhow::Result<()> {
let url = theseus::URL;
let version_req = VersionReq::STAR;
let version_req = VersionReq::parse("=16.3.0")?;
let (archive_version, archive) = get_archive(url, &version_req).await?;

assert!(version_req.matches(&archive_version));

let out_dir = tempfile::tempdir()?.path().to_path_buf();
extract(url, &archive, &out_dir).await?;
let files = extract(url, &archive, &out_dir).await?;
#[cfg(all(target_os = "linux", target_arch = "x86_64"))]
assert_eq!(1_312, files.len());
#[cfg(all(target_os = "macos", target_arch = "aarch64"))]
assert_eq!(1_271, files.len());
#[cfg(all(target_os = "macos", target_arch = "x86_64"))]
assert_eq!(1_271, files.len());
#[cfg(all(target_os = "windows", target_arch = "x86_64"))]
assert_eq!(3_120, files.len());
remove_dir_all(&out_dir)?;
Ok(())
}
Expand Down
5 changes: 3 additions & 2 deletions postgresql_archive/tests/blocking.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,13 +24,14 @@ fn test_get_version() -> anyhow::Result<()> {
#[allow(deprecated)]
fn test_get_archive_and_extract() -> anyhow::Result<()> {
let url = theseus::URL;
let version_req = &VersionReq::STAR;
let version_req = &VersionReq::parse("=16.3.0")?;
let (archive_version, archive) = get_archive(url, version_req)?;

assert!(version_req.matches(&archive_version));

let out_dir = tempfile::tempdir()?.path().to_path_buf();
extract(url, &archive, &out_dir)?;
let files = extract(url, &archive, &out_dir)?;
assert!(!files.is_empty());
remove_dir_all(&out_dir)?;
Ok(())
}
12 changes: 10 additions & 2 deletions postgresql_archive/tests/zonky.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,13 +35,21 @@ async fn test_get_version() -> anyhow::Result<()> {
#[cfg(feature = "zonky")]
async fn test_get_archive_and_extract() -> anyhow::Result<()> {
let url = zonky::URL;
let version_req = VersionReq::STAR;
let version_req = VersionReq::parse("=16.3.0")?;
let (archive_version, archive) = get_archive(url, &version_req).await?;

assert!(version_req.matches(&archive_version));

let out_dir = tempfile::tempdir()?.path().to_path_buf();
extract(url, &archive, &out_dir).await?;
let files = extract(url, &archive, &out_dir).await?;
#[cfg(all(target_os = "linux", target_arch = "x86_64"))]
assert_eq!(1_023, files.len());
#[cfg(all(target_os = "macos", target_arch = "aarch64"))]
assert_eq!(1_019, files.len());
#[cfg(all(target_os = "macos", target_arch = "x86_64"))]
assert_eq!(1_019, files.len());
#[cfg(all(target_os = "windows", target_arch = "x86_64"))]
assert_eq!(1_019, files.len());
remove_dir_all(&out_dir)?;
Ok(())
}
Expand Down

0 comments on commit 458c9c7

Please sign in to comment.