aboutsummaryrefslogtreecommitdiffhomepage
path: root/crates/shirabe/src
diff options
context:
space:
mode:
authornsfisis <nsfisis@gmail.com>2026-06-24 00:47:20 +0900
committernsfisis <nsfisis@gmail.com>2026-06-24 00:47:53 +0900
commit340164c64e90d44b1bdf620b514166db1f76cc98 (patch)
tree86195fe5ff8582b64e0324e9f40619e36c04948f /crates/shirabe/src
parent8fe3390d064303b86133a1d2983144a4818a7121 (diff)
downloadphp-shirabe-340164c64e90d44b1bdf620b514166db1f76cc98.tar.gz
php-shirabe-340164c64e90d44b1bdf620b514166db1f76cc98.tar.zst
php-shirabe-340164c64e90d44b1bdf620b514166db1f76cc98.zip
test: port more unimplemented tests
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Diffstat (limited to 'crates/shirabe/src')
-rw-r--r--crates/shirabe/src/installed_versions.rs14
-rw-r--r--crates/shirabe/src/package/archiver/archivable_files_finder.rs2
-rw-r--r--crates/shirabe/src/package/handle.rs9
-rw-r--r--crates/shirabe/src/question/strict_confirmation_question.rs4
-rw-r--r--crates/shirabe/src/repository/package_repository.rs87
-rw-r--r--crates/shirabe/src/util/http/proxy_manager.rs13
6 files changed, 127 insertions, 2 deletions
diff --git a/crates/shirabe/src/installed_versions.rs b/crates/shirabe/src/installed_versions.rs
index c4ef526..33286ad 100644
--- a/crates/shirabe/src/installed_versions.rs
+++ b/crates/shirabe/src/installed_versions.rs
@@ -352,6 +352,20 @@ impl InstalledVersions {
/// Returns the raw data of all installed.php which are currently loaded for custom implementations
///
/// @return array[]
+ /// Returns the first dataset loaded, which may not be what you expect. Use get_all_raw_data
+ /// instead, which returns all datasets for all autoloaders present in the process.
+ pub fn get_raw_data() -> IndexMap<String, PhpMixed> {
+ // PHP emits an E_USER_DEPRECATED notice here; there is no Rust equivalent.
+ let mut installed = INSTALLED.lock().unwrap();
+ if installed.is_none() {
+ // PHP only includes __DIR__/installed.php when loaded from its dumped location; the
+ // shim is always the source location (PHP's `else` branch), so the data is empty.
+ *installed = Some(IndexMap::new());
+ }
+
+ installed.clone().unwrap()
+ }
+
pub fn get_all_raw_data() -> Vec<IndexMap<String, PhpMixed>> {
Self::get_installed()
}
diff --git a/crates/shirabe/src/package/archiver/archivable_files_finder.rs b/crates/shirabe/src/package/archiver/archivable_files_finder.rs
index 08f8df1..67f2fda 100644
--- a/crates/shirabe/src/package/archiver/archivable_files_finder.rs
+++ b/crates/shirabe/src/package/archiver/archivable_files_finder.rs
@@ -57,7 +57,7 @@ impl ArchivableFilesFinder {
}
let relative_path = Preg::replace(
- &format!("^{}", preg_quote(&sources_clone, Some('#'))),
+ &format!("#^{}#", preg_quote(&sources_clone, Some('#'))),
"",
&fs.normalize_path(&realpath.to_string_lossy()),
);
diff --git a/crates/shirabe/src/package/handle.rs b/crates/shirabe/src/package/handle.rs
index 303983a..665efb6 100644
--- a/crates/shirabe/src/package/handle.rs
+++ b/crates/shirabe/src/package/handle.rs
@@ -1213,6 +1213,15 @@ macro_rules! impl_real_package_test_setters {
.expect("real package handle invariant")
.set_type(r#type);
}
+
+ /// For testing only: mirrors PHP `Package::setSourceType`.
+ pub fn __set_source_type(&self, r#type: Option<String>) {
+ self.0
+ .borrow_mut()
+ .as_package_mut()
+ .expect("real package handle invariant")
+ .set_source_type(r#type);
+ }
}
};
}
diff --git a/crates/shirabe/src/question/strict_confirmation_question.rs b/crates/shirabe/src/question/strict_confirmation_question.rs
index 87290ac..8d4239b 100644
--- a/crates/shirabe/src/question/strict_confirmation_question.rs
+++ b/crates/shirabe/src/question/strict_confirmation_question.rs
@@ -35,6 +35,10 @@ impl StrictConfirmationQuestion {
&self.inner
}
+ pub fn inner_mut(&mut self) -> &mut Question {
+ &mut self.inner
+ }
+
fn get_default_normalizer(&self) -> Box<dyn Fn(PhpMixed) -> PhpMixed> {
let default = self.inner.get_default();
let true_regex = self.true_answer_regex.clone();
diff --git a/crates/shirabe/src/repository/package_repository.rs b/crates/shirabe/src/repository/package_repository.rs
index 554e24a..e19d04c 100644
--- a/crates/shirabe/src/repository/package_repository.rs
+++ b/crates/shirabe/src/repository/package_repository.rs
@@ -2,12 +2,18 @@
use crate::advisory::SecurityAdvisory;
use crate::advisory::{AnySecurityAdvisory, PartialSecurityAdvisory};
+use crate::package::BasePackageHandle;
+use crate::package::PackageInterfaceHandle;
use crate::package::loader::ArrayLoader;
use crate::package::loader::ValidatingArrayLoader;
use crate::package::version::VersionParser;
use crate::repository::ArrayRepository;
use crate::repository::InvalidRepositoryException;
-use crate::repository::{AdvisoryProviderInterface, SecurityAdvisoryResult};
+use crate::repository::RepositoryInterfaceWeakHandle;
+use crate::repository::{
+ AdvisoryProviderInterface, FindPackageConstraint, LoadPackagesResult, ProviderInfo,
+ RepositoryInterface, SearchResult, SecurityAdvisoryResult,
+};
use indexmap::IndexMap;
use shirabe_external_packages::composer::pcre::Preg;
use shirabe_php_shim::{Exception, PhpMixed, RuntimeException, var_export};
@@ -80,6 +86,85 @@ impl PackageRepository {
}
}
+impl RepositoryInterface for PackageRepository {
+ // The structural methods are inherited from ArrayRepository in PHP, where they trigger the
+ // overridden initialize() that loads packages from config. Wiring that virtual dispatch is a
+ // Phase C concern; the advisory paths below are what is exercised so far.
+ fn count(&self) -> anyhow::Result<usize> {
+ todo!()
+ }
+
+ fn has_package(&self, _package: PackageInterfaceHandle) -> bool {
+ todo!()
+ }
+
+ fn find_package(
+ &mut self,
+ _name: &str,
+ _constraint: FindPackageConstraint,
+ ) -> anyhow::Result<Option<BasePackageHandle>> {
+ todo!()
+ }
+
+ fn find_packages(
+ &mut self,
+ _name: &str,
+ _constraint: Option<FindPackageConstraint>,
+ ) -> anyhow::Result<Vec<BasePackageHandle>> {
+ todo!()
+ }
+
+ fn get_packages(&mut self) -> anyhow::Result<Vec<BasePackageHandle>> {
+ todo!()
+ }
+
+ 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> {
+ todo!()
+ }
+
+ fn search(
+ &mut self,
+ _query: String,
+ _mode: i64,
+ _type: Option<String>,
+ ) -> anyhow::Result<Vec<SearchResult>> {
+ todo!()
+ }
+
+ fn get_providers(
+ &mut self,
+ _package_name: String,
+ ) -> anyhow::Result<IndexMap<String, ProviderInfo>> {
+ todo!()
+ }
+
+ fn get_repo_name(&self) -> String {
+ PackageRepository::get_repo_name(self)
+ }
+
+ fn as_advisory_provider(&self) -> Option<&dyn AdvisoryProviderInterface> {
+ Some(self)
+ }
+
+ fn as_advisory_provider_mut(&mut self) -> Option<&mut dyn AdvisoryProviderInterface> {
+ Some(self)
+ }
+
+ fn as_any(&self) -> &dyn std::any::Any {
+ self
+ }
+
+ fn set_self_handle(&self, weak: RepositoryInterfaceWeakHandle) {
+ self.inner.set_self_handle(weak);
+ }
+}
+
impl AdvisoryProviderInterface for PackageRepository {
fn has_security_advisories(&mut self) -> anyhow::Result<bool> {
Ok(!self.security_advisories.is_empty())
diff --git a/crates/shirabe/src/util/http/proxy_manager.rs b/crates/shirabe/src/util/http/proxy_manager.rs
index 37d73c0..d0ff9d9 100644
--- a/crates/shirabe/src/util/http/proxy_manager.rs
+++ b/crates/shirabe/src/util/http/proxy_manager.rs
@@ -1,5 +1,6 @@
//! ref: composer/src/Composer/Util/Http/ProxyManager.php
+use std::sync::atomic::{AtomicU64, Ordering};
use std::sync::{Mutex, OnceLock};
use crate::downloader::TransportException;
@@ -9,12 +10,17 @@ use crate::util::http::RequestProxy;
static INSTANCE: OnceLock<Mutex<Option<ProxyManager>>> = OnceLock::new();
+// Distinguishes ProxyManager instances so tests can mirror PHP `===` identity of the singleton,
+// which the Rust value-based singleton does not otherwise expose.
+static NEXT_GENERATION: AtomicU64 = AtomicU64::new(0);
+
#[derive(Debug)]
pub struct ProxyManager {
error: Option<String>,
http_proxy: Option<ProxyItem>,
https_proxy: Option<ProxyItem>,
no_proxy_handler: std::cell::RefCell<Option<NoProxyPattern>>,
+ generation: u64,
}
impl ProxyManager {
@@ -24,6 +30,7 @@ impl ProxyManager {
http_proxy: None,
https_proxy: None,
no_proxy_handler: std::cell::RefCell::new(None),
+ generation: NEXT_GENERATION.fetch_add(1, Ordering::Relaxed),
};
if let Err(e) = instance.get_proxy_data() {
instance.error = Some(e.to_string());
@@ -41,6 +48,12 @@ impl ProxyManager {
}
}
+ /// For testing only: a unique id per constructed instance, used to mirror PHP `===` identity
+ /// comparison of the ProxyManager singleton across `get_instance`/`reset`.
+ pub fn __generation(&self) -> u64 {
+ self.generation
+ }
+
pub fn has_proxy(&self) -> bool {
self.http_proxy.is_some() || self.https_proxy.is_some()
}