diff options
| author | nsfisis <nsfisis@gmail.com> | 2026-05-03 11:02:14 +0900 |
|---|---|---|
| committer | nsfisis <nsfisis@gmail.com> | 2026-05-03 11:02:14 +0900 |
| commit | d175ff0aca312eafc1e125ba12a9b4e8cf81960a (patch) | |
| tree | 237fefbb79e032a35f70006b9d5d02f12dbf8bf0 /crates/mozart-registry/src/inline_package.rs | |
| parent | c865a24596084eec90d10860265748c93bf7eb6a (diff) | |
| download | php-mozart-d175ff0aca312eafc1e125ba12a9b4e8cf81960a.tar.gz php-mozart-d175ff0aca312eafc1e125ba12a9b4e8cf81960a.tar.zst php-mozart-d175ff0aca312eafc1e125ba12a9b4e8cf81960a.zip | |
fix(registry): respect priority order across inline package repos
When a `type: package` repository declares a name already declared by a
higher-priority `type: package` entry, drop it. Mirrors Composer's
RepositorySet first-repo-wins semantics so duplicate names across inline
repositories cannot promote a lower-priority version into the pool.
Greens 4 installer fixtures: install_prefers_repos_over_package_versions,
repositories_priorities2, repositories_priorities4,
update_package_present_in_lower_repo_prio_but_not_main_due_to_min_stability.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Diffstat (limited to 'crates/mozart-registry/src/inline_package.rs')
| -rw-r--r-- | crates/mozart-registry/src/inline_package.rs | 22 |
1 files changed, 20 insertions, 2 deletions
diff --git a/crates/mozart-registry/src/inline_package.rs b/crates/mozart-registry/src/inline_package.rs index e10cd2b..bad00fb 100644 --- a/crates/mozart-registry/src/inline_package.rs +++ b/crates/mozart-registry/src/inline_package.rs @@ -7,6 +7,7 @@ use crate::packagist::PackagistVersion; use mozart_core::package::RawRepository; +use std::collections::HashSet; /// One package extracted from a `type: package` repository. pub struct InlinePackage { @@ -20,8 +21,14 @@ pub struct InlinePackage { /// objects. Entries that fail to parse (missing `name`/`version`, etc.) are /// silently skipped so the rest of the repositories list still applies — /// matching Composer's lenient PackageRepository constructor. +/// +/// Repositories are processed in declaration order. Once any repository +/// authoritatively answers for a package name, lower-priority `type: package` +/// repositories that list the same name are skipped — mirroring Composer's +/// first-repo-wins priority via `RepositorySet::findPackages`. pub fn collect_inline_packages(repositories: &[RawRepository]) -> Vec<InlinePackage> { let mut packages = Vec::new(); + let mut claimed: HashSet<String> = HashSet::new(); for repo in repositories { if repo.repo_type != "package" { continue; @@ -30,21 +37,32 @@ pub fn collect_inline_packages(repositories: &[RawRepository]) -> Vec<InlinePack continue; }; + let mut from_this_repo: Vec<InlinePackage> = Vec::new(); match value { serde_json::Value::Array(arr) => { for entry in arr { if let Some(pkg) = parse_inline_package(entry) { - packages.push(pkg); + from_this_repo.push(pkg); } } } serde_json::Value::Object(_) => { if let Some(pkg) = parse_inline_package(value) { - packages.push(pkg); + from_this_repo.push(pkg); } } _ => {} } + + let mut names_this_repo: HashSet<String> = HashSet::new(); + for pkg in from_this_repo { + if claimed.contains(&pkg.name) { + continue; + } + names_this_repo.insert(pkg.name.clone()); + packages.push(pkg); + } + claimed.extend(names_this_repo); } packages } |
