aboutsummaryrefslogtreecommitdiffhomepage
path: root/crates/shirabe/src/repository/array_repository.rs
diff options
context:
space:
mode:
authornsfisis <nsfisis@gmail.com>2026-05-28 22:43:11 +0900
committernsfisis <nsfisis@gmail.com>2026-05-28 22:43:43 +0900
commiteea4efe87e455742ec17881ee93d8095925e8516 (patch)
tree6d242f4fdd0bf32f0494a6fbbd62bce9ed6e1dc7 /crates/shirabe/src/repository/array_repository.rs
parentcc5d73c05a0abca2eebcc8a6afa0b1543ee49850 (diff)
downloadphp-shirabe-eea4efe87e455742ec17881ee93d8095925e8516.tar.gz
php-shirabe-eea4efe87e455742ec17881ee93d8095925e8516.tar.zst
php-shirabe-eea4efe87e455742ec17881ee93d8095925e8516.zip
refactor(repository): introduce Rc<RefCell<_>> handles for repositories
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Diffstat (limited to 'crates/shirabe/src/repository/array_repository.rs')
-rw-r--r--crates/shirabe/src/repository/array_repository.rs43
1 files changed, 36 insertions, 7 deletions
diff --git a/crates/shirabe/src/repository/array_repository.rs b/crates/shirabe/src/repository/array_repository.rs
index 6467c14..3a05513 100644
--- a/crates/shirabe/src/repository/array_repository.rs
+++ b/crates/shirabe/src/repository/array_repository.rs
@@ -2,6 +2,7 @@
use std::any::Any;
use std::cell::RefCell;
+use std::rc::Weak;
use anyhow::Result;
use indexmap::IndexMap;
@@ -17,7 +18,7 @@ use crate::package::version::StabilityFilter;
use crate::package::version::VersionParser;
use crate::repository::{
AbandonedInfo, FindPackageConstraint, LoadPackagesResult, ProviderInfo, RepositoryInterface,
- SearchResult,
+ RepositoryInterfaceHandle, RepositoryInterfaceWeakHandle, SearchResult,
};
/// A repository implementation that simply stores packages in an array
@@ -29,6 +30,10 @@ pub struct ArrayRepository {
/// @var ?array<BasePackage> indexed by package unique name and used to cache hasPackage calls
pub(crate) package_map: RefCell<Option<IndexMap<String, BasePackageHandle>>>,
+
+ /// Weak reference to the outermost repository handle wrapping this `ArrayRepository`,
+ /// injected via `set_self_handle`. Used to wire package -> repository back-references.
+ self_weak: RefCell<Option<RepositoryInterfaceWeakHandle>>,
}
impl ArrayRepository {
@@ -37,6 +42,7 @@ impl ArrayRepository {
let this = Self {
packages: RefCell::new(None),
package_map: RefCell::new(None),
+ self_weak: RefCell::new(None),
};
for package in packages {
this.add_package(package)?;
@@ -49,8 +55,12 @@ impl ArrayRepository {
if self.packages.borrow().is_none() {
self.initialize();
}
- // TODO(phase-b): pass a reference to self, not a clone
- package.set_repository(todo!("self as Box<dyn RepositoryInterface>"))?;
+ // PHP: $package->setRepository($this). The back-reference is wired only once this
+ // repository (or its outermost wrapper) has been put behind a RepositoryInterfaceHandle;
+ // packages added during construction are wired later in set_self_handle.
+ if let Some(handle) = self.self_weak.borrow().as_ref().and_then(Weak::upgrade) {
+ package.set_repository(RepositoryInterfaceHandle::from_rc(handle))?;
+ }
let aliased_package: Option<PackageHandle> =
package.as_alias().map(|alias| alias.get_alias_of());
@@ -59,13 +69,13 @@ impl ArrayRepository {
.borrow_mut()
.as_mut()
.unwrap()
- .push(package.into());
+ .push(package.clone());
if let Some(aliased_package) = aliased_package {
// PHP: if ($aliasedPackage->getRepository() === null) $this->addPackage($aliasedPackage);
- // TODO(phase-c): the handle does not expose get_repository (a `RefCell`-borrowed
- // back-reference); this needs repository back-references on handles.
- let _ = aliased_package;
+ if aliased_package.get_repository().is_none() {
+ self.add_package(aliased_package.into())?;
+ }
}
// invalidate package map cache
@@ -438,4 +448,23 @@ impl RepositoryInterface for ArrayRepository {
fn as_any(&self) -> &dyn std::any::Any {
self
}
+
+ fn set_self_handle(&self, weak: RepositoryInterfaceWeakHandle) {
+ *self.self_weak.borrow_mut() = Some(weak.clone());
+ // Wire back-references for packages added before this repository was wrapped in a handle
+ // (e.g. those passed to ArrayRepository::new). Reads the field directly to avoid
+ // triggering lazy initialization in wrapper repositories.
+ if let Some(handle) = weak.upgrade() {
+ let handle = RepositoryInterfaceHandle::from_rc(handle);
+ let pkgs: Vec<BasePackageHandle> = self
+ .packages
+ .borrow()
+ .as_ref()
+ .map(|v| v.clone())
+ .unwrap_or_default();
+ for pkg in pkgs {
+ let _ = pkg.set_repository(handle.clone());
+ }
+ }
+ }
}