From 2dc5df611258104ec56dbf6cea0089c28766e270 Mon Sep 17 00:00:00 2001 From: John Turner Date: Tue, 18 Nov 2025 03:21:44 +0000 Subject: [PATCH] support portage build-id extension --- src/atom/mod.rs | 31 ++++++++++++++++++++++++++++--- src/atom/parsers.rs | 5 ++++- 2 files changed, 32 insertions(+), 4 deletions(-) diff --git a/src/atom/mod.rs b/src/atom/mod.rs index 54de7ee..0378a8d 100644 --- a/src/atom/mod.rs +++ b/src/atom/mod.rs @@ -64,6 +64,7 @@ pub struct Version { letter: Option, suffixes: VersionSuffixes, rev: Option, + build_id: Option, } #[derive(Clone, Copy, Debug, PartialEq, Eq)] @@ -374,6 +375,13 @@ impl PartialEq for Version { (Some(_), None) | (None, Some(_)) => false, (None, None) => true, } + && match (&self.build_id, &other.build_id) { + (Some(a), Some(b)) => { + a.get().parse::().unwrap() == b.get().parse::().unwrap() + } + (Some(_), None) | (None, Some(_)) => false, + (None, None) => true, + } } } @@ -410,14 +418,30 @@ impl Ord for Version { } match (&self.rev, &other.rev) { + (Some(a), Some(b)) => match a + .get() + .parse::() + .unwrap() + .cmp(&b.get().parse().unwrap()) + { + Ordering::Less => return Ordering::Less, + Ordering::Greater => return Ordering::Greater, + Ordering::Equal => (), + }, + (Some(a), None) if a.get().chars().all(|c| c == '0') => (), + (Some(_), None) => return Ordering::Greater, + (None, Some(b)) if b.get().chars().all(|c| c == '0') => (), + (None, Some(_)) => return Ordering::Less, + (None, None) => (), + } + + match (&self.build_id, &other.build_id) { (Some(a), Some(b)) => a .get() .parse::() .unwrap() - .cmp(&b.get().parse().unwrap()), - (Some(a), None) if a.get().chars().all(|c| c == '0') => Ordering::Equal, + .cmp(&b.get().parse::().unwrap()), (Some(_), None) => Ordering::Greater, - (None, Some(b)) if b.get().chars().all(|c| c == '0') => Ordering::Equal, (None, Some(_)) => Ordering::Less, (None, None) => Ordering::Equal, } @@ -759,6 +783,7 @@ mod test { ("1.0.0_alpha", "1.0.0_alpha_p", Ordering::Less), ("1.0.0-r0", "1.0.0", Ordering::Equal), ("1.0.0-r0000", "1.0.0", Ordering::Equal), + ("1.0.0-r1-1", "1.0.0-r1-2", Ordering::Less), ]; for (a, b, ordering) in versions.iter().map(|(a, b, ordering)| { diff --git a/src/atom/parsers.rs b/src/atom/parsers.rs index ee2c42a..75eca51 100644 --- a/src/atom/parsers.rs +++ b/src/atom/parsers.rs @@ -94,16 +94,19 @@ impl<'a> Parseable<'a, &'a str> for Version { fn parser() -> Self::Parser { let rev = VersionNumber::parser().preceded_by(tag("-r")); + let build_id = VersionNumber::parser().preceded_by(tag("-")); VersionNumbers::parser() .and(r#if(|c: &char| c.is_ascii_alphabetic() && c.is_ascii_lowercase()).opt()) .and(VersionSuffixes::parser().preceded_by(tag("_")).opt()) .and(rev.opt()) - .map(|(((numbers, letter), suffixes), rev)| Version { + .and(build_id.opt()) + .map(|((((numbers, letter), suffixes), rev), build_id)| Version { numbers, letter, suffixes: suffixes.unwrap_or(VersionSuffixes(Vec::new())), rev, + build_id, }) } }