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 Nov 4, 2024
1 parent 395d5ad commit a6187d5
Show file tree
Hide file tree
Showing 2 changed files with 52 additions and 31 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
61 changes: 30 additions & 31 deletions ocaml/xapi/rpm.ml
Original file line number Diff line number Diff line change
Expand Up @@ -52,24 +52,12 @@ module Pkg = struct

type order = LT | EQ | GT

type version_segment = Int of int | Str of string
type version_segment = Int of int | Str of string | Tilde

let string_of_order = function LT -> "<" | EQ -> "=" | GT -> ">"

let order_of_int = function 0 -> EQ | r when r > 0 -> GT | _ -> LT

let version_segment_of_string s =
let is_all_number str =
let r = Re.Posix.compile_pat {|^[0-9]+$|} in
Re.execp r str
in
match s with
| _ when is_all_number s -> (
try Int (int_of_string s) with _ -> Str s
)
| _ ->
Str s

let error_msg = Printf.sprintf "Failed to parse '%s'"

let parse_epoch_version_release epoch_ver_rel =
Expand Down Expand Up @@ -177,29 +165,30 @@ module Pkg = struct
Int.compare i1 i2 |> order_of_int
| Str s1, Str s2 ->
String.compare s1 s2 |> order_of_int
| Tilde, Tilde ->
EQ
| Int _, Str _ ->
GT
| Str _, Int _ ->
LT
| Tilde, _ ->
LT
| _, Tilde ->
GT

let split_version_string s =
let r = Re.Posix.compile_pat {|([0-9]+|[a-zA-Z]+|~)|} in
let len = String.length s in
let rec aux acc pos =
if pos >= len then
List.rev acc
else
match Re.exec_opt ~pos r s with
| Some groups ->
let matched = Re.Group.get groups 0 in
let next_pos = Re.Group.stop groups 0 in
aux (matched :: acc) next_pos
| None ->
List.rev acc
in
aux [] 0
let split_version_string =
let r = Re.Posix.compile_pat {|[a-zA-Z]+|[0-9]+|~|} in
fun s -> s |> Re.all r |> List.map (fun g -> Re.Group.get g 0)

let normalize v = split_version_string v |> List.map version_segment_of_string
let normalize v =
let version_segment_of_string = function
| "~" ->
Tilde
| s -> (
try Int (int_of_string s) with _ -> Str s
)
in
v |> split_version_string |> List.map version_segment_of_string

let compare_version_strings s1 s2 =
(* Compare versions or releases of RPM packages
Expand All @@ -218,12 +207,18 @@ module Pkg = struct
* "1.0" ">" "1.a"
* "2.50" ">" "2.5"
* "XS3" "<" "xs2"
* "1.2.3" ">" "1.2.3a"
* "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"
*)
let rec compare_segments l1 l2 =
match (l1, l2) with
Expand All @@ -234,6 +229,10 @@ module Pkg = struct
| r ->
r
)
| Tilde :: _, [] ->
LT
| [], Tilde :: _ ->
GT
| _ :: _, [] ->
GT
| [], _ :: _ ->
Expand Down

0 comments on commit a6187d5

Please sign in to comment.