diff --git a/src/deb/local.rs b/src/deb/local.rs index 9743b3e..8a5249b 100644 --- a/src/deb/local.rs +++ b/src/deb/local.rs @@ -135,11 +135,21 @@ pub async fn build( } } - // UBUNTU: Ensure 'universe' repository is enabled - for source in &mut sources { - if source.uri.contains("ubuntu") && !source.components.contains(&"universe".to_string()) { - source.components.push("universe".to_string()); - modified = true; + // UBUNTU: Ensure the 'universe' component is enabled on official + // Ubuntu sources (many build dependencies live there). The old + // `uri.contains("ubuntu")` gate also caught third-party repositories + // whose URL merely mentions Ubuntu; the mirror-data check leaves them + // alone. 'universe' is only added when Ubuntu's component list still + // carries it. + let ubuntu_components = crate::distro_info::get_dist_components("ubuntu")?; + if ubuntu_components.iter().any(|c| c == "universe") { + for source in &mut sources { + if crate::distro_info::is_official_source("ubuntu", &source.uri) + && !source.components.contains(&"universe".to_string()) + { + source.components.push("universe".to_string()); + modified = true; + } } } diff --git a/src/deb/mod.rs b/src/deb/mod.rs index c051a8b..3b197c9 100644 --- a/src/deb/mod.rs +++ b/src/deb/mod.rs @@ -366,12 +366,15 @@ fn find_dsc_file( } /// Check whether an apt source URI points to a distribution archive -/// (as opposed to a PPA or another third-party repository) +/// (as opposed to a PPA or another third-party repository): a thin, +/// dist-agnostic wrapper over [`crate::distro_info::is_official_source`], +/// unioned across every known distro. Where the distribution is known, +/// the dist-scoped check is preferred (it cannot misfire on another +/// distro's mirror); this fallback stays for the sites that cannot know. pub(crate) fn is_archive_source(uri: &str) -> bool { - uri.contains("archive.ubuntu.com") - || uri.contains("security.ubuntu.com") - || uri.contains("ports.ubuntu.com") - || uri.contains("deb.debian.org") + crate::distro_info::supported_dists() + .iter() + .any(|dist| crate::distro_info::is_official_source(dist, uri)) } #[cfg(test)] @@ -379,6 +382,31 @@ mod tests { use super::*; use std::sync::Arc; + /// The archive check is dist-agnostic (any distro's official mirror + /// counts) and host-based: the country mirrors the old substring + /// checks matched (`fr.archive.ubuntu.com`) still count, look-alike + /// hosts and PPAs do not. + #[test] + fn archive_sources_are_official_mirrors_of_any_distro() { + for uri in [ + "https://archive.ubuntu.com/ubuntu", + // Country mirrors front the Ubuntu archive. + "http://fr.archive.ubuntu.com/ubuntu", + "http://security.ubuntu.com/ubuntu", + "http://ports.ubuntu.com/ubuntu-ports", + "https://deb.debian.org/debian", + ] { + assert!(is_archive_source(uri), "{uri}"); + } + for uri in [ + "https://ppa.launchpadcontent.net/user/ppa/ubuntu", + "http://notarchive.ubuntu.com/ubuntu", + "https://example.com/debian", + ] { + assert!(!is_archive_source(uri), "{uri}"); + } + } + async fn test_build_end_to_end( package: &str, series: &str,