lux_lib/package/
outdated.rs

1use std::fmt::Display;
2
3use thiserror::Error;
4
5use crate::remote_package_db::RemotePackageDB;
6
7use super::{version::PackageVersion, PackageName, PackageReq, PackageSpec, PackageVersionReq};
8
9#[derive(Error, Debug)]
10#[error("rock {0} not found")]
11pub struct RockNotFound(PackageName);
12
13#[derive(Error, Debug)]
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    /// Tries to find a newer version of a given rock.
22    /// Returns the latest version if found.
23    pub fn has_update(
24        &self,
25        package_db: &RemotePackageDB,
26    ) -> Result<Option<PackageVersion>, RockNotFound> {
27        let latest_version = package_db
28            .latest_version(&self.name)
29            .ok_or_else(|| RockNotFound(self.name.clone()))?;
30
31        if self.version < latest_version {
32            Ok(Some(latest_version))
33        } else {
34            Ok(None)
35        }
36    }
37
38    /// Tries to find a newer version of a rock given a constraint.
39    /// Returns the latest version if found.
40    pub fn has_update_with(
41        &self,
42        constraint: &PackageReq,
43        package_db: &RemotePackageDB,
44    ) -> Result<Option<PackageVersion>, RockConstraintUnsatisfied> {
45        let latest_version =
46            package_db
47                .latest_match(constraint, None)
48                .ok_or_else(|| RockConstraintUnsatisfied {
49                    name: self.name.clone(),
50                    constraint: constraint.version_req.clone(),
51                })?;
52
53        if self.version < latest_version.version {
54            Ok(Some(latest_version.version))
55        } else {
56            Ok(None)
57        }
58    }
59}
60
61impl Display for PackageSpec {
62    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
63        f.write_str(format!("{} {}", self.name, self.version).as_str())
64    }
65}
66
67#[cfg(test)]
68mod test {
69    use std::path::PathBuf;
70
71    use url::Url;
72
73    use crate::{
74        manifest::{Manifest, ManifestMetadata},
75        package::PackageSpec,
76    };
77
78    #[test]
79    fn rock_has_update() {
80        let test_manifest_path =
81            PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("resources/test/manifest-5.1");
82        let content = String::from_utf8(std::fs::read(&test_manifest_path).unwrap()).unwrap();
83        let metadata = ManifestMetadata::new(&content).unwrap();
84        let package_db = Manifest::new(Url::parse("https://example.com").unwrap(), metadata).into();
85
86        let test_package =
87            PackageSpec::parse("lua-cjson".to_string(), "2.0.0".to_string()).unwrap();
88
89        assert_eq!(
90            test_package.has_update(&package_db).unwrap(),
91            Some("2.1.0-1".parse().unwrap())
92        );
93    }
94}