lux_lib/package/
outdated.rs1use std::fmt::Display;
2
3use crate::package_db::PackageDB;
4use miette::Diagnostic;
5use thiserror::Error;
6
7use super::{version::PackageVersion, PackageName, PackageReq, PackageSpec, PackageVersionReq};
8
9#[derive(Error, Debug, Diagnostic)]
10#[error("rock {0} not found")]
11pub struct RockNotFound(PackageName);
12
13#[derive(Error, Debug, Diagnostic)]
14#[error("rock {} has no version that satisfies constraint {}", .name, .constraint.to_string())]
15pub struct RockConstraintUnsatisfied {
16 name: PackageName,
17 constraint: PackageVersionReq,
18}
19
20impl PackageSpec {
21 pub async fn has_update(
24 &self,
25 package_db: &PackageDB,
26 ) -> Result<Option<PackageVersion>, RockNotFound> {
27 let latest_version = package_db
28 .latest_version(&self.name)
29 .await
30 .ok_or_else(|| RockNotFound(self.name.clone()))?;
31
32 if self.version < latest_version {
33 Ok(Some(latest_version))
34 } else {
35 Ok(None)
36 }
37 }
38
39 pub async fn has_update_with(
42 &self,
43 constraint: &PackageReq,
44 package_db: &PackageDB,
45 ) -> Result<Option<PackageVersion>, RockConstraintUnsatisfied> {
46 let latest_version = package_db
47 .latest_match(constraint, None)
48 .await
49 .ok_or_else(|| RockConstraintUnsatisfied {
50 name: self.name.clone(),
51 constraint: constraint.version_req.clone(),
52 })?;
53
54 if self.version < latest_version.version {
55 Ok(Some(latest_version.version))
56 } else {
57 Ok(None)
58 }
59 }
60}
61
62impl Display for PackageSpec {
63 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
64 f.write_str(format!("{} {}", self.name, self.version).as_str())
65 }
66}
67
68#[cfg(test)]
69mod tests {
70 use std::path::PathBuf;
71
72 use url::Url;
73
74 use crate::{
75 config::ConfigBuilder,
76 manifest::{Manifest, ManifestMetadata},
77 package::PackageSpec,
78 package_db::PackageDB,
79 };
80
81 #[tokio::test]
82 async fn rock_has_update() {
83 let test_manifest_path =
84 PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("resources/test/manifest-5.1");
85 let content = String::from_utf8(std::fs::read(&test_manifest_path).unwrap()).unwrap();
86 let metadata = ManifestMetadata::new(&content).unwrap();
87 let config = ConfigBuilder::new().unwrap().build().unwrap();
88 let package_db = PackageDB::from_manifest(
89 Manifest::new(
90 Url::parse("https://example.com").unwrap(),
91 metadata,
92 Default::default(),
93 ),
94 &config,
95 );
96
97 let test_package =
98 PackageSpec::parse("lua-cjson".to_string(), "2.0.0".to_string()).unwrap();
99
100 assert_eq!(
101 test_package.has_update(&package_db).await.unwrap(),
102 Some("2.1.0.10-1".parse().unwrap())
103 );
104 }
105}