aboutsummaryrefslogtreecommitdiffhomepage
path: root/crates/mozart-semver/src/lib.rs
diff options
context:
space:
mode:
authornsfisis <nsfisis@gmail.com>2026-05-04 00:32:45 +0900
committernsfisis <nsfisis@gmail.com>2026-05-04 00:32:45 +0900
commit6449a15de90fe8252fb288bd5eacb99dc2cd699a (patch)
tree81a2b5c2c595a67112d7211db6dcb670efb09ea0 /crates/mozart-semver/src/lib.rs
parent5fc05048a456ce18fd9408ea985031865cf45550 (diff)
downloadphp-mozart-6449a15de90fe8252fb288bd5eacb99dc2cd699a.tar.gz
php-mozart-6449a15de90fe8252fb288bd5eacb99dc2cd699a.tar.zst
php-mozart-6449a15de90fe8252fb288bd5eacb99dc2cd699a.zip
fix(compat): align repositories/version/platform parsing with Composer
Three Composer-compat bugs surfaced by the github_issues_9290 fixture, fixed together since they form one resolution path: - RawPackageData.repositories now accepts a JSON object keyed by name, matching RepositoryFactory::createRepos which iterates either int- or string-keyed arrays via PHP foreach. - Version::parse fills every unspecified position of a `.x-dev` branch with 9999999, mirroring VersionParser::normalizeBranch. Previously `2.x-dev` parsed to 2.0.9999999.9999999-dev and failed to satisfy ^2.8. - is_platform_package limits the `php-` family to the closed set {64bit,ipv6,zts,debug} per PLATFORM_PACKAGE_REGEX. Vendor packages like `php-http/client-common` are no longer misclassified. Unblocks github_issues_7051, _8903, _9012, _9290. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Diffstat (limited to 'crates/mozart-semver/src/lib.rs')
-rw-r--r--crates/mozart-semver/src/lib.rs23
1 files changed, 15 insertions, 8 deletions
diff --git a/crates/mozart-semver/src/lib.rs b/crates/mozart-semver/src/lib.rs
index d141566..d5d2826 100644
--- a/crates/mozart-semver/src/lib.rs
+++ b/crates/mozart-semver/src/lib.rs
@@ -187,17 +187,21 @@ impl Version {
// the form Composer's `normalizeBranch` emits for `3.2.x`) is NOT a
// branch — it falls through to classical parsing where `-dev` is just
// a regular pre-release stability and `is_dev_branch` stays false.
+ //
+ // Mirrors `Composer\Semver\VersionParser::normalizeBranch`: every
+ // position not given by the input becomes 9999999. So `2.x-dev` →
+ // `2.9999999.9999999.9999999-dev`, not `2.0.9999999.9999999-dev`.
let s_lower = s.to_lowercase();
if s_lower.ends_with(".x-dev") {
let base = &s[..s.len() - ".x-dev".len()];
let parts: Vec<&str> = base.split('.').collect();
- let major = parts.first().and_then(|p| p.parse().ok()).unwrap_or(0);
- let minor = parts.get(1).and_then(|p| p.parse().ok()).unwrap_or(0);
+ let part_at =
+ |i: usize| -> u64 { parts.get(i).and_then(|p| p.parse().ok()).unwrap_or(9999999) };
return Ok(Version {
- major,
- minor,
- patch: 9999999,
- build: 9999999,
+ major: part_at(0),
+ minor: part_at(1),
+ patch: part_at(2),
+ build: part_at(3),
pre_release: Some("dev".to_string()),
is_dev_branch: true,
dev_branch_name: None,
@@ -1389,11 +1393,14 @@ mod tests {
#[test]
fn test_parse_x_dev_two_segment() {
- // "2.x-dev" → major=2, minor=0, patch=9999999, build=9999999
+ // "2.x-dev" → major=2, minor/patch/build all 9999999. Mirrors
+ // Composer's `normalizeBranch`, which fills every position not given
+ // by the input with `.x` and then replaces `x` with `9999999`. So the
+ // missing minor position is also 9999999, not 0.
let v = Version::parse("2.x-dev").unwrap();
assert!(v.is_dev_branch);
assert_eq!(v.major, 2);
- assert_eq!(v.minor, 0);
+ assert_eq!(v.minor, 9999999);
assert_eq!(v.patch, 9999999);
assert_eq!(v.build, 9999999);
}