From d4ec1dcb6fc04ff029ded35cc2fcc14f3bbc02ad Mon Sep 17 00:00:00 2001 From: nsfisis Date: Thu, 25 Jun 2026 17:49:35 +0900 Subject: test: port 32 command/repository/downloader tests Add create_installed_json/create_composer_lock test helpers. Port command (8), repository path/forgejo/perforce/vcs (11), and fossil/hg/download_manager (13) tests. Fix production porting bugs: root_package_loader/forgejo_url/version_bumper regex delimiters, repository_manager create_repository_by_class, array_loader isset, licenses_command RefCell borrow; implement disk_free_space and touch2/touch3 via libc. Co-Authored-By: Claude Opus 4.8 (1M context) --- crates/shirabe/src/repository/handle.rs | 8 +++++++ .../shirabe/src/repository/installed_repository.rs | 6 +++-- .../shirabe/src/repository/repository_manager.rs | 26 +++++++++++++++++++--- crates/shirabe/src/repository/vcs_repository.rs | 12 +++++++++- 4 files changed, 46 insertions(+), 6 deletions(-) (limited to 'crates/shirabe/src/repository') diff --git a/crates/shirabe/src/repository/handle.rs b/crates/shirabe/src/repository/handle.rs index 2e83ef8..90a9090 100644 --- a/crates/shirabe/src/repository/handle.rs +++ b/crates/shirabe/src/repository/handle.rs @@ -148,6 +148,14 @@ impl RepositoryInterfaceHandle { // --- InstalledRepositoryInterface helpers (valid only when the wrapped repository is one) --- + /// PHP `$repository instanceof InstalledRepositoryInterface`. + pub fn is_installed_repository_interface(&self) -> bool { + self.0 + .borrow() + .as_installed_repository_interface() + .is_some() + } + pub fn is_fresh(&self) -> bool { self.0 .borrow() diff --git a/crates/shirabe/src/repository/installed_repository.rs b/crates/shirabe/src/repository/installed_repository.rs index 55ec50f..cfa5a7a 100644 --- a/crates/shirabe/src/repository/installed_repository.rs +++ b/crates/shirabe/src/repository/installed_repository.rs @@ -364,12 +364,14 @@ impl InstalledRepository { } pub fn add_repository(&mut self, repository: RepositoryInterfaceHandle) { - // TODO: type guard? assert!( repository.is::() + || repository.is_installed_repository_interface() || repository.is::() || repository.is::(), - "An InstalledRepository can contain a repository of type: LockArrayRepository, RootPackageRepository or PlatformRepository" + "An InstalledRepository can not contain a repository of type {} ({})", + repository.get_repo_name(), + repository.get_repo_name() ); self.inner.add_repository(repository); diff --git a/crates/shirabe/src/repository/repository_manager.rs b/crates/shirabe/src/repository/repository_manager.rs index 403b504..247236c 100644 --- a/crates/shirabe/src/repository/repository_manager.rs +++ b/crates/shirabe/src/repository/repository_manager.rs @@ -147,10 +147,30 @@ impl RepositoryManager { fn create_repository_by_class( &self, - _class: &str, - _config: IndexMap, + class: &str, + config: IndexMap, ) -> anyhow::Result { - todo!("Phase B: dynamic class instantiation by class name") + // PHP: `new $class($config, $this->io, $this->config, $this->httpDownloader, + // $this->eventDispatcher, $this->process)`. Rust cannot instantiate by string class name, so + // dispatch over the classes registered in `createDefaultRepositoryManager`. + match class { + "Composer\\Repository\\ComposerRepository" => Ok(RepositoryInterfaceHandle::new( + crate::repository::ComposerRepository::new( + config, + self.io.clone(), + &self.config.borrow(), + self.http_downloader.clone(), + self.event_dispatcher.clone(), + )?, + )), + "Composer\\Repository\\PackageRepository" => Ok(RepositoryInterfaceHandle::new( + crate::repository::PackageRepository::new(config), + )), + other => todo!( + "Phase B: dynamic class instantiation by class name: {}", + other + ), + } } pub fn set_repository_class(&mut self, r#type: &str, class: &str) { diff --git a/crates/shirabe/src/repository/vcs_repository.rs b/crates/shirabe/src/repository/vcs_repository.rs index 526aa01..7a143eb 100644 --- a/crates/shirabe/src/repository/vcs_repository.rs +++ b/crates/shirabe/src/repository/vcs_repository.rs @@ -264,6 +264,16 @@ impl VcsRepository { &self.version_transport_exceptions } + /// For testing only: drives `initialize` (which shells out to the VCS driver to discover + /// tags/branches and load each package) and returns the packages collected by the inner + /// `ArrayRepository`, mirroring the polymorphic `RepositoryInterface::getPackages` dispatch + /// in PHP where `VcsRepository` inherits `getPackages` from `ArrayRepository`. + pub fn __get_packages(&mut self) -> anyhow::Result> { + self.initialize()?; + use crate::repository::RepositoryInterface; + self.inner.get_packages() + } + pub fn initialize(&mut self) -> Result<()> { self.inner.initialize(); @@ -282,7 +292,7 @@ impl VcsRepository { self.version_parser = Some(VersionParser::new()); if self.loader.is_none() { self.loader = Some(Box::new(ArrayLoader::new( - Some(todo!("phase-b: clone VersionParser")), + self.version_parser.clone(), false, ))); } -- cgit v1.3.1