Skip to content

Commit 458c9c7

Browse files
Merge pull request #115 from theseus-rs/archive-extract-signature
refactor!: return list of files from archive extract function
2 parents 0c892df + 2b0fc97 commit 458c9c7

File tree

9 files changed

+50
-30
lines changed

9 files changed

+50
-30
lines changed

postgresql_archive/src/archive.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
use crate::error::Result;
55
use crate::{extractor, repository};
66
use semver::{Version, VersionReq};
7-
use std::path::Path;
7+
use std::path::{Path, PathBuf};
88
use tracing::instrument;
99

1010
/// Gets the version for the specified [version requirement](VersionReq). If a version for the
@@ -41,7 +41,7 @@ pub async fn get_archive(url: &str, version_req: &VersionReq) -> Result<(Version
4141
/// Returns an error if the extraction fails.
4242
#[allow(clippy::cast_precision_loss)]
4343
#[instrument(skip(bytes))]
44-
pub async fn extract(url: &str, bytes: &Vec<u8>, out_dir: &Path) -> Result<()> {
44+
pub async fn extract(url: &str, bytes: &Vec<u8>, out_dir: &Path) -> Result<Vec<PathBuf>> {
4545
let extractor_fn = extractor::registry::get(url)?;
4646
extractor_fn(bytes, out_dir)
4747
}

postgresql_archive/src/blocking/archive.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
use crate::{Version, VersionReq};
2-
use std::path::Path;
2+
use std::path::{Path, PathBuf};
33
use std::sync::LazyLock;
44
use tokio::runtime::Runtime;
55

@@ -33,7 +33,7 @@ pub fn get_archive(url: &str, version_req: &VersionReq) -> crate::Result<(Versio
3333
///
3434
/// # Errors
3535
/// Returns an error if the extraction fails.
36-
pub fn extract(url: &str, bytes: &Vec<u8>, out_dir: &Path) -> crate::Result<()> {
36+
pub fn extract(url: &str, bytes: &Vec<u8>, out_dir: &Path) -> crate::Result<Vec<PathBuf>> {
3737
RUNTIME
3838
.handle()
3939
.block_on(async move { crate::extract(url, bytes, out_dir).await })

postgresql_archive/src/configuration/theseus/extractor.rs

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -17,11 +17,11 @@ use tracing::{debug, instrument, warn};
1717
/// Returns an error if the extraction fails.
1818
#[allow(clippy::cast_precision_loss)]
1919
#[instrument(skip(bytes))]
20-
pub fn extract(bytes: &Vec<u8>, out_dir: &Path) -> Result<()> {
20+
pub fn extract(bytes: &Vec<u8>, out_dir: &Path) -> Result<Vec<PathBuf>> {
21+
let mut files = Vec::new();
2122
let input = BufReader::new(Cursor::new(bytes));
2223
let decoder = GzDecoder::new(input);
2324
let mut archive = Archive::new(decoder);
24-
let mut files = 0;
2525
let mut extracted_bytes = 0;
2626

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

4848
let extract_dir = tempfile::tempdir_in(parent_dir)?.into_path();
@@ -74,20 +74,20 @@ pub fn extract(bytes: &Vec<u8>, out_dir: &Path) -> Result<()> {
7474
} else if entry_type.is_file() {
7575
let mut output_file = File::create(&entry_name)?;
7676
copy(&mut entry, &mut output_file)?;
77-
78-
files += 1;
7977
extracted_bytes += entry_size;
8078

8179
#[cfg(unix)]
8280
{
8381
use std::os::unix::fs::PermissionsExt;
8482
output_file.set_permissions(std::fs::Permissions::from_mode(file_mode))?;
8583
}
84+
files.push(entry_name);
8685
} else if entry_type.is_symlink() {
8786
#[cfg(unix)]
8887
if let Some(symlink_target) = entry.link_name()? {
89-
let symlink_path = entry_name;
88+
let symlink_path = entry_name.clone();
9089
std::os::unix::fs::symlink(symlink_target.as_ref(), symlink_path)?;
90+
files.push(entry_name);
9191
}
9292
}
9393
}
@@ -113,13 +113,14 @@ pub fn extract(bytes: &Vec<u8>, out_dir: &Path) -> Result<()> {
113113
remove_file(lock_file)?;
114114
}
115115

116+
let number_of_files = files.len();
116117
debug!(
117118
"Extracting {} files totalling {}",
118-
files.to_formatted_string(&Locale::en),
119+
number_of_files.to_formatted_string(&Locale::en),
119120
human_bytes(extracted_bytes as f64)
120121
);
121122

122-
Ok(())
123+
Ok(files)
123124
}
124125

125126
/// Acquires a lock file in the [out_dir](Path) to prevent multiple processes from extracting the

postgresql_archive/src/configuration/zonky/extractor.rs

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,8 @@ use zip::ZipArchive;
1919
#[allow(clippy::case_sensitive_file_extension_comparisons)]
2020
#[allow(clippy::cast_precision_loss)]
2121
#[instrument(skip(bytes))]
22-
pub fn extract(bytes: &Vec<u8>, out_dir: &Path) -> Result<()> {
22+
pub fn extract(bytes: &Vec<u8>, out_dir: &Path) -> Result<Vec<PathBuf>> {
23+
let mut files = Vec::new();
2324
let parent_dir = if let Some(parent) = out_dir.parent() {
2425
parent
2526
} else {
@@ -38,7 +39,7 @@ pub fn extract(bytes: &Vec<u8>, out_dir: &Path) -> Result<()> {
3839
out_dir.to_string_lossy()
3940
);
4041
remove_file(&lock_file)?;
41-
return Ok(());
42+
return Ok(files);
4243
}
4344

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

7272
for archive_entry in archive.entries()? {
@@ -92,20 +92,20 @@ pub fn extract(bytes: &Vec<u8>, out_dir: &Path) -> Result<()> {
9292
} else if entry_type.is_file() {
9393
let mut output_file = File::create(&entry_name)?;
9494
copy(&mut entry, &mut output_file)?;
95-
96-
files += 1;
9795
extracted_bytes += entry_size;
9896

9997
#[cfg(unix)]
10098
{
10199
use std::os::unix::fs::PermissionsExt;
102100
output_file.set_permissions(std::fs::Permissions::from_mode(file_mode))?;
103101
}
102+
files.push(entry_name);
104103
} else if entry_type.is_symlink() {
105104
#[cfg(unix)]
106105
if let Some(symlink_target) = entry.link_name()? {
107-
let symlink_path = entry_name;
106+
let symlink_path = entry_name.clone();
108107
std::os::unix::fs::symlink(symlink_target.as_ref(), symlink_path)?;
108+
files.push(entry_name);
109109
}
110110
}
111111
}
@@ -131,13 +131,14 @@ pub fn extract(bytes: &Vec<u8>, out_dir: &Path) -> Result<()> {
131131
remove_file(lock_file)?;
132132
}
133133

134+
let number_of_files = files.len();
134135
debug!(
135136
"Extracting {} files totalling {}",
136-
files.to_formatted_string(&Locale::en),
137+
number_of_files.to_formatted_string(&Locale::en),
137138
human_bytes(extracted_bytes as f64)
138139
);
139140

140-
Ok(())
141+
Ok(files)
141142
}
142143

143144
/// Acquires a lock file in the [out_dir](Path) to prevent multiple processes from extracting the

postgresql_archive/src/extractor/registry.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,14 @@ use crate::configuration::theseus;
44
use crate::configuration::zonky;
55
use crate::Error::{PoisonedLock, UnsupportedExtractor};
66
use crate::Result;
7-
use std::path::Path;
7+
use std::path::{Path, PathBuf};
88
use std::sync::{Arc, LazyLock, Mutex, RwLock};
99

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

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

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

103103
#[test]
104104
fn test_register() -> Result<()> {
105-
register(|url| Ok(url == "https://foo.com"), |_, _| Ok(()))?;
105+
register(|url| Ok(url == "https://foo.com"), |_, _| Ok(Vec::new()))?;
106106
let url = "https://foo.com";
107107
let extractor = get(url)?;
108108
assert!(extractor(&Vec::new(), Path::new("foo")).is_ok());

postgresql_archive/src/lib.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,8 @@
2929
//! let url = theseus::URL;
3030
//! let (archive_version, archive) = get_archive(url, &VersionReq::STAR).await?;
3131
//! let out_dir = std::env::temp_dir();
32-
//! extract(url, &archive, &out_dir).await
32+
//! let files = extract(url, &archive, &out_dir).await?;
33+
//! Ok(())
3334
//! }
3435
//! ```
3536
//!

postgresql_archive/tests/archive.rs

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,13 +26,21 @@ async fn test_get_version() -> anyhow::Result<()> {
2626
#[test(tokio::test)]
2727
async fn test_get_archive_and_extract() -> anyhow::Result<()> {
2828
let url = theseus::URL;
29-
let version_req = VersionReq::STAR;
29+
let version_req = VersionReq::parse("=16.3.0")?;
3030
let (archive_version, archive) = get_archive(url, &version_req).await?;
3131

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

3434
let out_dir = tempfile::tempdir()?.path().to_path_buf();
35-
extract(url, &archive, &out_dir).await?;
35+
let files = extract(url, &archive, &out_dir).await?;
36+
#[cfg(all(target_os = "linux", target_arch = "x86_64"))]
37+
assert_eq!(1_312, files.len());
38+
#[cfg(all(target_os = "macos", target_arch = "aarch64"))]
39+
assert_eq!(1_271, files.len());
40+
#[cfg(all(target_os = "macos", target_arch = "x86_64"))]
41+
assert_eq!(1_271, files.len());
42+
#[cfg(all(target_os = "windows", target_arch = "x86_64"))]
43+
assert_eq!(3_120, files.len());
3644
remove_dir_all(&out_dir)?;
3745
Ok(())
3846
}

postgresql_archive/tests/blocking.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,13 +24,14 @@ fn test_get_version() -> anyhow::Result<()> {
2424
#[allow(deprecated)]
2525
fn test_get_archive_and_extract() -> anyhow::Result<()> {
2626
let url = theseus::URL;
27-
let version_req = &VersionReq::STAR;
27+
let version_req = &VersionReq::parse("=16.3.0")?;
2828
let (archive_version, archive) = get_archive(url, version_req)?;
2929

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

3232
let out_dir = tempfile::tempdir()?.path().to_path_buf();
33-
extract(url, &archive, &out_dir)?;
33+
let files = extract(url, &archive, &out_dir)?;
34+
assert!(!files.is_empty());
3435
remove_dir_all(&out_dir)?;
3536
Ok(())
3637
}

postgresql_archive/tests/zonky.rs

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,13 +35,21 @@ async fn test_get_version() -> anyhow::Result<()> {
3535
#[cfg(feature = "zonky")]
3636
async fn test_get_archive_and_extract() -> anyhow::Result<()> {
3737
let url = zonky::URL;
38-
let version_req = VersionReq::STAR;
38+
let version_req = VersionReq::parse("=16.3.0")?;
3939
let (archive_version, archive) = get_archive(url, &version_req).await?;
4040

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

4343
let out_dir = tempfile::tempdir()?.path().to_path_buf();
44-
extract(url, &archive, &out_dir).await?;
44+
let files = extract(url, &archive, &out_dir).await?;
45+
#[cfg(all(target_os = "linux", target_arch = "x86_64"))]
46+
assert_eq!(1_023, files.len());
47+
#[cfg(all(target_os = "macos", target_arch = "aarch64"))]
48+
assert_eq!(1_019, files.len());
49+
#[cfg(all(target_os = "macos", target_arch = "x86_64"))]
50+
assert_eq!(1_019, files.len());
51+
#[cfg(all(target_os = "windows", target_arch = "x86_64"))]
52+
assert_eq!(1_019, files.len());
4553
remove_dir_all(&out_dir)?;
4654
Ok(())
4755
}

0 commit comments

Comments
 (0)