diff options
| author | nsfisis <nsfisis@gmail.com> | 2026-05-10 00:32:08 +0900 |
|---|---|---|
| committer | nsfisis <nsfisis@gmail.com> | 2026-05-10 00:32:08 +0900 |
| commit | 8cc1ba8a02c0318b65658f1634de378c780392b9 (patch) | |
| tree | fdd5cb61e488018891a486b25991b87c84220bb8 /crates/mozart-registry/src/browse_repos.rs | |
| parent | 72b2e877c01e67ba7edd37e34ac2eadb7a1c62c4 (diff) | |
| download | php-mozart-8cc1ba8a02c0318b65658f1634de378c780392b9.tar.gz php-mozart-8cc1ba8a02c0318b65658f1634de378c780392b9.tar.zst php-mozart-8cc1ba8a02c0318b65658f1634de378c780392b9.zip | |
refactor(workspace): consolidate crates into mozart-core
Merged mozart-archiver, mozart-autoload, mozart-registry,
mozart-sat-resolver, and mozart-vcs into mozart-core to align
the source layout with Composer's structure.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Diffstat (limited to 'crates/mozart-registry/src/browse_repos.rs')
| -rw-r--r-- | crates/mozart-registry/src/browse_repos.rs | 293 |
1 files changed, 0 insertions, 293 deletions
diff --git a/crates/mozart-registry/src/browse_repos.rs b/crates/mozart-registry/src/browse_repos.rs deleted file mode 100644 index 0f9b169..0000000 --- a/crates/mozart-registry/src/browse_repos.rs +++ /dev/null @@ -1,293 +0,0 @@ -//! Composite of repositories consulted by the `browse` command. -//! -//! Mirrors `Composer\Command\HomeCommand::initializeRepos()`: -//! root package + local installed repository + remote(s). Each repo -//! exposes a uniform [`BrowseRepo::find_packages`] that yields -//! [`CompletePackageView`]s — the trio of fields -//! `Composer\Command\HomeCommand::handlePackage` reads off -//! `CompletePackageInterface` (`getSupport()['source']`, -//! `getSourceUrl()`, `getHomepage()`). - -use crate::cache::Cache; -use crate::installed::{InstalledPackageEntry, InstalledPackages}; -use crate::lockfile::LockedPackage; -use crate::packagist::{self, PackagistVersion}; -use mozart_core::package::RawPackageData; - -/// Subset of `Composer\Package\CompletePackageInterface` consumed by -/// `HomeCommand::handlePackage`. Every backing repo flattens its -/// package shape into this so URL selection lives in one place. -#[derive(Debug, Clone, Default, PartialEq, Eq)] -pub struct CompletePackageView { - /// `$package->getSupport()['source']`. - pub support_source: Option<String>, - /// `$package->getSourceUrl()`. - pub source_url: Option<String>, - /// `$package->getHomepage()`. - pub homepage: Option<String>, -} - -impl From<&LockedPackage> for CompletePackageView { - fn from(pkg: &LockedPackage) -> Self { - Self { - support_source: pkg - .support - .as_ref() - .and_then(|s| s.get("source")) - .and_then(|s| s.as_str()) - .map(str::to_string), - source_url: pkg.source.as_ref().map(|s| s.url.clone()), - homepage: pkg.homepage.clone(), - } - } -} - -impl From<&InstalledPackageEntry> for CompletePackageView { - fn from(pkg: &InstalledPackageEntry) -> Self { - Self { - support_source: pkg - .support - .as_ref() - .and_then(|s| s.get("source")) - .and_then(|s| s.as_str()) - .map(str::to_string), - source_url: pkg - .source - .as_ref() - .and_then(|s| s.get("url")) - .and_then(|s| s.as_str()) - .map(str::to_string), - homepage: pkg.homepage.clone(), - } - } -} - -impl From<&PackagistVersion> for CompletePackageView { - fn from(pkg: &PackagistVersion) -> Self { - Self { - support_source: pkg - .support - .as_ref() - .and_then(|s| s.get("source")) - .and_then(|s| s.as_str()) - .map(str::to_string), - source_url: pkg.source.as_ref().map(|s| s.url.clone()), - homepage: pkg.homepage.clone(), - } - } -} - -/// `RawPackageData` lacks a typed `support` field — the root package's -/// `support` block lives inside `extra_fields` because the schema is not -/// yet ported. Read it manually here. -pub fn view_from_raw(pkg: &RawPackageData) -> CompletePackageView { - CompletePackageView { - support_source: pkg - .extra_fields - .get("support") - .and_then(|s| s.get("source")) - .and_then(|s| s.as_str()) - .map(str::to_string), - source_url: None, - homepage: pkg.homepage.clone(), - } -} - -/// One repository in the composite. Mirrors the three repo kinds -/// `HomeCommand::initializeRepos()` returns: -/// `RootPackageRepository` + local installed + remotes. -pub enum BrowseRepo { - /// Stand-in for `Composer\Repository\RootPackageRepository` — - /// a one-package array containing the root composer.json. - /// Boxed because `RawPackageData` is much larger than the other - /// variants (clippy::large_enum_variant). - Root(Box<RawPackageData>), - /// Stand-in for `RepositoryManager::getLocalRepository()` — - /// the installed.json view of `vendor/`. - Installed(InstalledPackages), - /// Stand-in for the configured remote. For now Mozart only knows - /// the default Packagist remote (`RepositoryFactory::defaultRepos`). - Packagist { cache: Cache }, -} - -impl BrowseRepo { - /// Mirrors `RepositoryInterface::findPackages($name)` — case-insensitive - /// match by package name, returning every match the repo holds. - pub async fn find_packages(&self, name: &str) -> anyhow::Result<Vec<CompletePackageView>> { - match self { - BrowseRepo::Root(pkg) => { - if pkg.name.eq_ignore_ascii_case(name) { - Ok(vec![view_from_raw(pkg)]) - } else { - Ok(Vec::new()) - } - } - BrowseRepo::Installed(installed) => Ok(installed - .packages - .iter() - .filter(|p| p.name.eq_ignore_ascii_case(name)) - .map(CompletePackageView::from) - .collect()), - BrowseRepo::Packagist { cache } => { - let versions = packagist::fetch_package_versions(name, cache).await?; - Ok(versions.iter().map(CompletePackageView::from).collect()) - } - } - } -} - -/// Ordered composite consulted by `HomeCommand::execute()`'s outer -/// `foreach ($repos as $repo)` loop. -pub struct BrowseRepos { - repos: Vec<BrowseRepo>, -} - -impl BrowseRepos { - /// Build the composite. `root` and `installed` are passed in - /// rather than read here so callers can decide whether to load - /// them from `Composer` (when composer.json is present) or skip - /// them entirely (the `defaultReposWithDefaultManager` fallback). - pub fn new( - root: Option<RawPackageData>, - installed: Option<InstalledPackages>, - packagist_cache: Cache, - ) -> Self { - let mut repos: Vec<BrowseRepo> = Vec::with_capacity(3); - if let Some(root) = root { - repos.push(BrowseRepo::Root(Box::new(root))); - } - if let Some(installed) = installed { - repos.push(BrowseRepo::Installed(installed)); - } - repos.push(BrowseRepo::Packagist { - cache: packagist_cache, - }); - Self { repos } - } - - pub fn iter(&self) -> std::slice::Iter<'_, BrowseRepo> { - self.repos.iter() - } -} - -#[cfg(test)] -mod tests { - use super::*; - use std::collections::BTreeMap; - - fn locked( - name: &str, - source_url: Option<&str>, - homepage: Option<&str>, - support_source: Option<&str>, - ) -> LockedPackage { - LockedPackage { - name: name.to_string(), - version: "1.0.0".to_string(), - version_normalized: None, - source: source_url.map(|url| crate::lockfile::LockedSource { - source_type: "git".to_string(), - url: url.to_string(), - reference: None, - }), - dist: None, - require: BTreeMap::new(), - require_dev: BTreeMap::new(), - conflict: BTreeMap::new(), - provide: BTreeMap::new(), - replace: BTreeMap::new(), - suggest: None, - package_type: None, - autoload: None, - autoload_dev: None, - license: None, - description: None, - homepage: homepage.map(str::to_string), - keywords: None, - authors: None, - support: support_source.map(|s| serde_json::json!({"source": s})), - funding: None, - time: None, - extra_fields: BTreeMap::new(), - } - } - - #[test] - fn view_from_locked_package_carries_three_urls() { - let pkg = locked( - "vendor/pkg", - Some("https://github.com/vendor/pkg.git"), - Some("https://vendor.example.com"), - Some("https://github.com/vendor/pkg"), - ); - let view = CompletePackageView::from(&pkg); - assert_eq!( - view.support_source.as_deref(), - Some("https://github.com/vendor/pkg") - ); - assert_eq!( - view.source_url.as_deref(), - Some("https://github.com/vendor/pkg.git") - ); - assert_eq!(view.homepage.as_deref(), Some("https://vendor.example.com")); - } - - #[test] - fn view_from_installed_entry_extracts_source_url() { - let mut entry = InstalledPackageEntry { - name: "vendor/pkg".to_string(), - version: "1.0.0".to_string(), - version_normalized: None, - source: Some(serde_json::json!({"url": "https://github.com/vendor/pkg.git"})), - dist: None, - package_type: None, - install_path: None, - autoload: None, - 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(), - }; - let view = CompletePackageView::from(&entry); - assert_eq!( - view.source_url.as_deref(), - Some("https://github.com/vendor/pkg.git") - ); - assert_eq!( - view.support_source.as_deref(), - Some("https://github.com/vendor/pkg") - ); - assert_eq!(view.homepage.as_deref(), Some("https://vendor.example.com")); - - entry.support = None; - entry.source = None; - entry.homepage = None; - let empty = CompletePackageView::from(&entry); - assert_eq!(empty, CompletePackageView::default()); - } - - #[test] - fn view_from_raw_reads_support_via_extra_fields() { - let mut raw = RawPackageData::new("vendor/root".to_string()); - raw.homepage = Some("https://vendor.example.com".to_string()); - raw.extra_fields.insert( - "support".to_string(), - serde_json::json!({"source": "https://github.com/vendor/root"}), - ); - let view = view_from_raw(&raw); - assert_eq!( - view.support_source.as_deref(), - Some("https://github.com/vendor/root") - ); - assert!(view.source_url.is_none()); - assert_eq!(view.homepage.as_deref(), Some("https://vendor.example.com")); - } - - #[tokio::test] - async fn root_repo_matches_case_insensitively() { - let raw = RawPackageData::new("Vendor/Root".to_string()); - let repo = BrowseRepo::Root(Box::new(raw)); - assert_eq!(repo.find_packages("vendor/root").await.unwrap().len(), 1); - assert_eq!(repo.find_packages("other/pkg").await.unwrap().len(), 0); - } -} |
