package_info: refactor sources parsing with iterator
All checks were successful
CI / build (push) Successful in 7m12s

This commit is contained in:
2025-12-31 19:23:49 +01:00
parent 1538e9ee19
commit a567506831

View File

@@ -214,20 +214,32 @@ async fn get_components(
Err("Components not found.".into()) Err("Components not found.".into())
} }
/* struct DebianSources {
* Parse a 'Sources.gz' debian package file data, to look for a target package and splitted_sources: std::str::Split<'static, &'static str>,
* return the data for that package stanza }
*/ impl DebianSources {
fn parse_sources( fn new(data: &[u8]) -> Result<DebianSources, Box<dyn Error>> {
data: &[u8], // Gz-decode 'Sources.gz' file into a string, and split it on stanzas
target_package: &str, let mut d = GzDecoder::new(data);
target_version: Option<&str>, let mut s = String::new();
) -> Result<Option<PackageStanza>, Box<dyn Error>> { d.read_to_string(&mut s)?;
let mut d = GzDecoder::new(data);
let mut s = String::new();
d.read_to_string(&mut s)?;
for stanza in s.split("\n\n") { // Convert the string to a static lifetime by leaking it
let static_str = Box::leak(s.into_boxed_str());
let splitted = static_str.split("\n\n");
Ok(DebianSources {
splitted_sources: splitted,
})
}
}
impl Iterator for DebianSources {
type Item = HashMap<String, String>;
fn next(&mut self) -> Option<Self::Item> {
let stanza = self.splitted_sources.next()?;
// Parse stanza into a hashmap of strings, the fields
let mut fields: HashMap<String, String> = HashMap::new(); let mut fields: HashMap<String, String> = HashMap::new();
let mut current_key = String::new(); let mut current_key = String::new();
@@ -248,50 +260,62 @@ fn parse_sources(
} }
} }
if let Some(pkg) = fields.get("Package") Some(fields)
&& pkg == target_package }
{ }
// Check version if requested
if let Some(ver) = target_version {
if let Some(pkg_ver) = fields.get("Version") {
if pkg_ver != ver {
continue;
}
} else {
continue;
}
}
let mut files = Vec::new(); /*
if let Some(checksums) = fields.get("Checksums-Sha256") { * Parse a 'Sources.gz' debian package file data, to look for a target package and
for line in checksums.lines() { * return the data for that package stanza
let parts: Vec<&str> = line.split_whitespace().collect(); */
if parts.len() >= 3 { fn parse_sources(
files.push(FileEntry { data: &[u8],
sha256: parts[0].to_string(), target_package: &str,
size: parts[1].parse().unwrap_or(0), target_version: Option<&str>,
name: parts[2].to_string(), ) -> Result<Option<PackageStanza>, Box<dyn Error>> {
}); let mut sources = DebianSources::new(data)?;
}
}
}
return Ok(Some(PackageStanza { // Find the right package, with the right version if requested
package: pkg.clone(), let stanza = sources.find(|s| {
version: fields.get("Version").cloned().unwrap_or_default(), let pkg = s.get("Package");
directory: fields.get("Directory").cloned().unwrap_or_default(), pkg.is_some()
format: fields && pkg.unwrap() == target_package
.get("Format") && (target_version.is_none() || s.get("Version").unwrap() == target_version.unwrap())
.cloned() });
.unwrap_or_else(|| "1.0".to_string()),
vcs_git: fields.get("Vcs-Git").cloned(), if stanza.is_none() {
vcs_browser: fields.get("Vcs-Browser").cloned(), return Ok(None);
files, }
})); let stanza = stanza.unwrap();
// Parse package files
let mut files = Vec::new();
if let Some(checksums) = stanza.get("Checksums-Sha256") {
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(),
size: parts[1].parse().unwrap_or(0),
name: parts[2].to_string(),
});
}
} }
} }
Ok(None) // Return package stanza
Ok(Some(PackageStanza {
package: stanza.get("Package").cloned().unwrap(),
version: stanza.get("Version").cloned().unwrap_or_default(),
directory: stanza.get("Directory").cloned().unwrap_or_default(),
format: stanza
.get("Format")
.cloned()
.unwrap_or_else(|| "1.0".to_string()),
vcs_git: stanza.get("Vcs-Git").cloned(),
vcs_browser: stanza.get("Vcs-Browser").cloned(),
files,
}))
} }
pub async fn get( pub async fn get(