use std::fmt::Display;
use crate::package_db::PackageDB;
use miette::Diagnostic;
use thiserror::Error;
use super::{version::Version, Name, Req, Spec, VersionReq};
#[derive(Error, Debug, Diagnostic)]
#[error("rock {0} not found")]
pub struct RockNotFound(Name);
#[derive(Error, Debug, Diagnostic)]
#[error("rock {} has no version that satisfies constraint {}", .name, .constraint.to_string())]
pub struct RockConstraintUnsatisfied {
name: Name,
constraint: VersionReq,
}
impl Spec {
pub async fn has_update(
&self,
package_db: &PackageDB,
) -> Result<Option<Version>, RockNotFound> {
let latest_version = package_db
.latest_version(self.name())
.await
.ok_or_else(|| RockNotFound(self.name().clone()))?;
if self.version() < &latest_version {
Ok(Some(latest_version))
} else {
Ok(None)
}
}
pub async fn has_update_with(
&self,
constraint: &Req,
package_db: &PackageDB,
) -> Result<Option<Version>, RockConstraintUnsatisfied> {
let latest_version = package_db
.latest_match(constraint, None)
.await
.ok_or_else(|| RockConstraintUnsatisfied {
name: self.name().clone(),
constraint: constraint.version_req.clone(),
})?;
if self.version() < latest_version.version() {
Ok(Some(latest_version.version().clone()))
} else {
Ok(None)
}
}
}
impl Display for Spec {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.write_str(format!("{} {}", self.name(), self.version()).as_str())
}
}
#[cfg(test)]
mod tests {
use std::path::PathBuf;
use url::Url;
use crate::{
config::ConfigBuilder,
manifest::{Manifest, ManifestMetadata},
package::Spec,
package_db::PackageDB,
};
#[tokio::test]
async fn rock_has_update() {
let test_manifest_path =
PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("resources/test/manifest-5.1");
let content = String::from_utf8(std::fs::read(&test_manifest_path).unwrap()).unwrap();
let metadata = ManifestMetadata::new(&content).unwrap();
let config = ConfigBuilder::new().unwrap().build().unwrap();
let package_db = PackageDB::from_manifest(
Manifest::new(
Url::parse("https://example.com").unwrap(),
metadata,
Default::default(),
),
&config,
);
let test_package = Spec::parse("lua-cjson".to_string(), "2.0.0".to_string()).unwrap();
assert_eq!(
test_package.has_update(&package_db).await.unwrap(),
Some("2.1.0.10-1".parse().unwrap())
);
}
}