alef_core/version.rs
1//! Cross-ecosystem version-format conversions.
2//!
3//! Cargo and the polyglot package registries disagree on prerelease syntax;
4//! these helpers normalize between them so each binding manifest receives a
5//! version string that its tooling will accept.
6
7/// Convert a semver pre-release version to RubyGems canonical prerelease format.
8///
9/// RubyGems rejects the dash-form prerelease syntax that cargo uses
10/// (`Gem::Version.new("1.8.0-rc.2")` raises) and requires the `.pre.` form.
11///
12/// # Examples
13///
14/// ```
15/// use alef_core::version::to_rubygems_prerelease;
16/// assert_eq!(to_rubygems_prerelease("1.8.0"), "1.8.0");
17/// assert_eq!(to_rubygems_prerelease("1.8.0-rc.2"), "1.8.0.pre.rc.2");
18/// assert_eq!(to_rubygems_prerelease("0.1.0-alpha.2"), "0.1.0.pre.alpha.2");
19/// ```
20pub fn to_rubygems_prerelease(version: &str) -> String {
21 if let Some((base, pre)) = version.split_once('-') {
22 let normalized_pre = pre.replace(['-', '_'], ".");
23 format!("{base}.pre.{normalized_pre}")
24 } else {
25 version.to_string()
26 }
27}
28
29#[cfg(test)]
30mod tests {
31 use super::*;
32
33 #[test]
34 fn release_version_is_unchanged() {
35 assert_eq!(to_rubygems_prerelease("1.8.0"), "1.8.0");
36 assert_eq!(to_rubygems_prerelease("0.1.0"), "0.1.0");
37 }
38
39 #[test]
40 fn rc_prerelease_uses_pre_dot_form() {
41 assert_eq!(to_rubygems_prerelease("1.8.0-rc.2"), "1.8.0.pre.rc.2");
42 }
43
44 #[test]
45 fn alpha_and_beta_prereleases_normalize() {
46 assert_eq!(to_rubygems_prerelease("0.1.0-alpha.2"), "0.1.0.pre.alpha.2");
47 assert_eq!(to_rubygems_prerelease("0.1.0-beta.3"), "0.1.0.pre.beta.3");
48 }
49
50 #[test]
51 fn dashes_in_prerelease_become_dots() {
52 assert_eq!(to_rubygems_prerelease("1.0.0-pre-rc-2"), "1.0.0.pre.pre.rc.2");
53 }
54}