m/cup
1
0
mirror of https://github.com/sergi0g/cup.git synced 2025-11-17 01:23:39 -05:00

Add semver regex and function to match tags (preparing to implement semver checking)

This commit is contained in:
Sergio
2024-10-27 18:09:26 +02:00
parent 078a51c4fa
commit 3ed79e69bd

View File

@@ -146,6 +146,55 @@ impl Image {
time: self.time_ms
}
}
/// Tries to parse the tag into semver parts
pub fn get_version(&self) -> Option<SemVer> {
get_version(self.tag.as_ref().unwrap())
}
}
/// Tries to parse the tag into semver parts. Should have been included in impl Image, but that would make the tests more complicated
pub fn get_version(tag: &str) -> Option<SemVer> {
let captures = SEMVER.captures_iter(tag);
// And now... terrible best match selection for everyone!
let mut max_matches = 0;
let mut best_match = None;
for capture in captures {
let mut count = 0;
for idx in 1..capture.len() {
if capture.get(idx).is_some() {
count += 1
} else {
break;
}
}
if count > max_matches {
max_matches = count;
best_match = Some(capture);
}
}
match best_match {
Some(c) => {
let major: i32 = match c.name("major") {
Some(major) => major.as_str().parse().unwrap(),
None => return None,
};
let minor: i32 = match c.name("minor") {
Some(minor) => minor.as_str().parse().unwrap(),
None => 0,
};
let patch: i32 = match c.name("patch") {
Some(patch) => patch.as_str().parse().unwrap(),
None => 0,
};
Some(SemVer {
major,
minor,
patch,
})
}
None => None,
}
}
/// Regex to match Docker image references against, so registry, repository and tag can be extracted.
@@ -156,6 +205,12 @@ static RE: Lazy<Regex> = Lazy::new(|| {
.unwrap()
});
/// Heavily modified version of the official semver regex based on common tagging schemes for container images. Sometimes it matches more than once, but we'll try to select the best match. Yes, there _will_ be errors.
static SEMVER: Lazy<Regex> = Lazy::new(|| {
Regex::new(r#"(?P<major>0|[1-9]\d*)(?:\.(?P<minor>0|[1-9]\d*))?(?:\.(?P<patch>0|[1-9]\d*)+)?"#)
.unwrap()
});
/// Enum for image status
pub enum Status {
UpToDate,
@@ -183,3 +238,36 @@ impl Status {
}
}
}
#[derive(Debug, PartialEq)]
pub struct SemVer {
major: i32,
minor: i32,
patch: i32,
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
#[rustfmt::skip]
fn semver() {
assert_eq!(get_version("5.3.2" ).unwrap(), SemVer { major: 5, minor: 3, patch: 2 });
assert_eq!(get_version("14" ).unwrap(), SemVer { major: 14, minor: 0, patch: 0 });
assert_eq!(get_version("v0.107.53" ).unwrap(), SemVer { major: 0, minor: 107, patch: 53 });
assert_eq!(get_version("12-alpine" ).unwrap(), SemVer { major: 12, minor: 0, patch: 0 });
assert_eq!(get_version("0.9.5-nginx" ).unwrap(), SemVer { major: 0, minor: 9, patch: 5 });
assert_eq!(get_version("v27.0" ).unwrap(), SemVer { major: 27, minor: 0, patch: 0 });
assert_eq!(get_version("16.1" ).unwrap(), SemVer { major: 16, minor: 1, patch: 0 });
assert_eq!(get_version("version-1.5.6" ).unwrap(), SemVer { major: 1, minor: 5, patch: 6 });
assert_eq!(get_version("15.4-alpine" ).unwrap(), SemVer { major: 15, minor: 4, patch: 0 });
assert_eq!(get_version("pg14-v0.2.0" ).unwrap(), SemVer { major: 0, minor: 2, patch: 0 });
assert_eq!(get_version("18-jammy-full.s6-v0.88.0").unwrap(), SemVer { major: 0, minor: 88, patch: 0 });
assert_eq!(get_version("fpm-2.1.0-prod" ).unwrap(), SemVer { major: 2, minor: 1, patch: 0 });
assert_eq!(get_version("7.3.3.50" ).unwrap(), SemVer { major: 7, minor: 3, patch: 3 });
assert_eq!(get_version("1.21.11-0" ).unwrap(), SemVer { major: 1, minor: 21, patch: 11 });
assert_eq!(get_version("4.1.2.1-full" ).unwrap(), SemVer { major: 4, minor: 1, patch: 2 });
assert_eq!(get_version("v4.0.3-ls215" ).unwrap(), SemVer { major: 4, minor: 0, patch: 3 });
}
}