diff options
| author | nsfisis <nsfisis@gmail.com> | 2026-06-28 15:50:49 +0900 |
|---|---|---|
| committer | nsfisis <nsfisis@gmail.com> | 2026-06-28 15:50:49 +0900 |
| commit | e2955f0acb9e82448b1f72354e7e8dd6ab229ad5 (patch) | |
| tree | e06358115aec3057a5979e1bb144a132f1fd984e /crates/shirabe/src/repository/path_repository.rs | |
| parent | b62e7052ca528c68e9175d607e0ae3921e0784d9 (diff) | |
| download | php-shirabe-e2955f0acb9e82448b1f72354e7e8dd6ab229ad5.tar.gz php-shirabe-e2955f0acb9e82448b1f72354e7e8dd6ab229ad5.tar.zst php-shirabe-e2955f0acb9e82448b1f72354e7e8dd6ab229ad5.zip | |
feat(repository): impl RepositoryInterface for Artifact/Path/Vcs repos
The structural methods are inherited from ArrayRepository in PHP, where
the lazy package load is driven by the overridden initialize(). Without
virtual dispatch, each repository now ensures that load via a &self
ensure_initialized() before delegating to the inner ArrayRepository.
This required moving the repositories' lazily-populated state behind
interior mutability (RefCell/Cell) and adding &self find_package_internal
/find_packages_internal helpers on ArrayRepository.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Diffstat (limited to 'crates/shirabe/src/repository/path_repository.rs')
| -rw-r--r-- | crates/shirabe/src/repository/path_repository.rs | 119 |
1 files changed, 114 insertions, 5 deletions
diff --git a/crates/shirabe/src/repository/path_repository.rs b/crates/shirabe/src/repository/path_repository.rs index e5dff0e..f573ee9 100644 --- a/crates/shirabe/src/repository/path_repository.rs +++ b/crates/shirabe/src/repository/path_repository.rs @@ -11,12 +11,18 @@ use crate::config::Config; use crate::event_dispatcher::EventDispatcher; use crate::io::IOInterface; use crate::json::JsonFile; +use crate::package::BasePackageHandle; +use crate::package::PackageInterfaceHandle; use crate::package::loader::ArrayLoader; use crate::package::loader::LoaderInterface; use crate::package::version::VersionGuesser; use crate::package::version::VersionParser; use crate::repository::ArrayRepository; use crate::repository::ConfigurableRepositoryInterface; +use crate::repository::RepositoryInterfaceWeakHandle; +use crate::repository::{ + FindPackageConstraint, LoadPackagesResult, ProviderInfo, RepositoryInterface, SearchResult, +}; use crate::util::Filesystem; use crate::util::Git as GitUtil; use crate::util::HttpDownloader; @@ -28,7 +34,7 @@ use crate::util::Url; pub struct PathRepository { inner: ArrayRepository, loader: ArrayLoader, - version_guesser: VersionGuesser, + version_guesser: std::cell::RefCell<VersionGuesser>, url: String, repo_config: IndexMap<String, PhpMixed>, process: std::rc::Rc<std::cell::RefCell<ProcessExecutor>>, @@ -92,7 +98,7 @@ impl PathRepository { Ok(Self { inner: ArrayRepository::new(vec![])?, loader: ArrayLoader::new(None, true), - version_guesser, + version_guesser: std::cell::RefCell::new(version_guesser), url, repo_config, process, @@ -139,7 +145,18 @@ impl PathRepository { Ok(self.inner.has_package(package)) } - pub(crate) fn initialize(&mut self) -> anyhow::Result<()> { + // In PHP the inherited ArrayRepository methods lazily call the overridden initialize() to glob + // the configured url and load each path package. Without virtual dispatch we trigger that load + // here before delegating to the inner repository; ArrayRepository's own lazy check then sees the + // populated array and skips re-initializing it. + fn ensure_initialized(&self) -> anyhow::Result<()> { + if !self.inner.is_initialized() { + self.initialize()?; + } + Ok(()) + } + + pub(crate) fn initialize(&self) -> anyhow::Result<()> { self.inner.initialize(); let url_matches = self.get_url_matches()?; @@ -260,7 +277,9 @@ impl PathRepository { if code1 == 0 && code2 == 0 && ref1.as_string() == ref2.as_string() { package.insert( "version".to_string(), - PhpMixed::String(self.version_guesser.get_root_version_from_env()?), + PhpMixed::String( + self.version_guesser.borrow().get_root_version_from_env()?, + ), ); } } @@ -294,7 +313,10 @@ impl PathRepository { } if !package.contains_key("version") { - let version_data = self.version_guesser.guess_version(&package, &path)?; + let version_data = self + .version_guesser + .borrow_mut() + .guess_version(&package, &path)?; if let Some(version_data) = version_data { if let Some(pretty_version) = version_data .pretty_version @@ -371,3 +393,90 @@ impl PathRepository { .collect()) } } + +impl RepositoryInterface for PathRepository { + // The structural methods are inherited from ArrayRepository in PHP, where the lazy package load + // is driven by the overridden initialize(). Here each one first ensures that load has happened + // (see ensure_initialized), then delegates to the inner ArrayRepository. + fn count(&self) -> anyhow::Result<usize> { + self.ensure_initialized()?; + self.inner.count() + } + + fn has_package(&self, package: PackageInterfaceHandle) -> bool { + // TODO(phase-d): hasPackage returns bool and cannot surface an initialization error; a + // failed load leaves the inner repository with whatever packages were added before the + // failure. + let _ = self.ensure_initialized(); + self.inner.has_package(package) + } + + fn find_package( + &mut self, + name: &str, + constraint: FindPackageConstraint, + ) -> anyhow::Result<Option<BasePackageHandle>> { + self.ensure_initialized()?; + self.inner.find_package(name, constraint) + } + + fn find_packages( + &mut self, + name: &str, + constraint: Option<FindPackageConstraint>, + ) -> anyhow::Result<Vec<BasePackageHandle>> { + self.ensure_initialized()?; + self.inner.find_packages(name, constraint) + } + + fn get_packages(&mut self) -> anyhow::Result<Vec<BasePackageHandle>> { + self.ensure_initialized()?; + self.inner.get_packages() + } + + fn load_packages( + &mut self, + package_name_map: IndexMap<String, Option<shirabe_semver::constraint::AnyConstraint>>, + acceptable_stabilities: IndexMap<String, i64>, + stability_flags: IndexMap<String, i64>, + already_loaded: IndexMap<String, IndexMap<String, PackageInterfaceHandle>>, + ) -> anyhow::Result<LoadPackagesResult> { + self.ensure_initialized()?; + self.inner.load_packages( + package_name_map, + acceptable_stabilities, + stability_flags, + already_loaded, + ) + } + + fn search( + &mut self, + query: String, + mode: i64, + r#type: Option<String>, + ) -> anyhow::Result<Vec<SearchResult>> { + self.ensure_initialized()?; + self.inner.search(query, mode, r#type) + } + + fn get_providers( + &mut self, + package_name: String, + ) -> anyhow::Result<IndexMap<String, ProviderInfo>> { + self.ensure_initialized()?; + self.inner.get_providers(package_name) + } + + fn get_repo_name(&self) -> String { + PathRepository::get_repo_name(self) + } + + fn as_any(&self) -> &dyn std::any::Any { + self + } + + fn set_self_handle(&self, weak: RepositoryInterfaceWeakHandle) { + self.inner.set_self_handle(weak); + } +} |
