Skip to content

Commit

Permalink
CA-400560: Support tilde in RPM version/release comparison
Browse files Browse the repository at this point in the history
Tilde `~` used in RPM version stands for pre-release. So version
with `~` is earlier than the same version without `~`.
For example:
1.2.3~beta < 1.2.3
1.xs8 > 1.xs8~2_1

Signed-off-by: Changlei Li <[email protected]>
  • Loading branch information
changlei-li committed Oct 30, 2024
1 parent 94dc48c commit d5bd6ed
Show file tree
Hide file tree
Showing 2 changed files with 78 additions and 23 deletions.
22 changes: 22 additions & 0 deletions ocaml/tests/test_rpm.ml
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,19 @@ module PkgOfFullnameTest = Generic.MakeStateless (struct
}
)
)
; ( Io.Line "libpath-utils-2:0.2.1~rc1-29.xs8~2_1.x86_64"
, Ok
(Some
Pkg.
{
name= "libpath-utils"
; epoch= Some 2
; version= "0.2.1~rc1"
; release= "29.xs8~2_1"
; arch= "x86_64"
}
)
)
; (Io.Line "libpath-utils-:0.2.1-29.el7.x86_64", Ok None)
; (Io.Line "libpath-utils-2:0.2.1-29.el7x86_64", Ok None)
; (* all RPM packages installed by default *)
Expand Down Expand Up @@ -171,6 +184,15 @@ module PkgCompareVersionStringsTest = Generic.MakeStateless (struct
; (("1.0_xs", "1.0.xs"), "=")
; (("1.0x3", "1.0x04"), ">")
; (("1.0O3", "1.0O04"), ">")
; (("1.2.3", "1.2.3~rc1"), ">")
; (("1.2.3~rc1", "1.2.3~rc2"), "<")
; (("1.2.3~rc1", "1.2.3~rc1"), "=")
; (("1.2.3~rc1", "1.2.3~rc1.1"), "<")
; (("1.2.3~rc1.1", "1.2.3~rc1.2"), "<")
; (("1.2.3~rc1.1", "1.2.3~rc1_1"), "=")
; (("1.2.3.xs8", "1.2.3.xs8~2_1"), ">")
; (("1.2.3.xs8~2_1", "1.2.3.xs8~2_1~beta"), ">")
; (("1.2.3.xs8~", "1.2.3.xs8"), "<")
]
end)

Expand Down
79 changes: 56 additions & 23 deletions ocaml/xapi/rpm.ml
Original file line number Diff line number Diff line change
Expand Up @@ -157,29 +157,7 @@ module Pkg = struct
| None, None ->
EQ

let compare_version_strings s1 s2 =
(* Compare versions or releases of RPM packages
* I.E. for "libpath-utils-0.2.1-29.el7.x86_64" and "libpath-utils-0.2.1a-30.el7.x86_64",
* this function compares:
* versions between "0.2.1" and "0.2.1a", or
* releases between "29.el7" and "30.el7".
* More examples:
* "1.2.3" "<" "1.2.4"
* "1.2.3" "=" "1.2.3"
* "1.2.3" ">" "1.2"
* "1.0011" ">" "1.9"
* "1.05" "=" "1.5"
* "1.0" ">" "1"
* "1.0" ">" "1.a"
* "2.50" ">" "2.5"
* "XS3" "<" "xs2"
* "1.2.3" ">" "1.2.3a"
* "xs4" "=" "xs.4"
* "2a" "<" "2.0"
* "2a" "<" "2b"
* "1.0" ">" "1.xs2"
* "1.0_xs" "=" "1.0.xs"
*)
let compare_no_tilde_version_strings s1 s2 =
let normalize v =
let split_letters_and_numbers s =
let r = Re.Posix.compile_pat {|^([^0-9]+)([0-9]+)$|} in
Expand Down Expand Up @@ -234,6 +212,61 @@ module Pkg = struct
in
compare_segments (normalize s1) (normalize s2)

let rec compare_version_strings s1 s2 =
(* Compare versions or releases of RPM packages
* I.E. for "libpath-utils-0.2.1-29.el7.x86_64" and
* "libpath-utils-0.2.1a-30.el7.x86_64",
* this function compares:
* versions between "0.2.1" and "0.2.1a", or
* releases between "29.el7" and "30.el7".
* More examples:
* "1.2.3" "<" "1.2.4"
* "1.2.3" "=" "1.2.3"
* "1.2.3" ">" "1.2"
* "1.0011" ">" "1.9"
* "1.05" "=" "1.5"
* "1.0" ">" "1"
* "1.0" ">" "1.a"
* "2.50" ">" "2.5"
* "XS3" "<" "xs2"
* "1.2.3" ">" "1.2.3a"
* "xs4" "=" "xs.4"
* "2a" "<" "2.0"
* "2a" "<" "2b"
* "1.0" ">" "1.xs2"
* "1.0_xs" "=" "1.0.xs"
* "1.xs8" ">" "1.xs8~2_1"
* "1.2.3" ">" "1.2.3~beta"
* Some corner cases that don't follow standard RPM versioning conventions
* with tilde:
* "1.2.3~rc1~beta" "<" "1.2.3~rc1"
* "1.2.3~" "<" "1.2.3"
*)
match (Astring.String.cut ~sep:"~" s1, Astring.String.cut ~sep:"~" s2) with
| None, None ->
compare_no_tilde_version_strings s1 s2
| Some (release1, pre_release1), Some (release2, pre_release2) -> (
match compare_no_tilde_version_strings release1 release2 with
| EQ ->
compare_version_strings pre_release1 pre_release2
| r ->
r
)
| Some (release1, _), None -> (
match compare_no_tilde_version_strings release1 s2 with
| EQ ->
LT
| r ->
r
)
| None, Some (release2, _) -> (
match compare_no_tilde_version_strings s1 release2 with
| EQ ->
GT
| r ->
r
)

let lt e1 v1 r1 e2 v2 r2 =
match
( compare_epoch e1 e2
Expand Down

0 comments on commit d5bd6ed

Please sign in to comment.