Returns true if `latest` is strictly newer than `current` using semver comparison. Handles pre-release suffixes (e.g. "2.5.0-beta.1") by stripping them for the base version comparison, then comparing pre-release tags lexicographically.
(current: &str, latest: &str)
| 242 | /// Handles pre-release suffixes (e.g. "2.5.0-beta.1") by stripping them for the |
| 243 | /// base version comparison, then comparing pre-release tags lexicographically. |
| 244 | pub fn is_newer_version(current: &str, latest: &str) -> bool { |
| 245 | /// Parses a version string into (major, minor, patch, pre-release). |
| 246 | fn parse(v: &str) -> Option<(u64, u64, u64, Option<&str>)> { |
| 247 | let (base, pre) = match v.split_once('-') { |
| 248 | Some((b, p)) => (b, Some(p)), |
| 249 | None => (v, None), |
| 250 | }; |
| 251 | let mut parts = base.split('.'); |
| 252 | let major = parts.next()?.parse().ok()?; |
| 253 | let minor = parts.next()?.parse().ok()?; |
| 254 | let patch = parts.next()?.parse().ok()?; |
| 255 | Some((major, minor, patch, pre)) |
| 256 | } |
| 257 | |
| 258 | match (parse(current), parse(latest)) { |
| 259 | (Some((cm, cn, cp, cpre)), Some((lm, ln, lp, lpre))) => { |
| 260 | // Beta and stable are separate channels — never suggest cross-channel updates. |
| 261 | if cpre.is_some() != lpre.is_some() { |
| 262 | return false; |
| 263 | } |
| 264 | let c_base = (cm, cn, cp); |
| 265 | let l_base = (lm, ln, lp); |
| 266 | if l_base != c_base { |
| 267 | return l_base > c_base; |
| 268 | } |
| 269 | // Same base version, same channel |
| 270 | match (cpre, lpre) { |
| 271 | (Some(a), Some(b)) => b > a, |
| 272 | _ => false, |
| 273 | } |
| 274 | } |
| 275 | _ => false, |
| 276 | } |
| 277 | } |
| 278 | |
| 279 | /// Returns true if `latest` is a newer version than `current` AND the |
| 280 | /// difference is at least a minor version bump (patch-only bumps return false). |
no test coverage detected