pray_core/
package_spec_version.rs1use super::PackageSpec;
2use crate::constraint::{normalize_version_constraint, version_satisfies};
3use crate::{PrayError, PrayResult};
4
5impl PackageSpec {
6 pub const LOCAL_VERSION: &'static str = "local";
7
8 pub fn has_release_version(&self) -> bool {
9 !self.version.is_empty() && self.version != Self::LOCAL_VERSION
10 }
11
12 pub fn recorded_version(&self) -> &str {
13 if self.has_release_version() {
14 &self.version
15 } else {
16 Self::LOCAL_VERSION
17 }
18 }
19
20 pub fn require_release_version(&self) -> PrayResult<()> {
21 if self.has_release_version() {
22 Ok(())
23 } else {
24 Err(PrayError::Manifest(format!(
25 "package {} needs a version before it can be packaged",
26 self.name
27 )))
28 }
29 }
30
31 pub fn satisfy_constraint(&self, constraint: &str) -> PrayResult<()> {
32 if !self.has_release_version() {
33 let normalized = normalize_version_constraint(constraint);
34 if normalized.is_empty() || normalized == "*" {
35 return Ok(());
36 }
37 return Err(PrayError::Resolution(format!(
38 "package {} has no version; add spec.version or omit the constraint",
39 self.name
40 )));
41 }
42 if version_satisfies(&self.version, constraint)? {
43 Ok(())
44 } else {
45 Err(PrayError::Resolution(format!(
46 "package {} version {} does not satisfy constraint {}",
47 self.name, self.version, constraint
48 )))
49 }
50 }
51}
52
53#[cfg(test)]
54mod tests {
55 use super::*;
56
57 fn spec_with_version(version: &str) -> PackageSpec {
58 PackageSpec {
59 name: "project".to_string(),
60 version: version.to_string(),
61 ..PackageSpec::default()
62 }
63 }
64
65 #[test]
66 fn omitted_version_records_local_and_matches_star() {
67 let spec = spec_with_version("");
68 assert_eq!(spec.recorded_version(), "local");
69 spec.satisfy_constraint("*").expect("star");
70 let error = spec.satisfy_constraint("~> 1.0").expect_err("range");
71 assert!(error.to_string().contains("has no version"));
72 spec.require_release_version().expect_err("pack");
73 }
74
75 #[test]
76 fn release_version_uses_semver_constraints() {
77 let spec = spec_with_version("1.4.3");
78 spec.satisfy_constraint("~> 1.4").expect("matches");
79 spec.require_release_version().expect("pack");
80 }
81}