about summary refs log tree commit diff
path: root/tvix/eval/src/builtins/versions.rs
diff options
context:
space:
mode:
Diffstat (limited to 'tvix/eval/src/builtins/versions.rs')
-rw-r--r--tvix/eval/src/builtins/versions.rs15
1 files changed, 15 insertions, 0 deletions
diff --git a/tvix/eval/src/builtins/versions.rs b/tvix/eval/src/builtins/versions.rs
index ee75eeaeed3b..e149cc4dba37 100644
--- a/tvix/eval/src/builtins/versions.rs
+++ b/tvix/eval/src/builtins/versions.rs
@@ -1,4 +1,5 @@
 use std::cmp::Ordering;
+use std::iter::{once, Chain, Once};
 use std::ops::RangeInclusive;
 
 /// Version strings can be broken up into Parts.
@@ -69,6 +70,20 @@ impl<'a> VersionPartsIter<'a> {
             version,
         }
     }
+
+    /// Create an iterator that yields all version parts followed by an additional
+    /// `VersionPart::Word("")` part (i.e. you can think of this as
+    /// `builtins.splitVersion version ++ [ "" ]`). This is necessary, because
+    /// Nix's `compareVersions` is not entirely lexicographical: If we have two
+    /// equal versions, but one is longer, the longer one is only considered
+    /// greater if the first additional part of the longer version is not `pre`,
+    /// e.g. `2.3 > 2.3pre`. It is otherwise lexicographical, so peculiar behavior
+    /// like `2.3 < 2.3.0pre` ensues. Luckily for us, this means that we can
+    /// lexicographically compare two version strings, _if_ we append an extra
+    /// component to both versions.
+    pub fn new_for_cmp(version: &'a str) -> Chain<Self, Once<VersionPart>> {
+        Self::new(version).chain(once(VersionPart::Word("")))
+    }
 }
 
 impl<'a> Iterator for VersionPartsIter<'a> {