get: fetch from all components
All checks were successful
CI / build (push) Successful in 1m12s

This commit is contained in:
2025-11-28 18:16:29 +01:00
parent 0c3c5404f9
commit 92dfe8bacb
2 changed files with 75 additions and 22 deletions

View File

@@ -315,8 +315,17 @@ mod tests {
test_get_package_end_to_end("hello", "bookworm").await;
}
#[tokio::test]
async fn test_get_2048_universe_ubuntu_end_to_end() {
test_get_package_end_to_end("2048", "noble").await;
}
#[tokio::test]
async fn test_get_1oom_contrib_debian_end_to_end() {
test_get_package_end_to_end("1oom", "trixie").await;
}
#[tokio::test]
async fn test_get_agg_svn_fallback_ok() {
test_get_package_end_to_end("agg", "sid").await;
test_get_package_end_to_end("agg", "trixie").await;
}
}

View File

@@ -119,6 +119,34 @@ fn get_base_url(dist: &str) -> &str {
}
}
/*
* Obtain the URL for the 'Release' file of a distribution series
*/
fn get_release_url(base_url: &str, series: &str, pocket: &str) -> String {
let pocket_full = if pocket.is_empty() { String::new() } else { format!("-{}", pocket) };
format!("{base_url}/dists/{series}{pocket_full}/Release")
}
/*
* Obtain the components of a distribution series by parsing the 'Release' file
*/
async fn get_components(base_url: &str, series: &str, pocket: &str) -> Result<Vec<String>, Box<dyn Error>> {
let url = get_release_url(base_url, series, pocket);
debug!("Fetching Release file from: {}", url);
let content = reqwest::get(&url).await?.text().await?;
for line in content.lines() {
if line.starts_with("Components:") {
if let Some((_, components)) = line.split_once(':') {
return Ok(components.split_whitespace().map(|s| s.to_string()).collect());
}
}
}
Err("Components not found.".into())
}
/*
* Parse a 'Sources.gz' debian package file data, to look for a target package and
* return the data for that package stanza
@@ -193,33 +221,49 @@ pub async fn get(package_name: &str, series: &str, pocket: &str) -> Result<Optio
let base_url = get_base_url(&dist);
let component = "main"; // TODO: Make configurable or detect
let url = get_sources_url(base_url, series, pocket, component);
let components = get_components(base_url, series, pocket).await?;
debug!("Found components: {:?}", components);
debug!("Fetching sources from: {}", url);
let response = reqwest::get(&url).await?;
let compressed_data = response.bytes().await?;
debug!("Downloaded Sources.gz for {}/{}", dist, series);
for component in components {
let url = get_sources_url(base_url, series, pocket, &component);
debug!("Fetching sources from: {}", url);
if let Some(stanza) = parse_sources(&compressed_data, package_name)? {
if let Some(vcs) = &stanza.vcs_git {
if preferred_vcs.is_none() {
preferred_vcs = Some(vcs.clone());
let response = match reqwest::get(&url).await {
Ok(resp) => resp,
Err(e) => {
debug!("Failed to fetch {}: {}", url, e);
continue;
}
};
if !response.status().is_success() {
debug!("Failed to fetch {}: status {}", url, response.status());
continue;
}
let archive_url = format!("{base_url}/{0}", stanza.directory);
return Ok(Some(PackageInfo {
dist: dist,
stanza: stanza,
preferred_vcs: preferred_vcs,
archive_url: archive_url,
}));
} else {
Err(format!("Package '{}' not found in {}/{}", package_name, dist, series).into())
let compressed_data = response.bytes().await?;
debug!("Downloaded Sources.gz for {}/{}/{}", dist, series, component);
if let Some(stanza) = parse_sources(&compressed_data, package_name)? {
if let Some(vcs) = &stanza.vcs_git {
if preferred_vcs.is_none() {
preferred_vcs = Some(vcs.clone());
}
}
let archive_url = format!("{base_url}/{0}", stanza.directory);
return Ok(Some(PackageInfo {
dist: dist,
stanza: stanza,
preferred_vcs: preferred_vcs,
archive_url: archive_url,
}));
}
}
Err(format!("Package '{}' not found in {}/{}", package_name, dist, series).into())
}
#[cfg(test)]