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:
+56
-5
@@ -39,8 +39,47 @@ pub struct FileEntry {
|
||||
pub name: String,
|
||||
/// Size of the file
|
||||
pub size: u64,
|
||||
/// SHA256 hash for the file
|
||||
pub sha256: String,
|
||||
/// Checksum hash for the file
|
||||
pub checksum: String,
|
||||
/// Algorithm used for the checksum
|
||||
pub checksum_algo: ChecksumAlgo,
|
||||
}
|
||||
|
||||
/// Checksum algorithm used for a file entry
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
pub enum ChecksumAlgo {
|
||||
/// MD5 (legacy 'Files' field)
|
||||
Md5,
|
||||
/// SHA-256 ('Checksums-Sha256' field)
|
||||
Sha256,
|
||||
/// SHA-512 ('Checksums-Sha512' field)
|
||||
Sha512,
|
||||
}
|
||||
|
||||
impl ChecksumAlgo {
|
||||
/// Compute the hex-encoded digest of the given data using this algorithm
|
||||
pub fn hex_digest(&self, data: &[u8]) -> String {
|
||||
match self {
|
||||
ChecksumAlgo::Md5 => {
|
||||
use md5::{Digest, Md5};
|
||||
let mut hasher = Md5::new();
|
||||
hasher.update(data);
|
||||
hex::encode(hasher.finalize())
|
||||
}
|
||||
ChecksumAlgo::Sha256 => {
|
||||
use sha2::{Digest, Sha256};
|
||||
let mut hasher = Sha256::new();
|
||||
hasher.update(data);
|
||||
hex::encode(hasher.finalize())
|
||||
}
|
||||
ChecksumAlgo::Sha512 => {
|
||||
use sha2::{Digest, Sha512};
|
||||
let mut hasher = Sha512::new();
|
||||
hasher.update(data);
|
||||
hex::encode(hasher.finalize())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// A package 'stanza' as found is 'Sources.gz' files, containing basic information about a source package
|
||||
@@ -138,16 +177,28 @@ impl Iterator for DebianSources {
|
||||
return self.next();
|
||||
}
|
||||
|
||||
// Parse package files
|
||||
// Parse package files.
|
||||
// Prefer the strongest available checksum field: Checksums-Sha256,
|
||||
// then Checksums-Sha512, then the legacy 'Files' (MD5) field.
|
||||
// Some archives (e.g. the Ubuntu development series) no longer ship
|
||||
// Checksums-Sha256, so falling back is required to keep working.
|
||||
let mut files = Vec::new();
|
||||
if let Some(checksums) = fields.get("Checksums-Sha256") {
|
||||
let (checksum_field, algo) = if fields.contains_key("Checksums-Sha256") {
|
||||
("Checksums-Sha256", ChecksumAlgo::Sha256)
|
||||
} else if fields.contains_key("Checksums-Sha512") {
|
||||
("Checksums-Sha512", ChecksumAlgo::Sha512)
|
||||
} else {
|
||||
("Files", ChecksumAlgo::Md5)
|
||||
};
|
||||
if let Some(checksums) = fields.get(checksum_field) {
|
||||
for line in checksums.lines() {
|
||||
let parts: Vec<&str> = line.split_whitespace().collect();
|
||||
if parts.len() >= 3 {
|
||||
files.push(FileEntry {
|
||||
sha256: parts[0].to_string(),
|
||||
checksum: parts[0].to_string(),
|
||||
size: parts[1].parse().unwrap_or(0),
|
||||
name: parts[2].to_string(),
|
||||
checksum_algo: algo,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user