Skip to main content

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}