diff options
| author | nsfisis <nsfisis@gmail.com> | 2026-02-22 17:49:49 +0900 |
|---|---|---|
| committer | nsfisis <nsfisis@gmail.com> | 2026-02-22 17:49:49 +0900 |
| commit | 07733b3b328f6e4ec23754fcb3504ddb196d65a3 (patch) | |
| tree | d3891db598caacf961aa0e4f72a71e766f9ae758 /crates/mozart-semver | |
| parent | b696eb7608d921ae0e14a4296e412c33340ceee8 (diff) | |
| download | php-mozart-07733b3b328f6e4ec23754fcb3504ddb196d65a3.tar.gz php-mozart-07733b3b328f6e4ec23754fcb3504ddb196d65a3.tar.zst php-mozart-07733b3b328f6e4ec23754fcb3504ddb196d65a3.zip | |
fix(resolver): replace ComposerVersion(u16) with semver::Version(u64)
ComposerVersion used u16 segments (max 65535), causing overflow for
PHP extensions like ext-dom (version 20031129). The extension became
invisible to the resolver, failing create-project with "depends on
ext-dom" errors.
Use mozart_semver::Version (u64 segments) directly as pubgrub's
version type, eliminating the overflow and redundant conversion layer.
Also fixes Ord for patch pre-releases (patch1 > stable) and adds
Display impl required by pubgrub.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Diffstat (limited to 'crates/mozart-semver')
| -rw-r--r-- | crates/mozart-semver/src/lib.rs | 59 |
1 files changed, 44 insertions, 15 deletions
diff --git a/crates/mozart-semver/src/lib.rs b/crates/mozart-semver/src/lib.rs index 7c417ec..474b6ce 100644 --- a/crates/mozart-semver/src/lib.rs +++ b/crates/mozart-semver/src/lib.rs @@ -1,4 +1,5 @@ use std::cmp::Ordering; +use std::fmt; /// A parsed Composer version (always 4 numeric segments + optional stability suffix). /// Composer normalizes all versions to `major.minor.patch.build[-stability[N]]`. @@ -70,11 +71,26 @@ impl Ord for Version { return num_cmp; } - // Compare pre-release: None (stable) > any pre-release + // Compare pre-release: None (stable) > most pre-releases, + // but patch/pl/p pre-releases (stability_rank 5) rank ABOVE stable. match (&self.pre_release, &other.pre_release) { (None, None) => Ordering::Equal, - (None, Some(_)) => Ordering::Greater, - (Some(_), None) => Ordering::Less, + (None, Some(b)) => { + if stability_rank(b) == 5 { + // patch pre-release ranks above stable + Ordering::Less + } else { + Ordering::Greater + } + } + (Some(a), None) => { + if stability_rank(a) == 5 { + // patch pre-release ranks above stable + Ordering::Greater + } else { + Ordering::Less + } + } (Some(a), Some(b)) => { let rank_a = stability_rank(a); let rank_b = stability_rank(b); @@ -92,6 +108,23 @@ impl Ord for Version { } } +impl fmt::Display for Version { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + if self.is_dev_branch { + if let Some(ref name) = self.dev_branch_name { + return write!(f, "dev-{}", name); + } + // Numeric dev branch (e.g. "2.x-dev") + return write!(f, "{}.{}.{}.{}-dev", self.major, self.minor, self.patch, self.build); + } + write!(f, "{}.{}.{}.{}", self.major, self.minor, self.patch, self.build)?; + if let Some(ref pre) = self.pre_release { + write!(f, "-{}", pre)?; + } + Ok(()) + } +} + impl Version { /// Parse a version string into a `Version` struct using Composer normalization rules. /// @@ -1224,14 +1257,12 @@ mod tests { } #[test] - fn test_ordering_stable_lt_patch() { - // The Ord impl: (None, Some(_)) => Greater — stable (pre_release=None) beats any - // pre_release including "patch1". Even though stability_rank("patch")=5 which is - // higher than stable's implicit 0, that path is only reached when both sides are - // Some(_). Since stable has pre_release=None, stable > patch version. + fn test_ordering_patch_gt_stable() { + // In Composer, patch/pl/p pre-releases rank ABOVE stable. + // e.g. 1.0.0-patch1 > 1.0.0 let stable = Version::parse("1.0.0").unwrap(); let patch = Version::parse("1.0.0-patch1").unwrap(); - assert!(stable > patch); + assert!(patch > stable); } #[test] @@ -1757,15 +1788,13 @@ mod tests { #[test] fn test_stability_rank_patch_via_ordering() { - // The Ord impl: (None, Some(_)) => Greater. - // stable has pre_release=None; patch version has pre_release=Some("patch1"). - // The None arm wins unconditionally: stable is always Greater than any pre_release. - // This means "patch" releases (post-release fixes) sort BELOW stable in this impl. + // In Composer, patch/pl/p pre-releases rank ABOVE stable. + // patch1 > stable for the same numeric version. let patch_ver = Version::parse("1.0.0-patch1").unwrap(); let stable = Version::parse("1.0.0").unwrap(); assert!( - stable > patch_ver, - "stable (None pre_release) beats patch pre-release" + patch_ver > stable, + "patch pre-release ranks above stable" ); } |
