//! Picks the `ReleaseSource` implementation for a package from its //! configured `source`. The one place that knows which hosts exist; the //! pipeline and the stages it calls only ever see the trait. use crate::checker::ReleaseSource; use crate::config::{Package, Source}; use crate::forgejo::ForgejoEndpoints; use crate::github::GithubEndpoints; use anyhow::{Context, Result}; /// Defensive: errors only if a `forgejo-release` package has no /// `base_url`, which `config::load_packages_dir` already guarantees. pub fn for_package(pkg: &Package) -> Result> { match pkg.source { Source::GithubRelease => Ok(Box::new(GithubEndpoints::default())), Source::ForgejoRelease => { let base_url = pkg .base_url .as_deref() .context("source = \"forgejo-release\" needs a base_url")?; Ok(Box::new(ForgejoEndpoints::from_base_url(base_url))) } } } #[cfg(test)] mod tests { use super::*; use crate::test_support::same_origin_package as package; #[test] fn github_source_uses_real_github() { let source = for_package(&package("")).unwrap(); assert_eq!(source.api(), "https://api.github.com"); } #[test] fn forgejo_source_uses_the_instances_api() { let pkg = package("source = \"forgejo-release\"\nbase_url = \"https://code.example.com\""); let source = for_package(&pkg).unwrap(); assert_eq!(source.api(), "https://code.example.com/api/v1"); } #[test] fn forgejo_source_without_base_url_errors() { let err = for_package(&package("source = \"forgejo-release\"")).unwrap_err(); assert!(err.to_string().contains("needs a base_url")); } }