diff options
Diffstat (limited to 'crates/mozart-core')
| -rw-r--r-- | crates/mozart-core/src/autoload.rs | 66 | ||||
| -rw-r--r-- | crates/mozart-core/src/installer/installed_repo.rs | 9 | ||||
| -rw-r--r-- | crates/mozart-core/src/package.rs | 252 | ||||
| -rw-r--r-- | crates/mozart-core/src/package/complete_package_interface.rs | 17 | ||||
| -rw-r--r-- | crates/mozart-core/src/package/package_interface.rs | 33 | ||||
| -rw-r--r-- | crates/mozart-core/src/repository/browse_repos.rs | 19 | ||||
| -rw-r--r-- | crates/mozart-core/src/repository/installed.rs | 5 | ||||
| -rw-r--r-- | crates/mozart-core/src/repository/lockfile.rs | 160 | ||||
| -rw-r--r-- | crates/mozart-core/src/repository/packagist.rs | 20 | ||||
| -rw-r--r-- | crates/mozart-core/src/repository/vcs_bridge.rs | 3 | ||||
| -rw-r--r-- | crates/mozart-core/src/repository_utils.rs | 19 |
11 files changed, 300 insertions, 303 deletions
diff --git a/crates/mozart-core/src/autoload.rs b/crates/mozart-core/src/autoload.rs index 7e8ead6..08a2859 100644 --- a/crates/mozart-core/src/autoload.rs +++ b/crates/mozart-core/src/autoload.rs @@ -8,7 +8,6 @@ use crate::repository::installed::InstalledPackages; use crate::repository::lockfile::LockedPackage; use indexmap::IndexSet; use mozart_class_map_generator::{scan_classmap_dirs, scan_psr_for_classmap}; -use std::collections::BTreeMap; use std::path::{Path, PathBuf}; // Embed Composer PHP files from the submodule at compile time. @@ -70,15 +69,15 @@ pub struct AutoloadConfig { pub struct AutoloadData { /// PSR-4: namespace prefix -> list of directory path expressions. /// Each path is a PHP expression string like `$vendorDir . '/psr/log/src'`. - pub psr4: BTreeMap<String, Vec<String>>, + pub psr4: indexmap::IndexMap<String, Vec<String>>, /// PSR-0: namespace prefix -> list of directory path expressions. /// (Empty in Phase 2.2, populated in 5.6.) - pub psr0: BTreeMap<String, Vec<String>>, + pub psr0: indexmap::IndexMap<String, Vec<String>>, /// Classmap entries: class name -> file path expression. /// (Empty in Phase 2.2, populated in 5.6.) - pub classmap: BTreeMap<String, String>, + pub classmap: indexmap::IndexMap<String, String>, /// Files to include on every request: file_identifier -> path expression. - pub files: BTreeMap<String, String>, + pub files: indexmap::IndexMap<String, String>, } /// Mirror of `Composer\ClassMapGenerator\ClassMap` — the return value @@ -92,9 +91,9 @@ pub struct AutoloadData { /// summary — once `generate` is refactored to expose the full classmap /// these fields will hold the real entries. pub struct ClassMap { - map: BTreeMap<String, String>, + map: indexmap::IndexMap<String, String>, psr_violations: Vec<String>, - ambiguous_classes: BTreeMap<String, Vec<String>>, + ambiguous_classes: indexmap::IndexMap<String, Vec<String>>, } impl ClassMap { @@ -126,7 +125,7 @@ impl ClassMap { } /// Read access to the underlying map (`getMap()` upstream). - pub fn map(&self) -> &BTreeMap<String, String> { + pub fn map(&self) -> &indexmap::IndexMap<String, String> { &self.map } @@ -136,7 +135,7 @@ impl ClassMap { } /// Read access to the ambiguous-class records. - pub fn ambiguous_classes(&self) -> &BTreeMap<String, Vec<String>> { + pub fn ambiguous_classes(&self) -> &indexmap::IndexMap<String, Vec<String>> { &self.ambiguous_classes } } @@ -282,9 +281,9 @@ impl AutoloadGeneratorExt for AutoloadGenerator { // for now and surface the limitation here rather than // silently writing files. return Ok(ClassMap { - map: BTreeMap::new(), + map: indexmap::IndexMap::new(), psr_violations: Vec::new(), - ambiguous_classes: BTreeMap::new(), + ambiguous_classes: indexmap::IndexMap::new(), }); } @@ -297,7 +296,7 @@ impl AutoloadGeneratorExt for AutoloadGenerator { // command code that only branches on `count()` / `has_*()` works // today; refactoring `generate` to surface the full map is // tracked as follow-up work. - let mut map = BTreeMap::new(); + let mut map = indexmap::IndexMap::new(); for i in 0..result.class_count { map.insert(format!("__mozart_placeholder_{i}"), String::new()); } @@ -308,7 +307,7 @@ impl AutoloadGeneratorExt for AutoloadGenerator { } else { Vec::new() }; - let mut ambiguous_classes = BTreeMap::new(); + let mut ambiguous_classes = indexmap::IndexMap::new(); if result.has_ambiguous_classes { ambiguous_classes.insert("__mozart_placeholder".to_string(), Vec::new()); } @@ -526,16 +525,16 @@ fn collect_autoloads( dev_mode: bool, ) -> (AutoloadData, AutoloadData) { let mut data = AutoloadData { - psr4: BTreeMap::new(), - psr0: BTreeMap::new(), - classmap: BTreeMap::new(), - files: BTreeMap::new(), + psr4: indexmap::IndexMap::new(), + psr0: indexmap::IndexMap::new(), + classmap: indexmap::IndexMap::new(), + files: indexmap::IndexMap::new(), }; let mut static_data = AutoloadData { - psr4: BTreeMap::new(), - psr0: BTreeMap::new(), - classmap: BTreeMap::new(), - files: BTreeMap::new(), + psr4: indexmap::IndexMap::new(), + psr0: indexmap::IndexMap::new(), + classmap: indexmap::IndexMap::new(), + files: indexmap::IndexMap::new(), }; // Process each installed package @@ -703,7 +702,7 @@ fn generate_autoload_static(static_data: &AutoloadData, suffix: &str) -> String // $prefixLengthsPsr4 — group by first character of namespace if !static_data.psr4.is_empty() { // Group namespaces by first character, sorted reverse - let mut by_char: BTreeMap<char, Vec<(&String, usize)>> = BTreeMap::new(); + let mut by_char: indexmap::IndexMap<_, Vec<_>> = indexmap::IndexMap::new(); let mut sorted_ns: Vec<&String> = static_data.psr4.keys().collect(); sorted_ns.sort_by(|a, b| b.cmp(a)); @@ -1278,11 +1277,11 @@ pub fn generate(config: &AutoloadConfig) -> anyhow::Result<GenerateResult> { version_normalized: p.version_normalized.clone(), source: None, dist: None, - require: std::collections::BTreeMap::new(), - require_dev: std::collections::BTreeMap::new(), - conflict: std::collections::BTreeMap::new(), - provide: std::collections::BTreeMap::new(), - replace: std::collections::BTreeMap::new(), + require: indexmap::IndexMap::new(), + require_dev: indexmap::IndexMap::new(), + conflict: indexmap::IndexMap::new(), + provide: indexmap::IndexMap::new(), + replace: indexmap::IndexMap::new(), suggest: None, package_type: p.package_type.clone(), autoload: p.autoload.clone(), @@ -1295,7 +1294,7 @@ pub fn generate(config: &AutoloadConfig) -> anyhow::Result<GenerateResult> { support: None, funding: None, time: None, - extra_fields: std::collections::BTreeMap::new(), + extra_fields: indexmap::IndexMap::new(), }) .collect() }; @@ -1370,7 +1369,6 @@ pub fn generate(config: &AutoloadConfig) -> anyhow::Result<GenerateResult> { mod tests { use super::*; use crate::repository::installed::{InstalledPackageEntry, InstalledPackages}; - use std::collections::BTreeMap; use tempfile::tempdir; fn make_installed_pkg(name: &str, version: &str) -> InstalledPackageEntry { @@ -1386,7 +1384,7 @@ mod tests { aliases: vec![], homepage: None, support: None, - extra_fields: BTreeMap::new(), + extra_fields: indexmap::IndexMap::new(), } } @@ -1589,10 +1587,10 @@ mod tests { #[test] fn test_generate_autoload_psr4_empty() { let data = AutoloadData { - psr4: BTreeMap::new(), - psr0: BTreeMap::new(), - classmap: BTreeMap::new(), - files: BTreeMap::new(), + psr4: indexmap::IndexMap::new(), + psr0: indexmap::IndexMap::new(), + classmap: indexmap::IndexMap::new(), + files: indexmap::IndexMap::new(), }; let output = generate_autoload_psr4(&data); assert!(output.contains("return array(\n);")); diff --git a/crates/mozart-core/src/installer/installed_repo.rs b/crates/mozart-core/src/installer/installed_repo.rs index 8361158..d7e4f83 100644 --- a/crates/mozart-core/src/installer/installed_repo.rs +++ b/crates/mozart-core/src/installer/installed_repo.rs @@ -17,7 +17,6 @@ //! or through a `provide` / `replace` link. use indexmap::IndexSet; -use std::collections::BTreeMap; /// One installed package, in the shape `findPackagesWithReplacersAndProviders` /// needs. Mirrors the fields of `Composer\Package\PackageInterface` that the @@ -33,9 +32,9 @@ pub struct InstalledCandidate { /// Original-case version, used in user-facing output. pub pretty_version: String, /// `provide` map: target package name → constraint string. - pub provides: BTreeMap<String, String>, + pub provides: indexmap::IndexMap<String, String>, /// `replace` map: target package name → constraint string. - pub replaces: BTreeMap<String, String>, + pub replaces: indexmap::IndexMap<String, String>, } #[derive(Debug, Clone, Default)] @@ -106,8 +105,8 @@ mod tests { pretty_name: name.to_string(), version: version.to_string(), pretty_version: version.to_string(), - provides: BTreeMap::new(), - replaces: BTreeMap::new(), + provides: indexmap::IndexMap::new(), + replaces: indexmap::IndexMap::new(), } } diff --git a/crates/mozart-core/src/package.rs b/crates/mozart-core/src/package.rs index c6a3ae9..de88ffc 100644 --- a/crates/mozart-core/src/package.rs +++ b/crates/mozart-core/src/package.rs @@ -1,14 +1,18 @@ use serde::de::{Deserializer, MapAccess, SeqAccess, Visitor}; use serde::{Deserialize, Serialize}; -use std::collections::BTreeMap; use std::fmt; use std::fs; use std::path::Path; pub mod archiver; +mod complete_package_interface; pub mod dumper; +mod package_interface; pub mod version; +pub use complete_package_interface::*; +pub use package_interface::*; + /// Package stability level. /// Higher value = less stable. /// Corresponds to `Composer\Package\BasePackage::STABILITY_*`. @@ -62,8 +66,8 @@ pub struct Author { /// Autoload rule sets (PSR-4, PSR-0, classmap, files). #[derive(Debug, Clone, Default)] pub struct AutoloadRules { - pub psr4: BTreeMap<String, Vec<String>>, - pub psr0: BTreeMap<String, Vec<String>>, + pub psr4: indexmap::IndexMap<String, Vec<String>>, + pub psr0: indexmap::IndexMap<String, Vec<String>>, pub classmap: Vec<String>, pub files: Vec<String>, } @@ -125,19 +129,19 @@ pub struct PackageData { pub dist_sha1_checksum: Option<String>, pub release_date: Option<String>, - pub extra: BTreeMap<String, serde_json::Value>, + pub extra: indexmap::IndexMap<String, serde_json::Value>, pub binaries: Vec<String>, pub dev: bool, pub stability: Stability, pub notification_url: Option<String>, // dependency links - pub requires: BTreeMap<String, Link>, - pub conflicts: BTreeMap<String, Link>, - pub provides: BTreeMap<String, Link>, - pub replaces: BTreeMap<String, Link>, - pub dev_requires: BTreeMap<String, Link>, - pub suggests: BTreeMap<String, String>, + pub requires: indexmap::IndexMap<String, Link>, + pub conflicts: indexmap::IndexMap<String, Link>, + pub provides: indexmap::IndexMap<String, Link>, + pub replaces: indexmap::IndexMap<String, Link>, + pub dev_requires: indexmap::IndexMap<String, Link>, + pub suggests: indexmap::IndexMap<String, String>, // autoload pub autoload: AutoloadRules, @@ -157,7 +161,7 @@ pub struct CompletePackageData { pub license: Vec<String>, pub keywords: Vec<String>, pub authors: Vec<Author>, - pub scripts: BTreeMap<String, Vec<String>>, + pub scripts: indexmap::IndexMap<String, Vec<String>>, pub support: Support, pub funding: Vec<Funding>, pub repositories: Vec<serde_json::Value>, @@ -175,105 +179,55 @@ pub struct RootPackageData { pub minimum_stability: Stability, pub prefer_stable: bool, - pub stability_flags: BTreeMap<String, Stability>, - pub config: BTreeMap<String, serde_json::Value>, - pub references: BTreeMap<String, String>, + pub stability_flags: indexmap::IndexMap<String, Stability>, + pub config: indexmap::IndexMap<String, serde_json::Value>, + pub references: indexmap::IndexMap<String, String>, pub aliases: Vec<VersionAlias>, } -/// Accessor for `PackageData` fields. -/// Corresponds to `Composer\Package\PackageInterface`. -pub trait Package { - fn name(&self) -> &str; - fn pretty_name(&self) -> &str; - fn version(&self) -> &str; - fn pretty_version(&self) -> &str; - fn package_type(&self) -> &str; - fn target_dir(&self) -> Option<&str>; - fn source_type(&self) -> Option<&str>; - fn source_url(&self) -> Option<&str>; - fn source_reference(&self) -> Option<&str>; - fn dist_type(&self) -> Option<&str>; - fn dist_url(&self) -> Option<&str>; - fn dist_reference(&self) -> Option<&str>; - fn dist_sha1_checksum(&self) -> Option<&str>; - fn release_date(&self) -> Option<&str>; - fn extra(&self) -> &BTreeMap<String, serde_json::Value>; - fn binaries(&self) -> &[String]; - fn is_dev(&self) -> bool; - fn stability(&self) -> Stability; - fn notification_url(&self) -> Option<&str>; - fn requires(&self) -> &BTreeMap<String, Link>; - fn conflicts(&self) -> &BTreeMap<String, Link>; - fn provides(&self) -> &BTreeMap<String, Link>; - fn replaces(&self) -> &BTreeMap<String, Link>; - fn dev_requires(&self) -> &BTreeMap<String, Link>; - fn suggests(&self) -> &BTreeMap<String, String>; - fn autoload(&self) -> &AutoloadRules; - fn dev_autoload(&self) -> &AutoloadRules; - fn is_default_branch(&self) -> bool; -} - -/// Accessor for `CompletePackageData` fields. -/// Corresponds to `Composer\Package\CompletePackageInterface`. -pub trait CompletePackage: Package { - fn description(&self) -> Option<&str>; - fn homepage(&self) -> Option<&str>; - fn license(&self) -> &[String]; - fn keywords(&self) -> &[String]; - fn authors(&self) -> &[Author]; - fn scripts(&self) -> &BTreeMap<String, Vec<String>>; - fn support(&self) -> &Support; - fn funding(&self) -> &[Funding]; - fn repositories(&self) -> &[serde_json::Value]; - fn abandoned(&self) -> Option<&str>; - fn archive_name(&self) -> Option<&str>; - fn archive_excludes(&self) -> &[String]; -} - /// Accessor for `RootPackageData` fields. /// Corresponds to `Composer\Package\RootPackageInterface`. -pub trait RootPackage: CompletePackage { +pub trait RootPackage: CompletePackageInterface { fn minimum_stability(&self) -> Stability; fn prefer_stable(&self) -> bool; - fn stability_flags(&self) -> &BTreeMap<String, Stability>; - fn config(&self) -> &BTreeMap<String, serde_json::Value>; - fn references(&self) -> &BTreeMap<String, String>; + fn stability_flags(&self) -> &indexmap::IndexMap<String, Stability>; + fn config(&self) -> &indexmap::IndexMap<String, serde_json::Value>; + fn references(&self) -> &indexmap::IndexMap<String, String>; fn aliases(&self) -> &[VersionAlias]; } /// Implements `Package` trait by delegating to an inner `PackageData` field. macro_rules! delegate_package { ($type:ty => $($path:ident).+) => { - impl Package for $type { - fn name(&self) -> &str { &self.$($path).+.name } - fn pretty_name(&self) -> &str { &self.$($path).+.pretty_name } - fn version(&self) -> &str { &self.$($path).+.version } - fn pretty_version(&self) -> &str { &self.$($path).+.pretty_version } - fn package_type(&self) -> &str { &self.$($path).+.package_type } - fn target_dir(&self) -> Option<&str> { self.$($path).+.target_dir.as_deref() } - fn source_type(&self) -> Option<&str> { self.$($path).+.source_type.as_deref() } - fn source_url(&self) -> Option<&str> { self.$($path).+.source_url.as_deref() } - fn source_reference(&self) -> Option<&str> { self.$($path).+.source_reference.as_deref() } - fn dist_type(&self) -> Option<&str> { self.$($path).+.dist_type.as_deref() } - fn dist_url(&self) -> Option<&str> { self.$($path).+.dist_url.as_deref() } - fn dist_reference(&self) -> Option<&str> { self.$($path).+.dist_reference.as_deref() } - fn dist_sha1_checksum(&self) -> Option<&str> { self.$($path).+.dist_sha1_checksum.as_deref() } - fn release_date(&self) -> Option<&str> { self.$($path).+.release_date.as_deref() } - fn extra(&self) -> &BTreeMap<String, serde_json::Value> { &self.$($path).+.extra } - fn binaries(&self) -> &[String] { &self.$($path).+.binaries } - fn is_dev(&self) -> bool { self.$($path).+.dev } - fn stability(&self) -> Stability { self.$($path).+.stability } - fn notification_url(&self) -> Option<&str> { self.$($path).+.notification_url.as_deref() } - fn requires(&self) -> &BTreeMap<String, Link> { &self.$($path).+.requires } - fn conflicts(&self) -> &BTreeMap<String, Link> { &self.$($path).+.conflicts } - fn provides(&self) -> &BTreeMap<String, Link> { &self.$($path).+.provides } - fn replaces(&self) -> &BTreeMap<String, Link> { &self.$($path).+.replaces } - fn dev_requires(&self) -> &BTreeMap<String, Link> { &self.$($path).+.dev_requires } - fn suggests(&self) -> &BTreeMap<String, String> { &self.$($path).+.suggests } - fn autoload(&self) -> &AutoloadRules { &self.$($path).+.autoload } - fn dev_autoload(&self) -> &AutoloadRules { &self.$($path).+.dev_autoload } - fn is_default_branch(&self) -> bool { self.$($path).+.is_default_branch } + impl PackageInterface for $type { + fn name(&self) -> &str { &self.$($path).+.name } + fn pretty_name(&self) -> &str { &self.$($path).+.pretty_name } + fn version(&self) -> &str { &self.$($path).+.version } + fn pretty_version(&self) -> &str { &self.$($path).+.pretty_version } + fn package_type(&self) -> &str { &self.$($path).+.package_type } + fn target_dir(&self) -> Option<&str> { self.$($path).+.target_dir.as_deref() } + fn source_type(&self) -> Option<&str> { self.$($path).+.source_type.as_deref() } + fn source_url(&self) -> Option<&str> { self.$($path).+.source_url.as_deref() } + fn source_reference(&self) -> Option<&str> { self.$($path).+.source_reference.as_deref() } + fn dist_type(&self) -> Option<&str> { self.$($path).+.dist_type.as_deref() } + fn dist_url(&self) -> Option<&str> { self.$($path).+.dist_url.as_deref() } + fn dist_reference(&self) -> Option<&str> { self.$($path).+.dist_reference.as_deref() } + fn dist_sha1_checksum(&self) -> Option<&str> { self.$($path).+.dist_sha1_checksum.as_deref() } + fn release_date(&self) -> Option<&str> { self.$($path).+.release_date.as_deref() } + fn extra(&self) -> &indexmap::IndexMap<String, serde_json::Value> { &self.$($path).+.extra } + fn binaries(&self) -> &[String] { &self.$($path).+.binaries } + fn is_dev(&self) -> bool { self.$($path).+.dev } + fn stability(&self) -> Stability { self.$($path).+.stability } + fn notification_url(&self) -> Option<&str> { self.$($path).+.notification_url.as_deref() } + fn requires(&self) -> &indexmap::IndexMap<String, Link> { &self.$($path).+.requires } + fn conflicts(&self) -> &indexmap::IndexMap<String, Link> { &self.$($path).+.conflicts } + fn provides(&self) -> &indexmap::IndexMap<String, Link> { &self.$($path).+.provides } + fn replaces(&self) -> &indexmap::IndexMap<String, Link> { &self.$($path).+.replaces } + fn dev_requires(&self) -> &indexmap::IndexMap<String, Link> { &self.$($path).+.dev_requires } + fn suggests(&self) -> &indexmap::IndexMap<String, String> { &self.$($path).+.suggests } + fn autoload(&self) -> &AutoloadRules { &self.$($path).+.autoload } + fn dev_autoload(&self) -> &AutoloadRules { &self.$($path).+.dev_autoload } + fn is_default_branch(&self) -> bool { self.$($path).+.is_default_branch } } }; } @@ -281,24 +235,24 @@ macro_rules! delegate_package { /// Implements `CompletePackage` trait by delegating to an inner `CompletePackageData` field. macro_rules! delegate_complete_package { ($type:ty => $($path:ident).+) => { - impl CompletePackage for $type { - fn description(&self) -> Option<&str> { self.$($path).+.description.as_deref() } - fn homepage(&self) -> Option<&str> { self.$($path).+.homepage.as_deref() } - fn license(&self) -> &[String] { &self.$($path).+.license } - fn keywords(&self) -> &[String] { &self.$($path).+.keywords } - fn authors(&self) -> &[Author] { &self.$($path).+.authors } - fn scripts(&self) -> &BTreeMap<String, Vec<String>> { &self.$($path).+.scripts } - fn support(&self) -> &Support { &self.$($path).+.support } - fn funding(&self) -> &[Funding] { &self.$($path).+.funding } - fn repositories(&self) -> &[serde_json::Value] { &self.$($path).+.repositories } - fn abandoned(&self) -> Option<&str> { self.$($path).+.abandoned.as_deref() } - fn archive_name(&self) -> Option<&str> { self.$($path).+.archive_name.as_deref() } - fn archive_excludes(&self) -> &[String] { &self.$($path).+.archive_excludes } + impl CompletePackageInterface for $type { + fn description(&self) -> Option<&str> { self.$($path).+.description.as_deref() } + fn homepage(&self) -> Option<&str> { self.$($path).+.homepage.as_deref() } + fn license(&self) -> &[String] { &self.$($path).+.license } + fn keywords(&self) -> &[String] { &self.$($path).+.keywords } + fn authors(&self) -> &[Author] { &self.$($path).+.authors } + fn scripts(&self) -> &indexmap::IndexMap<String, Vec<String>> { &self.$($path).+.scripts } + fn support(&self) -> &Support { &self.$($path).+.support } + fn funding(&self) -> &[Funding] { &self.$($path).+.funding } + fn repositories(&self) -> &[serde_json::Value] { &self.$($path).+.repositories } + fn abandoned(&self) -> Option<&str> { self.$($path).+.abandoned.as_deref() } + fn archive_name(&self) -> Option<&str> { self.$($path).+.archive_name.as_deref() } + fn archive_excludes(&self) -> &[String] { &self.$($path).+.archive_excludes } } }; } -impl Package for PackageData { +impl PackageInterface for PackageData { fn name(&self) -> &str { &self.name } @@ -341,7 +295,7 @@ impl Package for PackageData { fn release_date(&self) -> Option<&str> { self.release_date.as_deref() } - fn extra(&self) -> &BTreeMap<String, serde_json::Value> { + fn extra(&self) -> &indexmap::IndexMap<String, serde_json::Value> { &self.extra } fn binaries(&self) -> &[String] { @@ -356,22 +310,22 @@ impl Package for PackageData { fn notification_url(&self) -> Option<&str> { self.notification_url.as_deref() } - fn requires(&self) -> &BTreeMap<String, Link> { + fn requires(&self) -> &indexmap::IndexMap<String, Link> { &self.requires } - fn conflicts(&self) -> &BTreeMap<String, Link> { + fn conflicts(&self) -> &indexmap::IndexMap<String, Link> { &self.conflicts } - fn provides(&self) -> &BTreeMap<String, Link> { + fn provides(&self) -> &indexmap::IndexMap<String, Link> { &self.provides } - fn replaces(&self) -> &BTreeMap<String, Link> { + fn replaces(&self) -> &indexmap::IndexMap<String, Link> { &self.replaces } - fn dev_requires(&self) -> &BTreeMap<String, Link> { + fn dev_requires(&self) -> &indexmap::IndexMap<String, Link> { &self.dev_requires } - fn suggests(&self) -> &BTreeMap<String, String> { + fn suggests(&self) -> &indexmap::IndexMap<String, String> { &self.suggests } fn autoload(&self) -> &AutoloadRules { @@ -385,7 +339,7 @@ impl Package for PackageData { } } -impl CompletePackage for CompletePackageData { +impl CompletePackageInterface for CompletePackageData { fn description(&self) -> Option<&str> { self.description.as_deref() } @@ -401,7 +355,7 @@ impl CompletePackage for CompletePackageData { fn authors(&self) -> &[Author] { &self.authors } - fn scripts(&self) -> &BTreeMap<String, Vec<String>> { + fn scripts(&self) -> &indexmap::IndexMap<String, Vec<String>> { &self.scripts } fn support(&self) -> &Support { @@ -431,13 +385,13 @@ impl RootPackage for RootPackageData { fn prefer_stable(&self) -> bool { self.prefer_stable } - fn stability_flags(&self) -> &BTreeMap<String, Stability> { + fn stability_flags(&self) -> &indexmap::IndexMap<String, Stability> { &self.stability_flags } - fn config(&self) -> &BTreeMap<String, serde_json::Value> { + fn config(&self) -> &indexmap::IndexMap<String, serde_json::Value> { &self.config } - fn references(&self) -> &BTreeMap<String, String> { + fn references(&self) -> &indexmap::IndexMap<String, String> { &self.references } fn aliases(&self) -> &[VersionAlias] { @@ -489,23 +443,23 @@ pub struct RawPackageData { pub minimum_stability: Option<String>, #[serde(default)] - pub require: BTreeMap<String, String>, + pub require: indexmap::IndexMap<String, String>, #[serde( rename = "require-dev", default, - skip_serializing_if = "BTreeMap::is_empty" + skip_serializing_if = "indexmap::IndexMap::is_empty" )] - pub require_dev: BTreeMap<String, String>, + pub require_dev: indexmap::IndexMap<String, String>, - #[serde(default, skip_serializing_if = "BTreeMap::is_empty")] - pub conflict: BTreeMap<String, String>, + #[serde(default, skip_serializing_if = "indexmap::IndexMap::is_empty")] + pub conflict: indexmap::IndexMap<String, String>, - #[serde(default, skip_serializing_if = "BTreeMap::is_empty")] - pub provide: BTreeMap<String, String>, + #[serde(default, skip_serializing_if = "indexmap::IndexMap::is_empty")] + pub provide: indexmap::IndexMap<String, String>, - #[serde(default, skip_serializing_if = "BTreeMap::is_empty")] - pub replace: BTreeMap<String, String>, + #[serde(default, skip_serializing_if = "indexmap::IndexMap::is_empty")] + pub replace: indexmap::IndexMap<String, String>, /// `repositories` accepts either a JSON array or a JSON object keyed by /// repository name. Composer iterates `foreach ($repoConfigs as ...)` in @@ -525,7 +479,7 @@ pub struct RawPackageData { pub bin: Vec<String>, #[serde(flatten)] - pub extra_fields: BTreeMap<String, serde_json::Value>, + pub extra_fields: indexmap::IndexMap<String, serde_json::Value>, } #[derive(Debug, Clone, Serialize, Deserialize)] @@ -539,7 +493,7 @@ pub struct RawAuthor { #[derive(Debug, Clone, Serialize, Deserialize)] pub struct RawAutoload { #[serde(rename = "psr-4")] - pub psr4: BTreeMap<String, String>, + pub psr4: indexmap::IndexMap<String, String>, } #[derive(Debug, Clone, Serialize, Deserialize)] @@ -653,15 +607,15 @@ impl RawPackageData { license: None, authors: Vec::new(), minimum_stability: None, - require: BTreeMap::new(), - require_dev: BTreeMap::new(), - conflict: BTreeMap::new(), - provide: BTreeMap::new(), - replace: BTreeMap::new(), + require: indexmap::IndexMap::new(), + require_dev: indexmap::IndexMap::new(), + conflict: indexmap::IndexMap::new(), + provide: indexmap::IndexMap::new(), + replace: indexmap::IndexMap::new(), repositories: Vec::new(), autoload: None, bin: Vec::new(), - extra_fields: BTreeMap::new(), + extra_fields: indexmap::IndexMap::new(), } } @@ -696,9 +650,9 @@ impl RootPackageData { pub fn from_raw(raw: RawPackageData) -> Self { fn make_links( source: &str, - deps: BTreeMap<String, String>, + deps: indexmap::IndexMap<String, String>, description: &str, - ) -> BTreeMap<String, Link> { + ) -> indexmap::IndexMap<String, Link> { deps.into_iter() .map(|(target, constraint)| { let normalized = target.to_lowercase(); @@ -745,7 +699,7 @@ impl RootPackageData { }) .unwrap_or_default(); - let extra: BTreeMap<String, serde_json::Value> = raw + let extra: indexmap::IndexMap<String, serde_json::Value> = raw .extra_fields .get("extra") .and_then(|v| v.as_object()) @@ -783,7 +737,7 @@ impl RootPackageData { }) .unwrap_or_default(); - let scripts: BTreeMap<String, Vec<String>> = raw + let scripts: indexmap::IndexMap<String, Vec<String>> = raw .extra_fields .get("scripts") .and_then(|v| v.as_object()) @@ -841,7 +795,7 @@ impl RootPackageData { }) .unwrap_or_default(); - let config: BTreeMap<String, serde_json::Value> = raw + let config: indexmap::IndexMap<String, serde_json::Value> = raw .extra_fields .get("config") .and_then(|v| v.as_object()) @@ -882,7 +836,7 @@ impl RootPackageData { provides, replaces, dev_requires, - suggests: BTreeMap::new(), + suggests: indexmap::IndexMap::new(), autoload, dev_autoload: AutoloadRules::default(), is_default_branch: false, @@ -908,9 +862,9 @@ impl RootPackageData { complete: complete_data, minimum_stability, prefer_stable, - stability_flags: BTreeMap::new(), + stability_flags: indexmap::IndexMap::new(), config, - references: BTreeMap::new(), + references: indexmap::IndexMap::new(), aliases: Vec::new(), } } @@ -976,7 +930,7 @@ mod tests { security_advisories: None, }]; - let mut psr4 = BTreeMap::new(); + let mut psr4 = indexmap::IndexMap::new(); psr4.insert("Acme\\Full\\".to_string(), "src/".to_string()); raw.autoload = Some(RawAutoload { psr4 }); diff --git a/crates/mozart-core/src/package/complete_package_interface.rs b/crates/mozart-core/src/package/complete_package_interface.rs new file mode 100644 index 0000000..c321309 --- /dev/null +++ b/crates/mozart-core/src/package/complete_package_interface.rs @@ -0,0 +1,17 @@ +use crate::package::{Author, Funding, PackageInterface, Support}; + +/// ref: \Composer\Package\CompletePackageInterface +pub trait CompletePackageInterface: PackageInterface { + fn description(&self) -> Option<&str>; + fn homepage(&self) -> Option<&str>; + fn license(&self) -> &[String]; + fn keywords(&self) -> &[String]; + fn authors(&self) -> &[Author]; + fn scripts(&self) -> &indexmap::IndexMap<String, Vec<String>>; + fn support(&self) -> &Support; + fn funding(&self) -> &[Funding]; + fn repositories(&self) -> &[serde_json::Value]; + fn abandoned(&self) -> Option<&str>; + fn archive_name(&self) -> Option<&str>; + fn archive_excludes(&self) -> &[String]; +} diff --git a/crates/mozart-core/src/package/package_interface.rs b/crates/mozart-core/src/package/package_interface.rs new file mode 100644 index 0000000..7006657 --- /dev/null +++ b/crates/mozart-core/src/package/package_interface.rs @@ -0,0 +1,33 @@ +use crate::package::{AutoloadRules, Link, Stability}; + +/// ref: \Composer\Package\PackageInterface +pub trait PackageInterface { + fn name(&self) -> &str; + fn pretty_name(&self) -> &str; + fn version(&self) -> &str; + fn pretty_version(&self) -> &str; + fn package_type(&self) -> &str; + fn target_dir(&self) -> Option<&str>; + fn source_type(&self) -> Option<&str>; + fn source_url(&self) -> Option<&str>; + fn source_reference(&self) -> Option<&str>; + fn dist_type(&self) -> Option<&str>; + fn dist_url(&self) -> Option<&str>; + fn dist_reference(&self) -> Option<&str>; + fn dist_sha1_checksum(&self) -> Option<&str>; + fn release_date(&self) -> Option<&str>; + fn extra(&self) -> &indexmap::IndexMap<String, serde_json::Value>; + fn binaries(&self) -> &[String]; + fn is_dev(&self) -> bool; + fn stability(&self) -> Stability; + fn notification_url(&self) -> Option<&str>; + fn requires(&self) -> &indexmap::IndexMap<String, Link>; + fn conflicts(&self) -> &indexmap::IndexMap<String, Link>; + fn provides(&self) -> &indexmap::IndexMap<String, Link>; + fn replaces(&self) -> &indexmap::IndexMap<String, Link>; + fn dev_requires(&self) -> &indexmap::IndexMap<String, Link>; + fn suggests(&self) -> &indexmap::IndexMap<String, String>; + fn autoload(&self) -> &AutoloadRules; + fn dev_autoload(&self) -> &AutoloadRules; + fn is_default_branch(&self) -> bool; +} diff --git a/crates/mozart-core/src/repository/browse_repos.rs b/crates/mozart-core/src/repository/browse_repos.rs index 83a40f1..a174637 100644 --- a/crates/mozart-core/src/repository/browse_repos.rs +++ b/crates/mozart-core/src/repository/browse_repos.rs @@ -8,8 +8,8 @@ //! `CompletePackageInterface` (`getSupport()['source']`, //! `getSourceUrl()`, `getHomepage()`). -use super::super::package::Package as _; -use super::super::package::{CompletePackage as _, RootPackageData}; +use super::super::package::PackageInterface as _; +use super::super::package::{CompletePackageInterface as _, RootPackageData}; use super::cache::Cache; use super::installed::{InstalledPackageEntry, InstalledPackages}; use super::lockfile::LockedPackage; @@ -167,7 +167,6 @@ impl BrowseRepos { mod tests { use super::*; use crate::package::RawPackageData; - use std::collections::BTreeMap; fn locked( name: &str, @@ -185,11 +184,11 @@ mod tests { reference: None, }), dist: None, - require: BTreeMap::new(), - require_dev: BTreeMap::new(), - conflict: BTreeMap::new(), - provide: BTreeMap::new(), - replace: BTreeMap::new(), + require: indexmap::IndexMap::new(), + require_dev: indexmap::IndexMap::new(), + conflict: indexmap::IndexMap::new(), + provide: indexmap::IndexMap::new(), + replace: indexmap::IndexMap::new(), suggest: None, package_type: None, autoload: None, @@ -202,7 +201,7 @@ mod tests { support: support_source.map(|s| serde_json::json!({"source": s})), funding: None, time: None, - extra_fields: BTreeMap::new(), + extra_fields: indexmap::IndexMap::new(), } } @@ -240,7 +239,7 @@ mod tests { aliases: vec![], homepage: Some("https://vendor.example.com".to_string()), support: Some(serde_json::json!({"source": "https://github.com/vendor/pkg"})), - extra_fields: BTreeMap::new(), + extra_fields: indexmap::IndexMap::new(), }; let view = CompletePackageView::from(&entry); assert_eq!( diff --git a/crates/mozart-core/src/repository/installed.rs b/crates/mozart-core/src/repository/installed.rs index 422f79f..4bee0e5 100644 --- a/crates/mozart-core/src/repository/installed.rs +++ b/crates/mozart-core/src/repository/installed.rs @@ -1,7 +1,6 @@ use crate::installer::HasSuggests; use crate::package::to_json_pretty; use serde::{Deserialize, Serialize}; -use std::collections::BTreeMap; use std::fs; use std::path::Path; @@ -56,7 +55,7 @@ pub struct InstalledPackageEntry { pub support: Option<serde_json::Value>, #[serde(flatten)] - pub extra_fields: BTreeMap<String, serde_json::Value>, + pub extra_fields: indexmap::IndexMap<String, serde_json::Value>, } impl HasSuggests for InstalledPackageEntry { @@ -215,7 +214,7 @@ mod tests { aliases: vec![], homepage: None, support: None, - extra_fields: BTreeMap::new(), + extra_fields: indexmap::IndexMap::new(), } } diff --git a/crates/mozart-core/src/repository/lockfile.rs b/crates/mozart-core/src/repository/lockfile.rs index 146506d..cde7530 100644 --- a/crates/mozart-core/src/repository/lockfile.rs +++ b/crates/mozart-core/src/repository/lockfile.rs @@ -2,12 +2,12 @@ use super::packagist::{PackagistDist, PackagistSource, PackagistVersion}; use super::repository::RepositorySet; use super::resolver::ResolvedPackage; use crate::installer::HasSuggests; -use crate::package::Package as _; +use crate::package::PackageInterface as _; use crate::package::{Link, RawPackageData, to_json_pretty}; use indexmap::IndexMap; use indexmap::IndexSet; use serde::{Deserialize, Serialize}; -use std::collections::{BTreeMap, VecDeque}; +use std::collections::VecDeque; use std::fs; use std::path::Path; @@ -76,27 +76,27 @@ pub struct LockedPackage { #[serde(skip_serializing_if = "Option::is_none")] pub dist: Option<LockedDist>, - #[serde(default, skip_serializing_if = "BTreeMap::is_empty")] - pub require: BTreeMap<String, String>, + #[serde(default, skip_serializing_if = "indexmap::IndexMap::is_empty")] + pub require: indexmap::IndexMap<String, String>, #[serde( rename = "require-dev", default, - skip_serializing_if = "BTreeMap::is_empty" + skip_serializing_if = "indexmap::IndexMap::is_empty" )] - pub require_dev: BTreeMap<String, String>, + pub require_dev: indexmap::IndexMap<String, String>, - #[serde(default, skip_serializing_if = "BTreeMap::is_empty")] - pub conflict: BTreeMap<String, String>, + #[serde(default, skip_serializing_if = "indexmap::IndexMap::is_empty")] + pub conflict: indexmap::IndexMap<String, String>, - #[serde(default, skip_serializing_if = "BTreeMap::is_empty")] - pub provide: BTreeMap<String, String>, + #[serde(default, skip_serializing_if = "indexmap::IndexMap::is_empty")] + pub provide: indexmap::IndexMap<String, String>, - #[serde(default, skip_serializing_if = "BTreeMap::is_empty")] - pub replace: BTreeMap<String, String>, + #[serde(default, skip_serializing_if = "indexmap::IndexMap::is_empty")] + pub replace: indexmap::IndexMap<String, String>, #[serde(skip_serializing_if = "Option::is_none")] - pub suggest: Option<BTreeMap<String, String>>, + pub suggest: Option<indexmap::IndexMap<String, String>>, #[serde(rename = "type", skip_serializing_if = "Option::is_none")] pub package_type: Option<String>, @@ -133,7 +133,7 @@ pub struct LockedPackage { /// Catch-all for extra fields we don't explicitly model #[serde(flatten)] - pub extra_fields: BTreeMap<String, serde_json::Value>, + pub extra_fields: indexmap::IndexMap<String, serde_json::Value>, } impl HasSuggests for LockedPackage { @@ -231,9 +231,9 @@ impl LockFile { ]; // Collect relevant keys into a BTreeMap (auto-sorted by key) - let mut filtered: BTreeMap<&str, &serde_json::Value> = BTreeMap::new(); - for key in &relevant_keys { - if let Some(v) = obj.get(*key) { + let mut filtered = std::collections::BTreeMap::new(); + for key in relevant_keys { + if let Some(v) = obj.get(key) { filtered.insert(key, v); } } @@ -396,7 +396,7 @@ pub fn locked_package_branch_aliases(pkg: &LockedPackage) -> Vec<LockAlias> { } fn check_requirement_set( - requires: &BTreeMap<String, Link>, + requires: &IndexMap<String, Link>, description: &str, pool: &[LockedSearchEntry], messages: &mut Vec<String>, @@ -626,10 +626,10 @@ fn packagist_dist_to_locked(pd: &PackagistDist) -> LockedDist { /// `dev` after stripping the reference are left out (matching the /// `'dev' === VersionParser::parseStability(...)` guard in PHP). fn extract_root_references( - require: &BTreeMap<String, String>, - require_dev: &BTreeMap<String, String>, -) -> BTreeMap<String, String> { - let mut out = BTreeMap::new(); + require: &IndexMap<String, String>, + require_dev: &IndexMap<String, String>, +) -> indexmap::IndexMap<String, String> { + let mut out = indexmap::IndexMap::new(); for (name, raw_constraint) in require.iter().chain(require_dev.iter()) { if let Some(reference) = parse_inline_reference(raw_constraint) { out.insert(name.to_lowercase(), reference); @@ -730,7 +730,7 @@ fn rewrite_known_dist_url_reference(url: &str, reference: &str) -> String { /// Convert a `PackagistVersion` to a `LockedPackage`. fn packagist_version_to_locked_package(name: &str, pv: &PackagistVersion) -> LockedPackage { - let mut extra_fields: BTreeMap<String, serde_json::Value> = BTreeMap::new(); + let mut extra_fields = indexmap::IndexMap::new(); if let Some(extra) = &pv.extra { extra_fields.insert("extra".to_string(), extra.clone()); @@ -808,8 +808,8 @@ fn packagist_version_to_locked_package(name: &str, pv: &PackagistVersion) -> Loc /// declares `provide: { provided/pkg: 1.0.0 }`. fn classify_dev_packages( resolved: &[ResolvedPackage], - require: &BTreeMap<String, String>, - _require_dev: &BTreeMap<String, String>, + require: &IndexMap<String, String>, + _require_dev: &IndexMap<String, String>, requires_by_name: &IndexMap<String, Vec<String>>, providers_by_name: &IndexMap<String, Vec<String>>, ) -> IndexSet<String> { @@ -874,7 +874,7 @@ fn is_platform_name(name: &str) -> bool { /// /// Filters the map to include only platform package keys (`php`, `ext-*`, `lib-*`, etc.) /// and returns them as a JSON object. -fn extract_platform_requirements(requirements: &BTreeMap<String, String>) -> serde_json::Value { +fn extract_platform_requirements(requirements: &IndexMap<String, String>) -> serde_json::Value { let map: serde_json::Map<String, serde_json::Value> = requirements .iter() .filter(|(k, _)| is_platform_name(k)) @@ -920,12 +920,12 @@ pub async fn generate_lock_file(request: &LockFileGenerationRequest) -> anyhow:: // resolver picked a new commit at the same version label) still get // their ref refreshed. struct PreservedRelationships { - require: BTreeMap<String, String>, - require_dev: BTreeMap<String, String>, - conflict: BTreeMap<String, String>, - provide: BTreeMap<String, String>, - replace: BTreeMap<String, String>, - suggest: Option<BTreeMap<String, String>>, + require: indexmap::IndexMap<String, String>, + require_dev: indexmap::IndexMap<String, String>, + conflict: indexmap::IndexMap<String, String>, + provide: indexmap::IndexMap<String, String>, + replace: indexmap::IndexMap<String, String>, + suggest: Option<indexmap::IndexMap<String, String>>, } let mut preserved_rel: IndexMap<String, PreservedRelationships> = IndexMap::new(); if let Some(prev) = &request.previous_lock { @@ -1229,11 +1229,11 @@ mod tests { reference: Some("abc123".to_string()), shasum: Some("".to_string()), }), - require: BTreeMap::new(), - require_dev: BTreeMap::new(), - conflict: BTreeMap::new(), - provide: BTreeMap::new(), - replace: BTreeMap::new(), + require: indexmap::IndexMap::new(), + require_dev: indexmap::IndexMap::new(), + conflict: indexmap::IndexMap::new(), + provide: indexmap::IndexMap::new(), + replace: indexmap::IndexMap::new(), suggest: None, package_type: Some("library".to_string()), autoload: None, @@ -1246,7 +1246,7 @@ mod tests { support: None, funding: None, time: None, - extra_fields: BTreeMap::new(), + extra_fields: indexmap::IndexMap::new(), }); lock.write_to_file(&path).unwrap(); @@ -1320,15 +1320,15 @@ mod tests { fn make_packagist_version( version: &str, version_normalized: &str, - require: BTreeMap<String, String>, + require: indexmap::IndexMap<String, String>, ) -> PackagistVersion { PackagistVersion { version: version.to_string(), version_normalized: version_normalized.to_string(), require, - replace: BTreeMap::new(), - provide: BTreeMap::new(), - conflict: BTreeMap::new(), + replace: indexmap::IndexMap::new(), + provide: indexmap::IndexMap::new(), + conflict: indexmap::IndexMap::new(), dist: Some(super::super::packagist::PackagistDist { dist_type: "zip".to_string(), url: format!("https://example.com/{version}.zip"), @@ -1340,7 +1340,7 @@ mod tests { url: "https://github.com/example/pkg.git".to_string(), reference: Some("deadbeef".to_string()), }), - require_dev: BTreeMap::new(), + require_dev: indexmap::IndexMap::new(), suggest: None, package_type: Some("library".to_string()), autoload: Some(serde_json::json!({"psr-4": {"Example\\": "src/"}})), @@ -1366,7 +1366,7 @@ mod tests { #[test] fn test_packagist_version_to_locked_package() { - let pv = make_packagist_version("1.2.3", "1.2.3.0", BTreeMap::new()); + let pv = make_packagist_version("1.2.3", "1.2.3.0", indexmap::IndexMap::new()); let locked = packagist_version_to_locked_package("example/pkg", &pv); assert_eq!(locked.name, "example/pkg"); @@ -1414,13 +1414,13 @@ mod tests { let pv = PackagistVersion { version: "1.0.0".to_string(), version_normalized: "1.0.0.0".to_string(), - require: BTreeMap::new(), - replace: BTreeMap::new(), - provide: BTreeMap::new(), - conflict: BTreeMap::new(), + require: indexmap::IndexMap::new(), + replace: indexmap::IndexMap::new(), + provide: indexmap::IndexMap::new(), + conflict: indexmap::IndexMap::new(), dist: None, source: None, - require_dev: BTreeMap::new(), + require_dev: indexmap::IndexMap::new(), suggest: None, package_type: None, autoload: None, @@ -1484,16 +1484,16 @@ mod tests { }, ]; - let mut require = BTreeMap::new(); + let mut require = indexmap::IndexMap::new(); require.insert("vendor/a".to_string(), "^1.0".to_string()); - let mut require_dev = BTreeMap::new(); + let mut require_dev = indexmap::IndexMap::new(); require_dev.insert("vendor/b".to_string(), "^1.0".to_string()); let mut metadata: IndexMap<String, PackagistVersion> = IndexMap::new(); // A requires C - let mut a_require = BTreeMap::new(); + let mut a_require = indexmap::IndexMap::new(); a_require.insert("vendor/c".to_string(), "^1.0".to_string()); metadata.insert( "vendor/a".to_string(), @@ -1501,7 +1501,7 @@ mod tests { ); // B requires D - let mut b_require = BTreeMap::new(); + let mut b_require = indexmap::IndexMap::new(); b_require.insert("vendor/d".to_string(), "^1.0".to_string()); metadata.insert( "vendor/b".to_string(), @@ -1511,11 +1511,11 @@ mod tests { // C and D have no deps metadata.insert( "vendor/c".to_string(), - make_packagist_version("1.0.0", "1.0.0.0", BTreeMap::new()), + make_packagist_version("1.0.0", "1.0.0.0", indexmap::IndexMap::new()), ); metadata.insert( "vendor/d".to_string(), - make_packagist_version("1.0.0", "1.0.0.0", BTreeMap::new()), + make_packagist_version("1.0.0", "1.0.0.0", indexmap::IndexMap::new()), ); let requires_by_name: IndexMap<String, Vec<String>> = metadata @@ -1577,16 +1577,16 @@ mod tests { }, ]; - let mut require = BTreeMap::new(); + let mut require = indexmap::IndexMap::new(); require.insert("vendor/a".to_string(), "^1.0".to_string()); - let mut require_dev = BTreeMap::new(); + let mut require_dev = indexmap::IndexMap::new(); require_dev.insert("vendor/b".to_string(), "^1.0".to_string()); let mut metadata: IndexMap<String, PackagistVersion> = IndexMap::new(); // A requires C - let mut a_require = BTreeMap::new(); + let mut a_require = indexmap::IndexMap::new(); a_require.insert("vendor/c".to_string(), "^1.0".to_string()); metadata.insert( "vendor/a".to_string(), @@ -1594,7 +1594,7 @@ mod tests { ); // B also requires C - let mut b_require = BTreeMap::new(); + let mut b_require = indexmap::IndexMap::new(); b_require.insert("vendor/c".to_string(), "^1.0".to_string()); metadata.insert( "vendor/b".to_string(), @@ -1604,7 +1604,7 @@ mod tests { // C has no deps metadata.insert( "vendor/c".to_string(), - make_packagist_version("1.0.0", "1.0.0.0", BTreeMap::new()), + make_packagist_version("1.0.0", "1.0.0.0", indexmap::IndexMap::new()), ); let requires_by_name: IndexMap<String, Vec<String>> = metadata @@ -1636,7 +1636,7 @@ mod tests { #[test] fn test_extract_platform_requirements() { - let mut requirements = BTreeMap::new(); + let mut requirements = indexmap::IndexMap::new(); requirements.insert("php".to_string(), ">=8.1".to_string()); requirements.insert("ext-json".to_string(), "*".to_string()); requirements.insert("ext-mbstring".to_string(), "*".to_string()); @@ -1669,7 +1669,7 @@ mod tests { #[test] fn test_extract_platform_requirements_empty() { - let requirements = BTreeMap::new(); + let requirements = indexmap::IndexMap::new(); let platform = extract_platform_requirements(&requirements); assert_eq!(platform, serde_json::json!({})); } @@ -1729,11 +1729,11 @@ mod tests { version_normalized: None, source: None, dist: None, - require: BTreeMap::new(), - require_dev: BTreeMap::new(), - conflict: BTreeMap::new(), - provide: BTreeMap::new(), - replace: BTreeMap::new(), + require: indexmap::IndexMap::new(), + require_dev: indexmap::IndexMap::new(), + conflict: indexmap::IndexMap::new(), + provide: indexmap::IndexMap::new(), + replace: indexmap::IndexMap::new(), suggest: None, package_type: None, autoload: None, @@ -1746,7 +1746,7 @@ mod tests { support: None, funding: None, time: None, - extra_fields: BTreeMap::new(), + extra_fields: indexmap::IndexMap::new(), }, LockedPackage { name: "vendor/alpha".to_string(), @@ -1754,11 +1754,11 @@ mod tests { version_normalized: None, source: None, dist: None, - require: BTreeMap::new(), - require_dev: BTreeMap::new(), - conflict: BTreeMap::new(), - provide: BTreeMap::new(), - replace: BTreeMap::new(), + require: indexmap::IndexMap::new(), + require_dev: indexmap::IndexMap::new(), + conflict: indexmap::IndexMap::new(), + provide: indexmap::IndexMap::new(), + replace: indexmap::IndexMap::new(), suggest: None, package_type: None, autoload: None, @@ -1771,7 +1771,7 @@ mod tests { support: None, funding: None, time: None, - extra_fields: BTreeMap::new(), + extra_fields: indexmap::IndexMap::new(), }, ]; @@ -1892,11 +1892,11 @@ mod tests { version_normalized: None, source: None, dist: None, - require: BTreeMap::new(), - require_dev: BTreeMap::new(), - conflict: BTreeMap::new(), - provide: BTreeMap::new(), - replace: BTreeMap::new(), + require: indexmap::IndexMap::new(), + require_dev: indexmap::IndexMap::new(), + conflict: indexmap::IndexMap::new(), + provide: indexmap::IndexMap::new(), + replace: indexmap::IndexMap::new(), suggest: None, package_type: Some("library".to_string()), autoload: None, @@ -1909,7 +1909,7 @@ mod tests { support: None, funding: None, time: None, - extra_fields: BTreeMap::new(), + extra_fields: indexmap::IndexMap::new(), } } diff --git a/crates/mozart-core/src/repository/packagist.rs b/crates/mozart-core/src/repository/packagist.rs index 199ff51..91b47df 100644 --- a/crates/mozart-core/src/repository/packagist.rs +++ b/crates/mozart-core/src/repository/packagist.rs @@ -55,13 +55,13 @@ pub struct PackagistVersion { pub version: String, pub version_normalized: String, #[serde(default, deserialize_with = "deserialize_unset_as_default")] - pub require: BTreeMap<String, String>, + pub require: indexmap::IndexMap<String, String>, #[serde(default, deserialize_with = "deserialize_unset_as_default")] - pub replace: BTreeMap<String, String>, + pub replace: indexmap::IndexMap<String, String>, #[serde(default, deserialize_with = "deserialize_unset_as_default")] - pub provide: BTreeMap<String, String>, + pub provide: indexmap::IndexMap<String, String>, #[serde(default, deserialize_with = "deserialize_unset_as_default")] - pub conflict: BTreeMap<String, String>, + pub conflict: indexmap::IndexMap<String, String>, #[serde(default, deserialize_with = "deserialize_unset_as_none")] pub dist: Option<PackagistDist>, #[serde(default, deserialize_with = "deserialize_unset_as_none")] @@ -72,10 +72,10 @@ pub struct PackagistVersion { default, deserialize_with = "deserialize_unset_as_default" )] - pub require_dev: BTreeMap<String, String>, + pub require_dev: indexmap::IndexMap<String, String>, #[serde(default, deserialize_with = "deserialize_unset_as_none")] - pub suggest: Option<BTreeMap<String, String>>, + pub suggest: Option<indexmap::IndexMap<String, String>>, #[serde( rename = "type", @@ -160,17 +160,17 @@ impl PackagistVersion { /// /// Returns a map from branch name (e.g. `"dev-master"`) to alias target /// (e.g. `"2.x-dev"`). Returns an empty map when no aliases are declared. - pub fn branch_aliases(&self) -> BTreeMap<String, String> { + pub fn branch_aliases(&self) -> indexmap::IndexMap<String, String> { let Some(extra) = &self.extra else { - return BTreeMap::new(); + return indexmap::IndexMap::new(); }; let Some(branch_alias) = extra.get("branch-alias") else { - return BTreeMap::new(); + return indexmap::IndexMap::new(); }; let Some(map) = branch_alias.as_object() else { - return BTreeMap::new(); + return indexmap::IndexMap::new(); }; map.iter() diff --git a/crates/mozart-core/src/repository/vcs_bridge.rs b/crates/mozart-core/src/repository/vcs_bridge.rs index 18a8420..79c0c5b 100644 --- a/crates/mozart-core/src/repository/vcs_bridge.rs +++ b/crates/mozart-core/src/repository/vcs_bridge.rs @@ -10,7 +10,6 @@ use crate::repository::resolver::{parse_normalized, version_stability}; use crate::repository::vcs::DriverConfig; use crate::vcs::repository::{VcsPackageVersion, VcsRepository}; use indexmap::IndexMap; -use std::collections::BTreeMap; /// Scan all VCS-type repositories and collect package versions. /// @@ -191,7 +190,7 @@ pub fn vcs_to_packagist_version(vpkg: &VcsPackageVersion) -> PackagistVersion { } /// Extract a dependency map from composer.json JSON. -fn extract_dep_map(json: &serde_json::Value, key: &str) -> BTreeMap<String, String> { +fn extract_dep_map(json: &serde_json::Value, key: &str) -> indexmap::IndexMap<String, String> { json.get(key) .and_then(|v| v.as_object()) .map(|obj| { diff --git a/crates/mozart-core/src/repository_utils.rs b/crates/mozart-core/src/repository_utils.rs index b16a0d6..7a797c4 100644 --- a/crates/mozart-core/src/repository_utils.rs +++ b/crates/mozart-core/src/repository_utils.rs @@ -19,7 +19,7 @@ use std::collections::BTreeSet; /// `package_name` only in that case. pub trait Required { fn package_name(&self) -> &str; - fn requires(&self) -> &std::collections::BTreeMap<String, String>; + fn requires(&self) -> &indexmap::IndexMap<String, String>; fn package_names(&self) -> Option<Vec<&str>> { None } @@ -38,8 +38,8 @@ pub trait Required { /// discovered, matching PHP's `$bucket[] = $candidate;` push pattern. pub fn filter_required_packages<P, V>( packages: &[P], - requirer_requires: &std::collections::BTreeMap<String, V>, - requirer_dev_requires: Option<&std::collections::BTreeMap<String, V>>, + requirer_requires: &indexmap::IndexMap<String, V>, + requirer_dev_requires: Option<&indexmap::IndexMap<String, V>>, ) -> Vec<usize> where P: Required, @@ -78,24 +78,23 @@ where #[cfg(test)] mod tests { use super::*; - use std::collections::BTreeMap; struct Pkg { name: String, - requires: BTreeMap<String, String>, + requires: indexmap::IndexMap<String, String>, } impl Required for Pkg { fn package_name(&self) -> &str { &self.name } - fn requires(&self) -> &BTreeMap<String, String> { + fn requires(&self) -> &indexmap::IndexMap<String, String> { &self.requires } } fn pkg(name: &str, requires: &[&str]) -> Pkg { - let mut r = BTreeMap::new(); + let mut r = indexmap::IndexMap::new(); for n in requires { r.insert(n.to_string(), "*".to_string()); } @@ -105,8 +104,8 @@ mod tests { } } - fn root_requires(names: &[&str]) -> BTreeMap<String, String> { - let mut m = BTreeMap::new(); + fn root_requires(names: &[&str]) -> indexmap::IndexMap<String, String> { + let mut m = indexmap::IndexMap::new(); for n in names { m.insert(n.to_string(), "*".to_string()); } @@ -167,7 +166,7 @@ mod tests { #[test] fn empty_requires_yields_nothing() { let packages = vec![pkg("a/a", &[]), pkg("b/b", &[])]; - let root: BTreeMap<String, String> = BTreeMap::new(); + let root: indexmap::IndexMap<_, ()> = indexmap::IndexMap::new(); let kept = filter_required_packages(&packages, &root, None); assert!(kept.is_empty()); } |
