pull: support Sources.gz without Checksums-Sha256
The Ubuntu development series (stonking) Sources.gz no longer ships a Checksums-Sha256 field, only Checksums-Sha512 and the legacy Files (MD5) field. The package_info parser only read Checksums-Sha256, so the file list ended up empty and fetch_orig_tarball panicked on Option::unwrap() when looking for the orig tarball. - Add a ChecksumAlgo enum (Md5/Sha256/Sha512) to FileEntry, replacing the hardcoded sha256 field, and parse the strongest available checksum field (Sha256 > Sha512 > MD5). - Make download_file_checksum verify against the correct algorithm instead of always using SHA-256. - Replace the unwrap() on the orig tarball search with a proper error listing the available files, so future regressions fail clearly instead of panicking. - Add md-5 dependency for MD5 verification.
This commit is contained in:
+31
-10
@@ -83,7 +83,6 @@ fn clone_repo(
|
||||
}
|
||||
}
|
||||
|
||||
use sha2::{Digest, Sha256};
|
||||
use std::fs::File;
|
||||
use std::io::Write;
|
||||
|
||||
@@ -221,6 +220,7 @@ fn checkout_pristine_tar(package_dir: &Path, filename: &str) -> Result<(), Box<d
|
||||
async fn download_file_checksum(
|
||||
url: &str,
|
||||
checksum: &str,
|
||||
algo: crate::package_info::ChecksumAlgo,
|
||||
target_dir: &Path,
|
||||
progress: ProgressCallback<'_>,
|
||||
) -> Result<(), Box<dyn Error>> {
|
||||
@@ -242,11 +242,13 @@ async fn download_file_checksum(
|
||||
|
||||
// Download chunk by chunk to disk, while updating hasher for checksum
|
||||
let mut stream = response.bytes_stream();
|
||||
let mut hasher = Sha256::new();
|
||||
// Accumulate the downloaded bytes so we can compute the final digest with the
|
||||
// correct algorithm once the download is complete.
|
||||
let mut buffer: Vec<u8> = Vec::with_capacity(total_size as usize);
|
||||
while let Some(item) = stream.next().await {
|
||||
let chunk = item?;
|
||||
file.write_all(&chunk)?;
|
||||
hasher.update(&chunk);
|
||||
buffer.extend_from_slice(&chunk);
|
||||
|
||||
if let Some(cb) = progress {
|
||||
index = min(index + chunk.len(), total_size as usize);
|
||||
@@ -254,9 +256,8 @@ async fn download_file_checksum(
|
||||
}
|
||||
}
|
||||
|
||||
// Verify checksum
|
||||
let result = hasher.finalize();
|
||||
let calculated_checksum = hex::encode(result);
|
||||
// Verify checksum using the algorithm specified for this file
|
||||
let calculated_checksum = algo.hex_digest(&buffer);
|
||||
if calculated_checksum != checksum {
|
||||
return Err(format!(
|
||||
"Checksum mismatch! Expected {}, got {}",
|
||||
@@ -323,7 +324,18 @@ async fn fetch_orig_tarball(
|
||||
.files
|
||||
.iter()
|
||||
.find(|f| f.name.contains(".orig.tar."))
|
||||
.unwrap();
|
||||
.ok_or_else(|| {
|
||||
format!(
|
||||
"Could not find orig tarball in file list for package '{}'. \
|
||||
Available files: {:?}",
|
||||
info.stanza.package,
|
||||
info.stanza
|
||||
.files
|
||||
.iter()
|
||||
.map(|f| &f.name)
|
||||
.collect::<Vec<_>>()
|
||||
)
|
||||
})?;
|
||||
let filename = &orig_file.name;
|
||||
|
||||
// 1. Try executing pristine-tar
|
||||
@@ -343,7 +355,8 @@ async fn fetch_orig_tarball(
|
||||
let target_dir = cwd.unwrap_or_else(|| Path::new("."));
|
||||
download_file_checksum(
|
||||
format!("{}/{}", info.archive_url, filename).as_str(),
|
||||
&orig_file.sha256,
|
||||
&orig_file.checksum,
|
||||
orig_file.checksum_algo,
|
||||
target_dir,
|
||||
progress,
|
||||
)
|
||||
@@ -373,7 +386,8 @@ async fn fetch_dsc_file(
|
||||
|
||||
download_file_checksum(
|
||||
format!("{}/{}", info.archive_url, filename).as_str(),
|
||||
&dsc_file.sha256,
|
||||
&dsc_file.checksum,
|
||||
dsc_file.checksum_algo,
|
||||
target_dir,
|
||||
progress,
|
||||
)
|
||||
@@ -397,7 +411,14 @@ async fn fetch_archive_sources(
|
||||
|
||||
for file in &info.stanza.files {
|
||||
let url = format!("{}/{}", info.archive_url, file.name);
|
||||
download_file_checksum(&url, &file.sha256, package_dir, progress).await?;
|
||||
download_file_checksum(
|
||||
&url,
|
||||
&file.checksum,
|
||||
file.checksum_algo,
|
||||
package_dir,
|
||||
progress,
|
||||
)
|
||||
.await?;
|
||||
|
||||
// Extract all tar archives, merging extracted directories
|
||||
if file.name.ends_with(".tar.gz") || file.name.ends_with(".tar.xz") {
|
||||
|
||||
Reference in New Issue
Block a user