fix: Resolve dependency links to latest package version

Dependency FMRIs are version constraints (e.g. SUNWcs@0.5.11-151056.0)
not exact versions, so they don't match any specific manifest. Now
dependency links use the package name only, and the detail handler
resolves name-only or partial-version FMRIs by finding the latest
version from list_packages and redirecting to it.
This commit is contained in:
Till Wegmueller 2026-03-15 23:00:20 +01:00
parent 503efb6aed
commit 0d737168e0
No known key found for this signature in database

View file

@ -372,7 +372,37 @@ pub async fn ui_package_detail(
let fmri = Fmri::from_str(&decoded_fmri) let fmri = Fmri::from_str(&decoded_fmri)
.map_err(|e| DepotError::Repo(libips::repository::RepositoryError::Other(e.to_string())))?; .map_err(|e| DepotError::Repo(libips::repository::RepositoryError::Other(e.to_string())))?;
let content = repo.get_manifest_text(&publisher, &fmri)?; // If get_manifest_text fails (e.g. name-only FMRI from a dependency link),
// try to find the latest version of this package and redirect
let content = match repo.get_manifest_text(&publisher, &fmri) {
Ok(c) => c,
Err(_) if fmri.version().is_empty() || !fmri.version().contains(':') => {
// Likely a partial/missing version — find latest from package list
let pkg_name = fmri.stem();
if let Ok(packages) = repo.list_packages(Some(&publisher), None) {
if let Some(latest) = packages
.into_iter()
.filter(|p| p.fmri.name == pkg_name)
.max_by(|a, b| a.fmri.version().cmp(&b.fmri.version()))
{
let version = latest.fmri.version();
let path = format!("{}@{}", pkg_name, version);
let redirect_url = format!(
"/ui/package/{}/{}",
publisher,
encode_fmri(&path)
);
return Ok(axum::response::Redirect::to(&redirect_url).into_response());
}
}
return Err(DepotError::Repo(
libips::repository::RepositoryError::NotFound(
format!("Package {} not found in {}", pkg_name, publisher),
),
));
}
Err(e) => return Err(e),
};
let manifest = parse_manifest(&content)?; let manifest = parse_manifest(&content)?;
let name = fmri.stem().to_string(); let name = fmri.stem().to_string();
@ -411,11 +441,9 @@ pub async fn ui_package_detail(
let link = if dep_fmri.publisher.is_none() let link = if dep_fmri.publisher.is_none()
|| dep_fmri.publisher.as_deref() == Some(&publisher) || dep_fmri.publisher.as_deref() == Some(&publisher)
{ {
let dep_path = if dep_fmri.version().is_empty() { // Link to package name only — dependency versions are constraints,
dep_fmri.stem().to_string() // not exact versions, so they won't match a specific manifest
} else { let dep_path = dep_fmri.stem().to_string();
format!("{}@{}", dep_fmri.stem(), dep_fmri.version())
};
Some(format!("/ui/package/{}/{}", publisher, encode_fmri(&dep_path))) Some(format!("/ui/package/{}/{}", publisher, encode_fmri(&dep_path)))
} else { } else {
None None