diff options
| author | nsfisis <nsfisis@gmail.com> | 2026-06-06 02:13:59 +0900 |
|---|---|---|
| committer | nsfisis <nsfisis@gmail.com> | 2026-06-06 02:13:59 +0900 |
| commit | cd25c3e193f05a5e89bca2a1c706c85fdc9c9155 (patch) | |
| tree | 86971cac4e5011af0077416e6ca674c4251496ee /crates/shirabe/src | |
| parent | b299a0c9b66523b9630b4cf6d3dca1509c3692b5 (diff) | |
| download | php-shirabe-cd25c3e193f05a5e89bca2a1c706c85fdc9c9155.tar.gz php-shirabe-cd25c3e193f05a5e89bca2a1c706c85fdc9c9155.tar.zst php-shirabe-cd25c3e193f05a5e89bca2a1c706c85fdc9c9155.zip | |
refactor(repository): make read methods fallible and take &mut self
Change RepositoryInterface and WritableRepositoryInterface read methods
(find_package, find_packages, get_packages, load_packages, search,
get_providers, get_canonical_packages) to take &mut self and return
anyhow::Result, so lazy-loading repositories such as ComposerRepository
can perform fallible I/O and mutate internal state on access. Update all
implementors and call sites to propagate the Result and pass mutable
references.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Diffstat (limited to 'crates/shirabe/src')
56 files changed, 985 insertions, 716 deletions
diff --git a/crates/shirabe/src/autoload/autoload_generator.rs b/crates/shirabe/src/autoload/autoload_generator.rs index 9647a8d..c36125f 100644 --- a/crates/shirabe/src/autoload/autoload_generator.rs +++ b/crates/shirabe/src/autoload/autoload_generator.rs @@ -125,7 +125,7 @@ impl AutoloadGenerator { pub fn dump( &mut self, config: &Config, - local_repo: &dyn InstalledRepositoryInterface, + local_repo: &mut dyn InstalledRepositoryInterface, root_package: RootPackageInterfaceHandle, installation_manager: &mut InstallationManager, target_dir: &str, @@ -244,12 +244,12 @@ impl AutoloadGenerator { ); // Collect information from all packages. - let dev_package_names = local_repo.get_dev_package_names(); let package_map = self.build_package_map( installation_manager, root_package.clone(), - local_repo.get_canonical_packages(), + local_repo.get_canonical_packages()?, )?; + let dev_package_names = local_repo.get_dev_package_names(); let filtered_dev_packages: PhpMixed = if self.dev_mode.unwrap_or(false) { // if dev mode is enabled, then we do not filter any dev packages out so disable this entirely PhpMixed::Bool(false) diff --git a/crates/shirabe/src/command/archive_command.rs b/crates/shirabe/src/command/archive_command.rs index 18b69c3..5e60ce1 100644 --- a/crates/shirabe/src/command/archive_command.rs +++ b/crates/shirabe/src/command/archive_command.rs @@ -305,7 +305,7 @@ impl ArchiveCommand { Some(v) => Some(parser.parse_constraints(v)?.clone()), None => None, }; - let packages = repo_set.find_packages(&package_name.to_lowercase(), constraint, 0); + let packages = repo_set.find_packages(&package_name.to_lowercase(), constraint, 0)?; let package = if packages.len() > 1 { let mut version_selector = VersionSelector::new(repo_set, None)?; diff --git a/crates/shirabe/src/command/audit_command.rs b/crates/shirabe/src/command/audit_command.rs index 786843e..a28c344 100644 --- a/crates/shirabe/src/command/audit_command.rs +++ b/crates/shirabe/src/command/audit_command.rs @@ -156,11 +156,9 @@ impl AuditCommand { code: 0, }.into()); } - return Ok(CanonicalPackagesTrait::get_packages( - &*locker - .get_locked_repository(!input.get_option("no-dev").as_bool().unwrap_or(false))? - .borrow(), - )); + let locked_repo = locker + .get_locked_repository(!input.get_option("no-dev").as_bool().unwrap_or(false))?; + return locked_repo.borrow_mut().get_canonical_packages(); } let _root_pkg = composer.get_package(); diff --git a/crates/shirabe/src/command/base_dependency_command.rs b/crates/shirabe/src/command/base_dependency_command.rs index 177b0e6..5dfb13f 100644 --- a/crates/shirabe/src/command/base_dependency_command.rs +++ b/crates/shirabe/src/command/base_dependency_command.rs @@ -88,7 +88,7 @@ pub trait BaseDependencyCommand: BaseCommand { let local_repo = repository_manager.get_local_repository(); let root_pkg = composer.get_package(); - if local_repo.get_packages().len() == 0 + if local_repo.get_packages()?.len() == 0 && (root_pkg.get_requires().len() > 0 || root_pkg.get_dev_requires().len() > 0) { output.writeln( @@ -132,7 +132,7 @@ pub trait BaseDependencyCommand: BaseCommand { "*".to_string() }; - let packages = installed_repo.find_packages_with_replacers_and_providers(&needle, None); + let packages = installed_repo.find_packages_with_replacers_and_providers(&needle, None)?; if packages.is_empty() { return Err(anyhow::anyhow!(InvalidArgumentException { message: format!("Could not find package \"{}\" in your project", needle), @@ -143,9 +143,9 @@ pub trait BaseDependencyCommand: BaseCommand { let matched_package = installed_repo.find_package( &needle, FindPackageConstraint::String(text_constraint.clone()), - ); + )?; if matched_package.is_none() { - let default_repos = CompositeRepository::new( + let mut default_repos = CompositeRepository::new( RepositoryFactory::default_repos( Some(self.get_io()), Some(composer.get_config()), @@ -158,7 +158,7 @@ pub trait BaseDependencyCommand: BaseCommand { if let Some(r#match) = default_repos.find_package( &needle, FindPackageConstraint::String(text_constraint.clone()), - ) { + )? { installed_repo.add_repository( crate::repository::RepositoryInterfaceHandle::new( InstalledArrayRepository::new_with_packages(vec![ @@ -259,7 +259,7 @@ pub trait BaseDependencyCommand: BaseCommand { inverted, recursive, None, - ); + )?; if results.is_empty() { let extra = if has_constraint { format!( diff --git a/crates/shirabe/src/command/bump_command.rs b/crates/shirabe/src/command/bump_command.rs index b91a32a..f322ec0 100644 --- a/crates/shirabe/src/command/bump_command.rs +++ b/crates/shirabe/src/command/bump_command.rs @@ -241,7 +241,7 @@ impl BumpCommand { let package_opt = repo.find_package( pkg_name, crate::repository::FindPackageConstraint::String("*".to_string()), - ); + )?; let mut package = match package_opt { None => continue, Some(p) => p, diff --git a/crates/shirabe/src/command/check_platform_reqs_command.rs b/crates/shirabe/src/command/check_platform_reqs_command.rs index edacf0b..14b3be2 100644 --- a/crates/shirabe/src/command/check_platform_reqs_command.rs +++ b/crates/shirabe/src/command/check_platform_reqs_command.rs @@ -81,7 +81,7 @@ impl CheckPlatformReqsCommand { let repository_manager = composer.get_repository_manager().clone(); let repository_manager = repository_manager.borrow(); let local_repo = repository_manager.get_local_repository(); - if local_repo.get_packages().is_empty() { + if local_repo.get_packages()?.is_empty() { io.write_error(&format!( "<warning>No vendor dir present, checking {}platform requirements from the lock file</warning>", if no_dev { "non-dev " } else { "" } @@ -115,12 +115,12 @@ impl CheckPlatformReqsCommand { let root_pkg_repo = RootPackageRepository::new( crate::package::RootPackageInterfaceHandle::dup(composer.get_package()), ); - let installed_repo = InstalledRepository::new(vec![ + let mut installed_repo = InstalledRepository::new(vec![ installed_repo_base, crate::repository::RepositoryInterfaceHandle::new(root_pkg_repo), ]); - for package in installed_repo.get_packages() { + for package in installed_repo.get_packages()? { if remove_packages.contains(&package.get_name().to_string()) { continue; } @@ -149,7 +149,7 @@ impl CheckPlatformReqsCommand { 'requirements: for (require, links) in &requires_sorted { if PlatformRepository::is_platform_package(require) { let candidates = installed_repo_with_platform - .find_packages_with_replacers_and_providers(require, None); + .find_packages_with_replacers_and_providers(require, None)?; if !candidates.is_empty() { let mut req_results: Vec<CheckResult> = vec![]; 'candidates: for candidate in &candidates { diff --git a/crates/shirabe/src/command/create_project_command.rs b/crates/shirabe/src/command/create_project_command.rs index 189ccfc..8485069 100644 --- a/crates/shirabe/src/command/create_project_command.rs +++ b/crates/shirabe/src/command/create_project_command.rs @@ -788,7 +788,7 @@ impl CreateProjectCommand { } let platform_overrides = config.borrow_mut().get("platform"); - let platform_repo = PlatformRepository::new( + let mut platform_repo = PlatformRepository::new( vec![], match platform_overrides { PhpMixed::Array(m) => m @@ -805,7 +805,7 @@ impl CreateProjectCommand { )?; // find the latest version if there are multiple - let mut version_selector = VersionSelector::new(repository_set, Some(&platform_repo))?; + let mut version_selector = VersionSelector::new(repository_set, Some(&mut platform_repo))?; // TODO(phase-b): platform_requirement_filter is &dyn here but VersionSelector expects // Option<Box<dyn ...>>; pass None as placeholder. let _ = platform_requirement_filter; diff --git a/crates/shirabe/src/command/diagnose_command.rs b/crates/shirabe/src/command/diagnose_command.rs index bcedf30..d9ab5e2 100644 --- a/crates/shirabe/src/command/diagnose_command.rs +++ b/crates/shirabe/src/command/diagnose_command.rs @@ -162,12 +162,13 @@ impl DiagnoseCommand { .into_iter() .map(|(k, v)| (k, *v)) .collect(); - let platform_repo = PlatformRepository::new(vec![], platform_overrides_unboxed).unwrap(); + let mut platform_repo = + PlatformRepository::new(vec![], platform_overrides_unboxed).unwrap(); let php_pkg = <PlatformRepository as crate::repository::RepositoryInterface>::find_package( - &platform_repo, + &mut platform_repo, "php", crate::repository::FindPackageConstraint::String("*".to_string()), - ) + )? .unwrap(); let mut php_version = php_pkg.get_pretty_version().to_string(); if let Some(cp) = php_pkg.as_complete() { @@ -933,16 +934,14 @@ impl DiagnoseCommand { "url".to_string(), PhpMixed::String("https://packagist.org".to_string()), ); - // TODO(phase-b): ComposerRepository does not implement RepositoryInterface yet - let _composer_repo = ComposerRepository::new( - repo_config, - std::rc::Rc::new(std::cell::RefCell::new(NullIO::new())), - config, - self.http_downloader.clone().unwrap(), - None, - )?; - let composer_repo_as_repo: crate::repository::RepositoryInterfaceHandle = - todo!("ComposerRepository as RepositoryInterface"); + let composer_repo_as_repo = + crate::repository::RepositoryInterfaceHandle::new(ComposerRepository::new( + repo_config, + std::rc::Rc::new(std::cell::RefCell::new(NullIO::new())), + config, + self.http_downloader.clone().unwrap(), + None, + )?); repo_set.add_repository(composer_repo_as_repo)?; let mut io = BufferIO::new(String::new(), 0, None)?; diff --git a/crates/shirabe/src/command/fund_command.rs b/crates/shirabe/src/command/fund_command.rs index a01a67c..0fab473 100644 --- a/crates/shirabe/src/command/fund_command.rs +++ b/crates/shirabe/src/command/fund_command.rs @@ -56,7 +56,7 @@ impl FundCommand { let repository_manager = composer.get_repository_manager().clone(); let repository_manager = repository_manager.borrow(); let repo = repository_manager.get_local_repository(); - let remote_repos = CompositeRepository::new( + let mut remote_repos = CompositeRepository::new( repository_manager .get_repositories() .iter() @@ -67,7 +67,7 @@ impl FundCommand { let mut packages_to_load: IndexMap<String, Option<AnyConstraint>> = IndexMap::new(); let mut packages_to_load_names: indexmap::IndexSet<String> = indexmap::IndexSet::new(); - for package in repo.get_packages() { + for package in repo.get_packages()? { if package.as_alias().is_some() { continue; } @@ -84,7 +84,7 @@ impl FundCommand { IndexMap::from([("dev".to_string(), base_package::STABILITY_DEV)]), IndexMap::new(), IndexMap::new(), - ); + )?; // collect funding data from default branches for (_, package) in &result.packages { @@ -103,7 +103,7 @@ impl FundCommand { } // collect funding from installed packages if none was found in the default branch above - for package in repo.get_packages() { + for package in repo.get_packages()? { if package.as_alias().is_some() || !packages_to_load_names.contains(&package.get_name()) { continue; diff --git a/crates/shirabe/src/command/home_command.rs b/crates/shirabe/src/command/home_command.rs index e037487..69f2cca 100644 --- a/crates/shirabe/src/command/home_command.rs +++ b/crates/shirabe/src/command/home_command.rs @@ -103,7 +103,7 @@ impl HomeCommand { let mut package_exists = false; 'repos: for repo in &repos { - for package in repo.find_packages(&package_name, None) { + for package in repo.find_packages(&package_name, None)? { package_exists = true; if let Some(complete_pkg) = package.as_complete() { if self.handle_package(complete_pkg, show_homepage, show_only) { diff --git a/crates/shirabe/src/command/licenses_command.rs b/crates/shirabe/src/command/licenses_command.rs index 81f9b67..e66267f 100644 --- a/crates/shirabe/src/command/licenses_command.rs +++ b/crates/shirabe/src/command/licenses_command.rs @@ -105,20 +105,20 @@ impl LicensesCommand { } let no_dev = input.get_option("no-dev").as_bool().unwrap_or(false); let repo = locker.get_locked_repository(!no_dev)?; - <crate::repository::LockArrayRepository as crate::repository::RepositoryInterface>::get_packages(&*repo.borrow()) + <crate::repository::LockArrayRepository as crate::repository::RepositoryInterface>::get_packages(&mut *repo.borrow_mut())? } else { let repository_manager = composer.get_repository_manager().clone(); let repository_manager = repository_manager.borrow(); let repo = repository_manager.get_local_repository(); if input.get_option("no-dev").as_bool().unwrap_or(false) { RepositoryUtils::filter_required_packages( - &repo.get_packages(), + &repo.get_packages()?, composer.get_package().clone().into(), false, vec![], ) } else { - repo.get_packages() + repo.get_packages()? } }; let _ = composer.get_package(); diff --git a/crates/shirabe/src/command/package_discovery_trait.rs b/crates/shirabe/src/command/package_discovery_trait.rs index eba6b8b..1f2ef5b 100644 --- a/crates/shirabe/src/command/package_discovery_trait.rs +++ b/crates/shirabe/src/command/package_discovery_trait.rs @@ -56,7 +56,7 @@ pub trait PackageDiscoveryTrait { fn normalize_requirements(&self, requires: Vec<String>) -> Vec<IndexMap<String, String>>; - fn get_repos(&mut self) -> &CompositeRepository { + fn get_repos(&mut self) -> &mut CompositeRepository { if self.get_repos_mut().is_none() { // PHP: array_merge([new PlatformRepository], RepositoryFactory::defaultReposWithDefaultManager($this->getIO())) let mut repos: Vec<crate::repository::RepositoryInterfaceHandle> = vec![ @@ -75,7 +75,7 @@ pub trait PackageDiscoveryTrait { *self.get_repos_mut() = Some(CompositeRepository::new(repos)); } - self.get_repos_mut().as_ref().unwrap() + self.get_repos_mut().as_mut().unwrap() } /// @param key-of<BasePackage::STABILITIES>|null $minimumStability @@ -238,7 +238,7 @@ pub trait PackageDiscoveryTrait { .map(|rm| rm.get_local_repository()); let mut existing_packages: Vec<String> = vec![]; if let Some(repo) = &installed_repo { - for package in repo.get_packages() { + for package in repo.get_packages()? { existing_packages.push(package.get_name().to_string()); } } @@ -533,7 +533,7 @@ pub trait PackageDiscoveryTrait { } // Check if it is a virtual package provided by others - let providers = repo_set.get_providers(name); + let providers = repo_set.get_providers(name)?; if count(&PhpMixed::List( providers.iter().map(|_| Box::new(PhpMixed::Null)).collect(), )) > 0 @@ -593,7 +593,7 @@ pub trait PackageDiscoveryTrait { self.get_platform_exception_details( candidate.clone(), platform_repo, - ), + )?, ), &[PhpMixed::String(name.to_string())], ), @@ -694,7 +694,7 @@ pub trait PackageDiscoveryTrait { self.get_platform_exception_details( candidate.clone(), platform_repo, - ), + )?, ), &[ PhpMixed::String(name.to_string()), @@ -816,11 +816,10 @@ pub trait PackageDiscoveryTrait { } .into()); } - Ok(self - .get_repos_mut() + self.get_repos_mut() .as_mut() .unwrap() - .search(package.to_string(), 0, None)) + .search(package.to_string(), 0, None) })() { Ok(r) => r, Err(e) => { @@ -847,7 +846,7 @@ pub trait PackageDiscoveryTrait { .find_package( &result.name, crate::repository::FindPackageConstraint::String("*".to_string()), - ) + )? .is_some() { // Ignore installed package @@ -864,13 +863,13 @@ pub trait PackageDiscoveryTrait { &self, candidate: PackageInterfaceHandle, platform_repo: Option<&PlatformRepositoryHandle>, - ) -> String { + ) -> anyhow::Result<String> { let mut details: Vec<String> = vec![]; let platform_repo = match platform_repo { - None => return String::new(), + None => return Ok(String::new()), Some(p) => p, }; - let platform_repo = platform_repo.borrow(); + let mut platform_repo = platform_repo.borrow_mut(); for link in candidate.get_requires().values() { if !PlatformRepository::is_platform_package(link.get_target()) { @@ -879,7 +878,7 @@ pub trait PackageDiscoveryTrait { let platform_pkg = platform_repo.find_package( link.get_target(), crate::repository::FindPackageConstraint::String("*".to_string()), - ); + )?; let platform_pkg = match platform_pkg { None => { if platform_repo.is_platform_package_disabled(link.get_target()) { @@ -941,13 +940,13 @@ pub trait PackageDiscoveryTrait { details.iter().map(|_| Box::new(PhpMixed::Null)).collect(), )) == 0 { - return String::new(); + return Ok(String::new()); } - format!( + Ok(format!( ":{} - {}", PHP_EOL, implode(&format!("{} - ", PHP_EOL), &details) - ) + )) } } diff --git a/crates/shirabe/src/command/reinstall_command.rs b/crates/shirabe/src/command/reinstall_command.rs index 29e8129..d183c00 100644 --- a/crates/shirabe/src/command/reinstall_command.rs +++ b/crates/shirabe/src/command/reinstall_command.rs @@ -97,7 +97,7 @@ impl ReinstallCommand { .collect() }) .unwrap_or_default(); - for package in local_repo.get_canonical_packages() { + for package in local_repo.get_canonical_packages()? { if filter_types.contains(&package.get_type()) { package_names_to_reinstall.push(package.get_name()); packages_to_reinstall.push(package); @@ -123,7 +123,7 @@ impl ReinstallCommand { for pattern in &patterns { let pattern_regexp = base_package::package_name_to_regexp(pattern); let mut matched = false; - for package in local_repo.get_canonical_packages() { + for package in local_repo.get_canonical_packages()? { if Preg::is_match(&pattern_regexp, &package.get_name()).unwrap_or(false) { matched = true; package_names_to_reinstall.push(package.get_name()); @@ -146,7 +146,7 @@ impl ReinstallCommand { uninstall_operations.push(UninstallOperation::new(package)); } - let present_packages = local_repo.get_packages(); + let present_packages = local_repo.get_packages()?; let result_packages: Vec<crate::package::PackageInterfaceHandle> = present_packages.iter().map(|p| p.clone().into()).collect(); let present_packages: Vec<crate::package::PackageInterfaceHandle> = present_packages diff --git a/crates/shirabe/src/command/remove_command.rs b/crates/shirabe/src/command/remove_command.rs index faab5fe..225714e 100644 --- a/crates/shirabe/src/command/remove_command.rs +++ b/crates/shirabe/src/command/remove_command.rs @@ -22,6 +22,7 @@ use crate::json::JsonFile; use crate::package::BasePackage; use crate::package::base_package; use crate::repository::CanonicalPackagesTrait; +use crate::repository::RepositoryInterface; #[derive(Debug)] pub struct RemoveCommand { @@ -198,12 +199,11 @@ impl RemoveCommand { } } - let locked_packages = composer + let mut locked_repo = composer .get_locker() .borrow_mut() - .get_locked_repository(true)? - .borrow() - .get_packages(); + .get_locked_repository(true)?; + let locked_packages = locked_repo.borrow_mut().get_packages()?; let mut required: IndexMap<String, bool> = IndexMap::new(); for link in composer @@ -435,7 +435,7 @@ impl RemoveCommand { composer_opt .get_plugin_manager() .borrow_mut() - .deactivate_installed_plugins(); + .deactivate_installed_plugins()?; } self.reset_composer(); @@ -626,7 +626,7 @@ impl RemoveCommand { .get_repository_manager() .borrow() .get_local_repository() - .find_packages(package, None) + .find_packages(package, None)? .is_empty() { io.write_error(&format!( diff --git a/crates/shirabe/src/command/require_command.rs b/crates/shirabe/src/command/require_command.rs index cfa7bba..e5ddbe7 100644 --- a/crates/shirabe/src/command/require_command.rs +++ b/crates/shirabe/src/command/require_command.rs @@ -337,7 +337,7 @@ impl RequireCommand { let found_packages: Vec<crate::package::PackageInterfaceHandle> = self .get_repos() - .find_packages(name, None) + .find_packages(name, None)? .into_iter() .map(|p| p.into()) .collect(); @@ -557,7 +557,7 @@ impl RequireCommand { composer .get_plugin_manager() .borrow_mut() - .deactivate_installed_plugins(); + .deactivate_installed_plugins()?; let io = self.get_io().clone(); let do_update_result = @@ -955,7 +955,7 @@ impl RequireCommand { let mut package = repo.find_package( package_name, crate::repository::FindPackageConstraint::String("*".to_string()), - ); + )?; while let Some(alias) = package.as_ref().and_then(|p| p.as_alias()) { package = Some(alias.get_alias_of().into()); } diff --git a/crates/shirabe/src/command/search_command.rs b/crates/shirabe/src/command/search_command.rs index 2c5d27d..593b927 100644 --- a/crates/shirabe/src/command/search_command.rs +++ b/crates/shirabe/src/command/search_command.rs @@ -96,7 +96,7 @@ impl SearchCommand { { all_repos.push(r.clone()); } - let repos = CompositeRepository::new(all_repos); + let mut repos = CompositeRepository::new(all_repos); // TODO(plugin): dispatch CommandEvent for search command let command_event = CommandEvent::new(PluginEvents::COMMAND, "search", input, output); @@ -136,7 +136,7 @@ impl SearchCommand { query = preg_quote(&query, None); } - let results = repos.search(query, mode, r#type); + let results = repos.search(query, mode, r#type)?; if results.len() > 0 && format == "text" { let width = self.get_terminal_width(); diff --git a/crates/shirabe/src/command/show_command.rs b/crates/shirabe/src/command/show_command.rs index bb7b909..9592f4e 100644 --- a/crates/shirabe/src/command/show_command.rs +++ b/crates/shirabe/src/command/show_command.rs @@ -195,7 +195,7 @@ impl ShowCommand { // TODO(phase-b): PHP shares a single $platformRepo instance by reference. // We clone the overrides and re-construct as needed because PlatformRepository // is not Clone (PHP class semantics; Phase D will introduce Rc sharing). - let platform_repo = PlatformRepository::new(vec![], platform_overrides.clone())?; + let mut platform_repo = PlatformRepository::new(vec![], platform_overrides.clone())?; let make_platform_repo = || -> anyhow::Result<PlatformRepository> { PlatformRepository::new(vec![], platform_overrides.clone()) }; @@ -396,7 +396,7 @@ impl ShowCommand { .get_repository_manager() .borrow() .get_local_repository() - .get_packages(); + .get_packages()?; let packages = RepositoryUtils::filter_required_packages( &local_packages, root_pkg.clone().into(), @@ -431,7 +431,7 @@ impl ShowCommand { RepositoryInterfaceHandle::new(InstalledRepository::new(vec![root_repo, lr])); } - if installed_repo.get_packages().is_empty() { + if installed_repo.get_packages()?.is_empty() { let has_non_platform_reqs = |reqs: &IndexMap<String, Link>| -> bool { reqs.keys() .any(|name| !PlatformRepository::is_platform_package(name)) @@ -590,7 +590,7 @@ impl ShowCommand { latest_package = self.find_latest_package( package.clone().into(), composer.as_ref().unwrap(), - &platform_repo, + &mut platform_repo, input.get_option("major-only").as_bool().unwrap_or(false), input.get_option("minor-only").as_bool().unwrap_or(false), input.get_option("patch-only").as_bool().unwrap_or(false), @@ -645,7 +645,7 @@ impl ShowCommand { self.print_package_info( package.clone(), &versions_map, - &*installed_repo.borrow(), + &mut *installed_repo.borrow_mut(), latest_package, )?; } @@ -656,7 +656,7 @@ impl ShowCommand { // show tree view if requested if input.get_option("tree").as_bool() == Some(true) { let root_requires = self.get_root_requires(); - let mut packages = installed_repo.get_packages(); + let mut packages = installed_repo.get_packages()?; packages.sort_by(|a, b| { let sa: String = a.to_string(); let sb: String = b.to_string(); @@ -746,7 +746,7 @@ impl ShowCommand { if false { let _ = package_filter.as_deref(); } else { - for package in repo.get_packages() { + for package in repo.get_packages()? { let existing = packages .get(&type_owned) .and_then(|m| m.get(&package.get_name())); @@ -849,7 +849,7 @@ impl ShowCommand { let latest = self.find_latest_package( package.clone(), composer.as_ref().unwrap(), - &platform_repo, + &mut platform_repo, show_major_only, show_minor_only, show_patch_only, @@ -1574,10 +1574,10 @@ impl ShowCommand { &mut self, package: CompletePackageInterfaceHandle, versions: &IndexMap<String, String>, - installed_repo: &dyn RepositoryInterface, + installed_repo: &mut dyn RepositoryInterface, latest_package: Option<PackageInterfaceHandle>, ) -> anyhow::Result<()> { - self.print_meta(package.clone(), versions, installed_repo, latest_package); + self.print_meta(package.clone(), versions, installed_repo, latest_package)?; self.print_links(package.clone(), Link::TYPE_REQUIRE, None); self.print_links( package.clone(), @@ -1604,9 +1604,9 @@ impl ShowCommand { &mut self, package: CompletePackageInterfaceHandle, versions: &IndexMap<String, String>, - installed_repo: &dyn RepositoryInterface, + installed_repo: &mut dyn RepositoryInterface, latest_package: Option<PackageInterfaceHandle>, - ) { + ) -> anyhow::Result<()> { let is_installed_package = !PlatformRepository::is_platform_package(&package.get_name()) && installed_repo.has_package(package.clone().into()); @@ -1621,7 +1621,7 @@ impl ShowCommand { let keywords = package.get_keywords(); self.get_io() .write(&format!("<info>keywords</info> : {}", keywords.join(", "))); - self.print_versions(package.clone(), versions, installed_repo); + self.print_versions(package.clone(), versions, installed_repo)?; if is_installed_package { if let Some(rd) = package.get_release_date() { let rel = self.get_relative_time(&rd); @@ -1755,6 +1755,8 @@ impl ShowCommand { self.get_io().write(&include_paths.join(", ")); } } + + Ok(()) } /// Prints all available versions of this package and highlights the installed one if any. @@ -1762,13 +1764,13 @@ impl ShowCommand { &mut self, package: CompletePackageInterfaceHandle, versions: &IndexMap<String, String>, - installed_repo: &dyn RepositoryInterface, - ) { + installed_repo: &mut dyn RepositoryInterface, + ) -> anyhow::Result<()> { let mut versions_keys: Vec<String> = versions.keys().cloned().collect(); versions_keys = Semver::rsort(versions_keys); // highlight installed version - let installed_packages = installed_repo.find_packages(&package.get_name(), None); + let installed_packages = installed_repo.find_packages(&package.get_name(), None)?; if !installed_packages.is_empty() { for installed_package in installed_packages.iter() { let installed_version = installed_package.get_pretty_version(); @@ -1788,6 +1790,8 @@ impl ShowCommand { self.get_io() .write(&format!("<info>versions</info> : {}", versions_str)); + + Ok(()) } /// print link objects @@ -2561,7 +2565,7 @@ impl ShowCommand { &mut self, package: PackageInterfaceHandle, composer: &PartialComposerHandle, - platform_repo: &PlatformRepository, + platform_repo: &mut PlatformRepository, major_only: bool, minor_only: bool, patch_only: bool, diff --git a/crates/shirabe/src/command/status_command.rs b/crates/shirabe/src/command/status_command.rs index 457c546..e729e1f 100644 --- a/crates/shirabe/src/command/status_command.rs +++ b/crates/shirabe/src/command/status_command.rs @@ -118,7 +118,7 @@ impl StatusCommand { .get_repository_manager() .borrow() .get_local_repository() - .get_canonical_packages(); + .get_canonical_packages()?; for package in packages { let target_dir = composer .get_installation_manager() diff --git a/crates/shirabe/src/command/suggests_command.rs b/crates/shirabe/src/command/suggests_command.rs index 2091608..92a4288 100644 --- a/crates/shirabe/src/command/suggests_command.rs +++ b/crates/shirabe/src/command/suggests_command.rs @@ -87,11 +87,11 @@ impl SuggestsCommand { ); } - let installed_repo = InstalledRepository::new(installed_repos); + let mut installed_repo = InstalledRepository::new(installed_repos); let mut reporter = SuggestedPackagesReporter::new(self.get_io().clone()); let filter = input.get_argument("packages"); - let mut packages = RepositoryInterface::get_packages(&installed_repo); + let mut packages = RepositoryInterface::get_packages(&mut installed_repo)?; let root_pkg_as_base: crate::package::BasePackageHandle = composer.get_package().clone().into(); packages.push(root_pkg_as_base); @@ -121,7 +121,7 @@ impl SuggestsCommand { None }; - reporter.output(mode, Some(&installed_repo), only_dependents_of); + reporter.output(mode, Some(&mut installed_repo), only_dependents_of)?; Ok(0) } diff --git a/crates/shirabe/src/command/update_command.rs b/crates/shirabe/src/command/update_command.rs index 7fcfa4d..e28d407 100644 --- a/crates/shirabe/src/command/update_command.rs +++ b/crates/shirabe/src/command/update_command.rs @@ -212,8 +212,8 @@ impl UpdateCommand { .get_locker() .borrow_mut() .get_locked_repository(true)? - .borrow() - .get_canonical_packages() + .borrow_mut() + .get_canonical_packages()? { if package.is_dev() { continue; @@ -498,19 +498,17 @@ impl UpdateCommand { let mut autocompleter_values: IndexMap<String, String> = IndexMap::new(); let installed_packages: Vec<crate::package::PackageInterfaceHandle> = if composer_ref.get_locker().borrow_mut().is_locked() { - CanonicalPackagesTrait::get_packages( - &*composer_ref - .get_locker() - .borrow_mut() - .get_locked_repository(true)? - .borrow(), - ) + let locked_repo = composer_ref + .get_locker() + .borrow_mut() + .get_locked_repository(true)?; + locked_repo.borrow_mut().get_canonical_packages()? } else { composer_ref .get_repository_manager() .borrow() .get_local_repository() - .get_packages() + .get_packages()? }; let mut version_selector = self.create_version_selector(composer)?; for package in &installed_packages { diff --git a/crates/shirabe/src/command/validate_command.rs b/crates/shirabe/src/command/validate_command.rs index da76eca..b168b03 100644 --- a/crates/shirabe/src/command/validate_command.rs +++ b/crates/shirabe/src/command/validate_command.rs @@ -210,7 +210,7 @@ impl ValidateCommand { .get_repository_manager() .borrow() .get_local_repository() - .get_packages(); + .get_packages()?; for package in packages { let path = composer .get_installation_manager() diff --git a/crates/shirabe/src/dependency_resolver/local_repo_transaction.rs b/crates/shirabe/src/dependency_resolver/local_repo_transaction.rs index dc71562..5feb9eb 100644 --- a/crates/shirabe/src/dependency_resolver/local_repo_transaction.rs +++ b/crates/shirabe/src/dependency_resolver/local_repo_transaction.rs @@ -11,15 +11,15 @@ pub struct LocalRepoTransaction { impl LocalRepoTransaction { pub fn new( - locked_repository: &dyn RepositoryInterface, - local_repository: &dyn InstalledRepositoryInterface, - ) -> Self { - Self { + locked_repository: &mut dyn RepositoryInterface, + local_repository: &mut dyn InstalledRepositoryInterface, + ) -> anyhow::Result<Self> { + Ok(Self { inner: Transaction::new( - local_repository.get_packages(), - locked_repository.get_packages(), + local_repository.get_packages()?, + locked_repository.get_packages()?, ), - } + }) } pub fn get_operations( diff --git a/crates/shirabe/src/dependency_resolver/pool_builder.rs b/crates/shirabe/src/dependency_resolver/pool_builder.rs index 1bbd51e..5750450 100644 --- a/crates/shirabe/src/dependency_resolver/pool_builder.rs +++ b/crates/shirabe/src/dependency_resolver/pool_builder.rs @@ -162,10 +162,12 @@ impl PoolBuilder { .into()); } - let locked_packages = CanonicalPackagesTrait::get_packages( - &*request.get_locked_repository().unwrap().borrow(), - ); - for locked_package in locked_packages { + for locked_package in request + .get_locked_repository() + .unwrap() + .borrow_mut() + .get_canonical_packages()? + { if !self.is_update_allowed(locked_package.clone()) { // Path repo packages are never loaded from lock, to force them to always remain in sync // unless symlinking is disabled in which case we probably should rather treat them like @@ -530,7 +532,7 @@ impl PoolBuilder { .collect() }) .unwrap_or_default(), - ); + )?; let names_found = result.names_found; for name in &names_found { @@ -819,9 +821,12 @@ impl PoolBuilder { let pattern_regexp = base_package::package_name_to_regexp(pattern); // update pattern matches a locked package? => all good - for package in CanonicalPackagesTrait::get_packages( - &*request.get_locked_repository().unwrap().borrow(), - ) { + for package in request + .get_locked_repository() + .unwrap() + .borrow_mut() + .get_canonical_packages()? + { if Preg::is_match3(&pattern_regexp, &package.get_name(), None).unwrap_or(false) { continue 'outer; } diff --git a/crates/shirabe/src/dependency_resolver/problem.rs b/crates/shirabe/src/dependency_resolver/problem.rs index 7312bda..874d56e 100644 --- a/crates/shirabe/src/dependency_resolver/problem.rs +++ b/crates/shirabe/src/dependency_resolver/problem.rs @@ -110,7 +110,7 @@ impl Problem { is_verbose, &package_name, constraint, - ); + )?; return Ok(format!("\n {}", implode("", &[missing.0, missing.1]))); } } @@ -126,7 +126,7 @@ impl Problem { .cmp(&self.get_sortable_string(pool, &rule2.borrow())) }); - Ok(Self::format_deduplicated_rules( + Self::format_deduplicated_rules( &reasons, " ", repository_set, @@ -135,7 +135,7 @@ impl Problem { is_verbose, installed_map, learned_pool, - )) + ) } fn get_sortable_string(&self, pool: &Pool, rule: &Rule) -> String { @@ -208,7 +208,7 @@ impl Problem { is_verbose: bool, installed_map: &IndexMap<String, BasePackageHandle>, learned_pool: &Vec<Vec<std::rc::Rc<std::cell::RefCell<Rule>>>>, - ) -> String { + ) -> anyhow::Result<String> { let mut messages: Vec<String> = Vec::new(); let mut templates: IndexMap<String, IndexMap<String, IndexMap<String, String>>> = IndexMap::new(); @@ -224,7 +224,7 @@ impl Problem { is_verbose, installed_map, learned_pool, - ); + )?; let mut m: IndexMap<CaptureKey, String> = IndexMap::new(); let matched = if in_array( PhpMixed::Int(rule_ref.get_reason()), @@ -341,11 +341,11 @@ impl Problem { } } - format!( + Ok(format!( "\n{}- {}", indent, implode(&format!("\n{}- ", indent), &result) - ) + )) } pub fn is_caused_by_lock( @@ -394,7 +394,7 @@ impl Problem { is_verbose: bool, package_name: &str, constraint: Option<&AnyConstraint>, - ) -> (String, String) { + ) -> anyhow::Result<(String, String)> { if PlatformRepository::is_platform_package(package_name) { // handle php/php-*/hhvm if stripos(package_name, "php") == Some(0) || package_name == "hhvm" { @@ -413,51 +413,51 @@ impl Problem { if defined("HHVM_VERSION") || (package_name == "hhvm" && pool.what_provides(package_name, None).len() > 0) { - return ( + return Ok(( msg, "your HHVM version does not satisfy that requirement.".to_string(), - ); + )); } if package_name == "hhvm" { - return ( + return Ok(( msg, "HHVM was not detected on this machine, make sure it is in your PATH." .to_string(), - ); + )); } if version.is_none() { - return ( + return Ok(( msg, format!( "the {} package is disabled by your platform config. Enable it again with \"composer config platform.{} --unset\".", package_name, package_name ), - ); + )); } - return ( + return Ok(( msg, format!( "your {} version ({}) does not satisfy that requirement.", package_name, version.unwrap() ), - ); + )); } // handle php extensions if stripos(package_name, "ext-") == Some(0) { if strpos(package_name, " ").is_some() { - return ( + return Ok(( "- ".to_string(), format!( "PHP extension {} should be required as {}.", package_name, str_replace(" ", "-", package_name) ), - ); + )); } let ext = substr(package_name, 4, None); @@ -476,7 +476,7 @@ impl Problem { Self::get_platform_package_version(pool, package_name, &effective_version); if version.is_none() { let providers_str_opt = - Self::get_providers_list(repository_set, package_name, 5); + Self::get_providers_list(repository_set, package_name, 5)?; let providers_str = match providers_str_opt { Some(ps) => format!( "\n\n Alternatively you can require one of these packages that provide the extension (or parts of it):\n <warning>Keep in mind that the suggestions are automated and may not be valid or safe to use</warning>\n{}", @@ -486,28 +486,28 @@ impl Problem { }; if extension_loaded(&ext) { - return ( + return Ok(( msg, format!( "the {} package is disabled by your platform config. Enable it again with \"composer config platform.{} --unset\".{}", package_name, package_name, providers_str ), - ); + )); } - return ( + return Ok(( msg, format!( "it is missing from your system. Install or enable PHP's {} extension.{}", ext, providers_str ), - ); + )); } - return ( + return Ok(( msg, format!("it has the wrong version installed ({}).", version.unwrap()), - ); + )); } // handle linked libs @@ -519,17 +519,17 @@ impl Problem { "it is missing from your system, make sure the intl extension is loaded." }; - return ( + return Ok(( format!( "- Root composer.json requires linked library {}{} but ", package_name, Self::constraint_to_text(constraint) ), error.to_string(), - ); + )); } - let providers_str_opt = Self::get_providers_list(repository_set, package_name, 5); + let providers_str_opt = Self::get_providers_list(repository_set, package_name, 5)?; let providers_str = match providers_str_opt { Some(ps) => format!( "\n\n Alternatively you can require one of these packages that provide the library (or parts of it):\n <warning>Keep in mind that the suggestions are automated and may not be valid or safe to use</warning>\n{}", @@ -538,7 +538,7 @@ impl Problem { None => String::new(), }; - return ( + return Ok(( format!( "- Root composer.json requires linked library {}{} but ", package_name, @@ -548,7 +548,7 @@ impl Problem { "it has the wrong version installed or is missing from your system, make sure to load the extension providing it.{}", providers_str ), - ); + )); } } @@ -557,14 +557,14 @@ impl Problem { if package.get_name().as_str() == package_name { locked_package = Some(package.clone()); if pool.is_unacceptable_fixed_or_locked_package(package.clone()) { - return ( + return Ok(( "- ".to_string(), format!( "{} is fixed to {} (lock file version) by a partial update but that version is rejected by your minimum-stability. Make sure you list it as an argument for the update command.", package.get_pretty_name(), package.get_pretty_version() ), - ); + )); } break; } @@ -600,9 +600,9 @@ impl Problem { .into(), ), 0, - ); + )?; if packages.len() > 0 { - return ( + return Ok(( format!( "- Root composer.json requires {}{}, ", package_name, @@ -619,14 +619,15 @@ impl Problem { ), str_replace("#", "+", &c.get_pretty_string()) ), - ); + )); } } } // first check if the actual requested package is found in normal conditions // if so it must mean it is rejected by another constraint than the one given here - let packages = repository_set.find_packages(package_name, constraint.map(|c| c.clone()), 0); + let packages = + repository_set.find_packages(package_name, constraint.map(|c| c.clone()), 0)?; if packages.len() > 0 { let root_reqs = repository_set.get_root_requires(); if root_reqs.contains_key(package_name) { @@ -644,7 +645,7 @@ impl Problem { }) .collect(); if filtered.len() == 0 { - return ( + return Ok(( format!( "- Root composer.json requires {}{}, ", package_name, @@ -666,7 +667,7 @@ impl Problem { }, root_reqs[package_name].get_pretty_string() ), - ); + )); } } @@ -688,7 +689,7 @@ impl Problem { }) .collect(); if filtered.len() == 0 { - return ( + return Ok(( format!( "- Root composer.json requires {}{}, ", name, @@ -711,7 +712,7 @@ impl Problem { name, temp_reqs[&name].get_pretty_string() ), - ); + )); } } } @@ -736,7 +737,7 @@ impl Problem { }) .collect(); if filtered.len() == 0 { - return ( + return Ok(( format!( "- Root composer.json requires {}{}, ", package_name, @@ -753,7 +754,7 @@ impl Problem { ), lp.get_pretty_version() ), - ); + )); } } @@ -766,7 +767,7 @@ impl Problem { .collect(); if non_locked_packages.len() == 0 { - return ( + return Ok(( format!( "- Root composer.json requires {}{}, ", package_name, @@ -782,11 +783,11 @@ impl Problem { false ) ), - ); + )); } if pool.is_abandoned_removed_package_version(package_name, constraint) { - return ( + return Ok(( format!( "- Root composer.json requires {}{}, ", package_name, @@ -802,7 +803,7 @@ impl Problem { false ) ), - ); + )); } if pool.is_security_removed_package_version(package_name, constraint) { @@ -829,7 +830,7 @@ impl Problem { }) .collect(); - return ( + return Ok(( format!( "- Root composer.json requires {}{}, ", package_name, @@ -846,10 +847,10 @@ impl Problem { ), implode("\", \"", &advisories_list) ), - ); + )); } - return ( + return Ok(( format!( "- Root composer.json requires {}{}, ", package_name, @@ -864,7 +865,7 @@ impl Problem { "it conflicts" } ), - ); + )); } // check if the package is found when bypassing stability checks @@ -872,16 +873,16 @@ impl Problem { package_name, constraint.map(|c| c.clone()), RepositorySet::ALLOW_UNACCEPTABLE_STABILITIES, - ); + )?; if packages.len() > 0 { // we must first verify if a valid package would be found in a lower priority repository let all_repos_packages = repository_set.find_packages( package_name, constraint.map(|c| c.clone()), RepositorySet::ALLOW_SHADOWED_REPOSITORIES, - ); + )?; if all_repos_packages.len() > 0 { - return Self::compute_check_for_lower_prio_repo( + return Ok(Self::compute_check_for_lower_prio_repo( pool, is_verbose, package_name, @@ -889,10 +890,10 @@ impl Problem { &all_repos_packages, "minimum-stability", constraint, - ); + )); } - return ( + return Ok(( format!( "- Root composer.json requires {}{}, ", package_name, @@ -907,7 +908,7 @@ impl Problem { "it does" } ), - ); + )); } // check if the package is found when bypassing the constraint and stability checks @@ -915,16 +916,16 @@ impl Problem { package_name, None, RepositorySet::ALLOW_UNACCEPTABLE_STABILITIES, - ); + )?; if packages.len() > 0 { // we must first verify if a valid package would be found in a lower priority repository let all_repos_packages = repository_set.find_packages( package_name, constraint.map(|c| c.clone()), RepositorySet::ALLOW_SHADOWED_REPOSITORIES, - ); + )?; if all_repos_packages.len() > 0 { - return Self::compute_check_for_lower_prio_repo( + return Ok(Self::compute_check_for_lower_prio_repo( pool, is_verbose, package_name, @@ -932,7 +933,7 @@ impl Problem { &all_repos_packages, "constraint", constraint, - ); + )); } let mut suffix = String::new(); @@ -967,7 +968,7 @@ impl Problem { } } - return ( + return Ok(( format!( "- Root composer.json requires {}{}, ", package_name, @@ -983,25 +984,25 @@ impl Problem { }, suffix ), - ); + )); } if !Preg::is_match3(r"{^[A-Za-z0-9_./-]+$}", package_name, None).unwrap_or(false) { let illegal_chars = Preg::replace(r"{[A-Za-z0-9_./-]+}", "", package_name).unwrap_or_default(); - return ( + return Ok(( format!("- Root composer.json requires {}, it ", package_name), format!( "could not be found, it looks like its name is invalid, \"{}\" is not allowed in package names.", illegal_chars ), - ); + )); } - let providers_str = Self::get_providers_list(repository_set, package_name, 15); + let providers_str = Self::get_providers_list(repository_set, package_name, 15)?; if let Some(ps) = providers_str { - return ( + return Ok(( format!( "- Root composer.json requires {}{}, it ", package_name, @@ -1011,14 +1012,14 @@ impl Problem { "could not be found in any version, but the following packages provide it:\n{} Consider requiring one of these to satisfy the {} requirement.", ps, package_name ), - ); + )); } - ( + Ok(( format!("- Root composer.json requires {}, it ", package_name), "could not be found in any version, there may be a typo in the package name." .to_string(), - ) + )) } /// @internal @@ -1428,8 +1429,8 @@ impl Problem { repository_set: &RepositorySet, package_name: &str, max_providers: i64, - ) -> Option<String> { - let providers = repository_set.get_providers(package_name); + ) -> anyhow::Result<Option<String>> { + let providers = repository_set.get_providers(package_name)?; if providers.len() > 0 { let provider_count = providers.len() as i64; let slice: Vec<crate::repository::ProviderInfo> = if provider_count > max_providers + 1 @@ -1463,9 +1464,9 @@ impl Problem { )); } - return Some(providers_str); + return Ok(Some(providers_str)); } - None + Ok(None) } } diff --git a/crates/shirabe/src/dependency_resolver/request.rs b/crates/shirabe/src/dependency_resolver/request.rs index df26535..88957f2 100644 --- a/crates/shirabe/src/dependency_resolver/request.rs +++ b/crates/shirabe/src/dependency_resolver/request.rs @@ -195,11 +195,12 @@ impl Request { pub fn get_present_map( &self, package_ids: bool, - ) -> IndexMap<String, crate::package::BasePackageHandle> { + ) -> anyhow::Result<IndexMap<String, crate::package::BasePackageHandle>> { let mut present_map: IndexMap<String, crate::package::BasePackageHandle> = IndexMap::new(); if let Some(ref locked_repository) = self.locked_repository { - for package in RepositoryInterface::get_packages(&*locked_repository.borrow()) { + for package in RepositoryInterface::get_packages(&mut *locked_repository.borrow_mut())? + { let key = if package_ids { package.get_id().to_string() } else { @@ -218,7 +219,7 @@ impl Request { present_map.insert(key, package.clone()); } - present_map + Ok(present_map) } pub fn get_fixed_packages_map(&self) -> IndexMap<i64, BasePackageHandle> { diff --git a/crates/shirabe/src/dependency_resolver/rule.rs b/crates/shirabe/src/dependency_resolver/rule.rs index 1681509..3d7bb2d 100644 --- a/crates/shirabe/src/dependency_resolver/rule.rs +++ b/crates/shirabe/src/dependency_resolver/rule.rs @@ -347,10 +347,10 @@ impl Rule { is_verbose: bool, installed_map: &IndexMap<String, BasePackageHandle>, _learned_pool: &Vec<Vec<Rc<RefCell<Rule>>>>, - ) -> String { + ) -> anyhow::Result<String> { let mut literals = self.get_literals(); - match self.get_reason() { + Ok(match self.get_reason() { r if r == RULE_ROOT_REQUIRE => { let reason_data = self.get_reason_data(); let (package_name, constraint): (&str, &AnyConstraint) = match reason_data { @@ -358,16 +358,16 @@ impl Rule { package_name, constraint, } => (package_name.as_str(), constraint), - _ => return String::new(), + _ => return Ok(String::new()), }; let packages = pool.what_provides(package_name, Some(constraint)); if 0 == packages.len() { - return format!( + return Ok(format!( "No package found to satisfy root composer.json require {} {}", package_name, constraint.get_pretty_string(), - ); + )); } let packages_non_alias: Vec<BasePackageHandle> = packages @@ -378,11 +378,11 @@ impl Rule { if packages_non_alias.len() == 1 { let package = &packages_non_alias[0]; if request.is_locked_package(package.clone()) { - return format!( + return Ok(format!( "{} is locked to version {} and an update of this package was not requested.", package.get_pretty_name(), package.get_pretty_version(), - ); + )); } } @@ -403,16 +403,16 @@ impl Rule { r if r == RULE_FIXED => { let package_in = match self.get_reason_data() { ReasonData::Fixed { package } => package.clone(), - _ => return String::new(), + _ => return Ok(String::new()), }; let package = self.deduplicate_default_branch_alias(package_in); if request.is_locked_package(package.clone()) { - return format!( + return Ok(format!( "{} is locked to version {} and an update of this package was not requested.", package.get_pretty_name(), package.get_pretty_version(), - ); + )); } format!( @@ -433,7 +433,7 @@ impl Rule { let link = match reason_data { ReasonData::Link(l) => l, - _ => return String::new(), + _ => return Ok(String::new()), }; // swap literals if they are not in the right order with package2 being the conflicter if link.get_source() == package1.get_name() { @@ -494,7 +494,7 @@ impl Rule { let reason_data = self.get_reason_data(); let link = match reason_data { ReasonData::Link(l) => l, - _ => return String::new(), + _ => return Ok(String::new()), }; let mut requires: Vec<BasePackageHandle> = vec![]; @@ -525,9 +525,9 @@ impl Rule { is_verbose, target_name, Some(link.get_constraint()), - ); + )?; - return format!("{} -> {}", text, reason.1); + return Ok(format!("{} -> {}", text, reason.1)); } } @@ -577,7 +577,7 @@ impl Rule { } if installed_packages.len() > 0 && removable_packages.len() > 0 { - return format!( + return Ok(format!( "{} cannot be installed as that would require removing {}. {}", self.format_packages_unique_from_packages( pool, @@ -594,16 +594,16 @@ impl Rule { true, ), reason, - ); + )); } - return format!( + return Ok(format!( "Only one of these can be installed: {}. {}", self.format_packages_unique_from_literals( pool, &literals, is_verbose, None, true ), reason, - ); + )); } format!( @@ -665,7 +665,7 @@ impl Rule { // avoid returning content like "9999999-dev is an alias of dev-master" as it is useless if alias_package.get_version() == VersionParser::DEFAULT_BRANCH_ALIAS { - return String::new(); + return Ok(String::new()); } let package = self.deduplicate_default_branch_alias(pool.literal_to_package(literals[1])); @@ -682,7 +682,7 @@ impl Rule { // avoid returning content like "9999999-dev is an alias of dev-master" as it is useless if alias_package.get_version() == VersionParser::DEFAULT_BRANCH_ALIAS { - return String::new(); + return Ok(String::new()); } let package = self.deduplicate_default_branch_alias(pool.literal_to_package(literals[0])); @@ -704,7 +704,7 @@ impl Rule { format!("({})", rule_text) } - } + }) } // Corresponds the variant formatPackagesUnique() that takes an array of BasePackages. diff --git a/crates/shirabe/src/dependency_resolver/solver.rs b/crates/shirabe/src/dependency_resolver/solver.rs index 281c796..d88d9bb 100644 --- a/crates/shirabe/src/dependency_resolver/solver.rs +++ b/crates/shirabe/src/dependency_resolver/solver.rs @@ -299,7 +299,7 @@ impl Solver { // LockTransaction stores PackageInterfaceHandle maps; widen the request's BasePackageHandle // maps into them. let present_map = request - .get_present_map(false) + .get_present_map(false)? .into_iter() .map(|(k, v)| (k, v.into())) .collect(); diff --git a/crates/shirabe/src/dependency_resolver/solver_problems_exception.rs b/crates/shirabe/src/dependency_resolver/solver_problems_exception.rs index 17ebaf2..7aa8a46 100644 --- a/crates/shirabe/src/dependency_resolver/solver_problems_exception.rs +++ b/crates/shirabe/src/dependency_resolver/solver_problems_exception.rs @@ -52,8 +52,8 @@ impl SolverProblemsException { pool: &mut Pool, is_verbose: bool, is_dev_extraction: bool, - ) -> String { - let installed_map = request.get_present_map(true); + ) -> anyhow::Result<String> { + let installed_map = request.get_present_map(true)?; let mut missing_extensions: Vec<String> = Vec::new(); let mut is_caused_by_lock = false; @@ -61,16 +61,14 @@ impl SolverProblemsException { for problem in &self.problems { problems.push(format!( "{}\n", - problem - .get_pretty_string( - repository_set, - request, - pool, - is_verbose, - &installed_map, - &self.learned_pool - ) - .unwrap_or_default() + problem.get_pretty_string( + repository_set, + request, + pool, + is_verbose, + &installed_map, + &self.learned_pool + )? )); // TODO(phase-b): get_reasons returns an IndexMap; flatten its values into Vec<Vec<...>>. let reasons_vec: Vec<Vec<Rc<RefCell<Rule>>>> = problem @@ -126,7 +124,7 @@ impl SolverProblemsException { text.push_str(&hints.join("\n\n")); } - text + Ok(text) } pub fn get_problems(&self) -> &Vec<Problem> { diff --git a/crates/shirabe/src/event_dispatcher/event_dispatcher.rs b/crates/shirabe/src/event_dispatcher/event_dispatcher.rs index ea0d69a..7122a4b 100644 --- a/crates/shirabe/src/event_dispatcher/event_dispatcher.rs +++ b/crates/shirabe/src/event_dispatcher/event_dispatcher.rs @@ -308,7 +308,7 @@ impl EventDispatcher { if !is_string_callable { // TODO(plugin): non-string callable handling — verify is_callable, invoke, // and replicate the get_class / write_error / is_callable error path from PHP. - self.make_autoloader(event, &callable); + let _ = self.make_autoloader(event, &callable); if !is_callable(&PhpMixed::Null) { let (class_name, method) = match &callable { Callable::ArrayCallable(first, m) => { @@ -504,7 +504,8 @@ impl EventDispatcher { let class_name = substr(callable_str, 0, Some(pos)); let method_name = substr(callable_str, pos + 2, None); - self.make_autoloader(event, &Callable::String(callable_str.clone())); + let _ = + self.make_autoloader(event, &Callable::String(callable_str.clone())); if !class_exists(&class_name) { self.io.write_error3(&format!( "<warning>Class {} is not autoloadable, can not call {} script</warning>", @@ -550,7 +551,7 @@ impl EventDispatcher { Callable::String(ref callable_str) if self.is_command_class(callable_str) => { let class_name = callable_str.clone(); - self.make_autoloader( + let _ = self.make_autoloader( event, &Callable::ArrayCallable( Box::new(PhpMixed::String(callable_str.clone())), @@ -1223,11 +1224,11 @@ impl EventDispatcher { "unsupported".to_string() } - fn make_autoloader(&mut self, event: &Event, callable: &Callable) { + fn make_autoloader(&mut self, event: &Event, callable: &Callable) -> anyhow::Result<()> { let composer = self.composer(); // TODO(plugin): full autoloader rebuild on plugin-supplied callables — currently a stub. let Some(composer) = composer.as_full() else { - return; + return Ok(()); }; let composer = composer.borrow_mut(); @@ -1244,7 +1245,7 @@ impl EventDispatcher { Callable::Closure => "closure".to_string(), }; if self.previous_listeners.contains_key(&callable_key) { - return; + return Ok(()); } self.previous_listeners.insert(callable_key, true); @@ -1253,7 +1254,7 @@ impl EventDispatcher { .get_repository_manager() .borrow() .get_local_repository() - .get_canonical_packages(); + .get_canonical_packages()?; let generator = composer.get_autoload_generator().clone(); let generator = generator.borrow(); let mut hash_input = packages @@ -1269,7 +1270,7 @@ impl EventDispatcher { let hash_value = hash("sha256", &hash_input); if self.previous_hash.as_deref() == Some(hash_value.as_str()) { - return; + return Ok(()); } self.previous_hash = Some(hash_value); @@ -1302,6 +1303,7 @@ impl EventDispatcher { let mut loader = generator.create_loader(&map, Some(vendor_dir.clone())); loader.register(false); self.loader = Some(loader); + Ok(()) } // ---- helpers ---- diff --git a/crates/shirabe/src/factory.rs b/crates/shirabe/src/factory.rs index bb6ff28..cdad33c 100644 --- a/crates/shirabe/src/factory.rs +++ b/crates/shirabe/src/factory.rs @@ -1234,10 +1234,10 @@ impl Factory { fn purge_packages( &self, - repo: &dyn InstalledRepositoryInterface, + repo: &mut dyn InstalledRepositoryInterface, im: &mut InstallationManager, ) -> anyhow::Result<()> { - for package in repo.get_packages() { + for package in repo.get_packages()? { if !im.is_package_installed(repo, package.clone())? { let _ = package; } diff --git a/crates/shirabe/src/installer.rs b/crates/shirabe/src/installer.rs index 7fc3275..faa34fb 100644 --- a/crates/shirabe/src/installer.rs +++ b/crates/shirabe/src/installer.rs @@ -348,7 +348,7 @@ impl Installer { .borrow_mut() .get_locked_repository(self.dev_mode)? .into(); - let installed_repo = InstalledRepository::new(vec![ + let mut installed_repo = InstalledRepository::new(vec![ locked_repository_handle, crate::repository::RepositoryInterfaceHandle::new(self.create_platform_repo(false)), crate::repository::RepositoryInterfaceHandle::new(RootPackageRepository::new( @@ -360,12 +360,13 @@ impl Installer { .add_suggestions_from_package(self.package.clone().into()); } self.suggested_packages_reporter - .output_minimalistic(Some(&installed_repo), None); + .output_minimalistic(Some(&mut installed_repo), None)?; } // Find abandoned packages and warn user let locked_repository = self.locker.borrow_mut().get_locked_repository(true)?; - for package in CanonicalPackagesTrait::get_packages(&*locked_repository.borrow()) { + let packages = locked_repository.borrow_mut().get_canonical_packages()?; + for package in packages { let complete = match package.as_complete_package() { Some(p) if p.is_abandoned() => p, _ => continue, @@ -406,10 +407,12 @@ impl Installer { .borrow_mut() .set_platform_requirement_filter(self.platform_requirement_filter.clone()); let local_repo_handle = self.repository_manager.borrow().get_local_repository(); - let local_repo_ref = local_repo_handle.borrow(); + let mut local_repo_ref = local_repo_handle.borrow_mut(); self.autoload_generator.borrow_mut().dump( &*self.config.borrow(), - local_repo_ref.as_installed_repository_interface().unwrap(), + local_repo_ref + .as_installed_repository_interface_mut() + .unwrap(), self.package.clone(), &mut *self.installation_manager.borrow_mut(), "composer", @@ -424,7 +427,7 @@ impl Installer { // force binaries re-generation in case they are missing let repository_manager = self.repository_manager.clone(); let repository_manager = repository_manager.borrow(); - for package in repository_manager.get_local_repository().get_packages() { + for package in repository_manager.get_local_repository().get_packages()? { self.installation_manager .borrow_mut() .ensure_binaries_presence(package.clone()); @@ -444,7 +447,7 @@ impl Installer { let mut funding_count: i64 = 0; let repository_manager = self.repository_manager.clone(); let repository_manager = repository_manager.borrow(); - for package in repository_manager.get_local_repository().get_packages() { + for package in repository_manager.get_local_repository().get_packages()? { if let Some(cp) = package.as_complete() { if package.as_alias().is_none() && !cp.get_funding().is_empty() { funding_count += 1; @@ -490,7 +493,7 @@ impl Installer { if audit_config.audit { let (packages, target) = if self.update && !self.install { ( - locked_repository.borrow().get_canonical_packages(), + locked_repository.borrow_mut().get_canonical_packages()?, "locked", ) } else { @@ -498,7 +501,7 @@ impl Installer { self.repository_manager .borrow() .get_local_repository() - .get_canonical_packages(), + .get_canonical_packages()?, "installed", ) }; @@ -561,7 +564,7 @@ impl Installer { local_repo: crate::repository::RepositoryInterfaceHandle, do_install: bool, ) -> anyhow::Result<i64> { - let platform_repo = self.create_platform_repo(true); + let mut platform_repo = self.create_platform_repo(true); let aliases = self.get_root_aliases(true); let mut locked_repository: Option<crate::repository::LockArrayRepositoryHandle> = None; @@ -616,8 +619,9 @@ impl Installer { .write_error("<info>Loading composer repositories with package information</info>"); // creating repository set - let policy = self.create_policy(true, locked_repository.as_ref()); - let mut repository_set = self.create_repository_set(true, &platform_repo, &aliases, None); + let policy = self.create_policy(true, locked_repository.as_ref())?; + let mut repository_set = + self.create_repository_set(true, &platform_repo, &aliases, None)?; let repository_manager = self.repository_manager.clone(); let repository_manager = repository_manager.borrow(); let repositories = repository_manager.get_repositories(); @@ -631,9 +635,9 @@ impl Installer { let fixed_root_package = self.fixed_root_package.clone(); let mut request = self.create_request( fixed_root_package, - &platform_repo, + &mut platform_repo, locked_repository.as_ref(), - ); + )?; self.require_packages_for_update(&mut request, locked_repository.as_ref(), true)?; // pass the allow list into the request, so the pool builder can apply it @@ -708,7 +712,7 @@ impl Installer { let exit_code = self.extract_dev_packages( &mut lock_transaction, - &platform_repo, + &mut platform_repo, &aliases, &*policy, locked_repository.as_ref(), @@ -913,7 +917,7 @@ impl Installer { pub(crate) fn extract_dev_packages( &mut self, lock_transaction: &mut LockTransaction, - platform_repo: &PlatformRepository, + platform_repo: &mut PlatformRepository, aliases: &Vec<IndexMap<String, String>>, policy: &dyn PolicyInterface, locked_repository: Option<&crate::repository::LockArrayRepositoryHandle>, @@ -933,12 +937,13 @@ impl Installer { result_repo.add_package(loaded)?; } - let mut repository_set = self.create_repository_set(true, platform_repo, aliases, None); + let mut repository_set = self.create_repository_set(true, platform_repo, aliases, None)?; repository_set.add_repository(crate::repository::RepositoryInterfaceHandle::new( result_repo, ))?; - let mut request = self.create_request(self.fixed_root_package.clone(), platform_repo, None); + let mut request = + self.create_request(self.fixed_root_package.clone(), platform_repo, None)?; self.require_packages_for_update(&mut request, locked_repository, false)?; let pool = repository_set.create_pool_with_all_packages()?; @@ -1006,24 +1011,27 @@ impl Installer { "<info>Verifying lock file contents can be installed on current platform.</info>", ); - let platform_repo = self.create_platform_repo(false); + let mut platform_repo = self.create_platform_repo(false); // creating repository set - let policy = self.create_policy(false, None); + let policy = self.create_policy(false, None)?; // use aliases from lock file only, so empty root aliases here - let locked_repo_borrow = locked_repository.borrow(); + let mut locked_repo_borrow = locked_repository.borrow_mut(); let mut repository_set = self.create_repository_set( false, &platform_repo, &vec![], - Some(&*locked_repo_borrow), - ); + Some(&mut *locked_repo_borrow), + )?; drop(locked_repo_borrow); repository_set.add_repository(locked_repository.clone().into())?; // creating requirements request let fixed_root_package = self.fixed_root_package.clone(); - let mut request = - self.create_request(fixed_root_package, &platform_repo, Some(&locked_repository)); + let mut request = self.create_request( + fixed_root_package, + &mut platform_repo, + Some(&locked_repository), + )?; if !self.locker.borrow_mut().is_fresh()? { self.io.write_error3( @@ -1052,7 +1060,8 @@ impl Installer { } } - for package in RepositoryInterface::get_packages(&*locked_repository.borrow()) { + for package in RepositoryInterface::get_packages(&mut *locked_repository.borrow_mut())? + { request.fix_locked_package(package.clone()); } @@ -1121,12 +1130,14 @@ impl Installer { // TODO in how far do we need to do anything here to ensure dev packages being updated to latest in lock without version change are treated correctly? let local_repo_transaction = { - let local_repo_ref = local_repo.borrow(); - let locked_repo_ref = locked_repository.borrow(); + let mut local_repo_ref = local_repo.borrow_mut(); + let mut locked_repo_ref = locked_repository.borrow_mut(); LocalRepoTransaction::new( - &*locked_repo_ref, - local_repo_ref.as_installed_repository_interface().unwrap(), - ) + &mut *locked_repo_ref, + local_repo_ref + .as_installed_repository_interface_mut() + .unwrap(), + )? }; // TODO(phase-b): dispatch_installer_event takes owned Transaction, not &LocalRepoTransaction // self.event_dispatcher.borrow_mut().dispatch_installer_event( @@ -1270,8 +1281,8 @@ impl Installer { for_update: bool, platform_repo: &PlatformRepository, root_aliases: &Vec<IndexMap<String, String>>, - locked_repository: Option<&dyn RepositoryInterface>, - ) -> RepositorySet { + locked_repository: Option<&mut dyn RepositoryInterface>, + ) -> anyhow::Result<RepositorySet> { let minimum_stability: String; let mut stability_flags: IndexMap<String, i64>; @@ -1313,7 +1324,7 @@ impl Installer { .unwrap_or_default(); let mut tmp: IndexMap<String, AnyConstraint> = IndexMap::new(); - for package in locked_repository.unwrap().get_packages() { + for package in locked_repository.unwrap().get_packages()? { let constraint = SimpleConstraint::new( "=".to_string(), package.get_version().to_string(), @@ -1395,14 +1406,14 @@ impl Installer { let _ = repository_set.add_repository(additional_fixed_repository.clone()); } - repository_set + Ok(repository_set) } fn create_policy( &mut self, for_update: bool, locked_repo: Option<&crate::repository::LockArrayRepositoryHandle>, - ) -> std::rc::Rc<dyn PolicyInterface> { + ) -> anyhow::Result<std::rc::Rc<dyn PolicyInterface>> { let mut prefer_stable: Option<bool> = None; let mut prefer_lowest: Option<bool> = None; if !for_update { @@ -1421,7 +1432,8 @@ impl Installer { let mut preferred_versions: Option<IndexMap<String, String>> = None; if for_update && self.minimal_update && locked_repo.is_some() { let mut versions: IndexMap<String, String> = IndexMap::new(); - for pkg in CanonicalPackagesTrait::get_packages(&*locked_repo.unwrap().borrow()) { + let pkgs = locked_repo.unwrap().borrow_mut().get_canonical_packages()?; + for pkg in pkgs { if pkg.as_alias().is_some() || (self.update_allow_list.is_some() && self @@ -1438,19 +1450,19 @@ impl Installer { preferred_versions = Some(versions); } - std::rc::Rc::new(DefaultPolicy::new( + Ok(std::rc::Rc::new(DefaultPolicy::new( prefer_stable.unwrap(), prefer_lowest.unwrap(), preferred_versions, - )) + ))) } fn create_request( &self, root_package: RootPackageInterfaceHandle, - platform_repo: &PlatformRepository, + platform_repo: &mut PlatformRepository, locked_repository: Option<&crate::repository::LockArrayRepositoryHandle>, - ) -> Request { + ) -> anyhow::Result<Request> { let mut request = Request::new(locked_repository.cloned()); let root_package_handle: PackageInterfaceHandle = root_package.clone().into(); @@ -1459,9 +1471,9 @@ impl Installer { request.fix_package(alias.get_alias_of().into()); } - let mut fixed_packages = platform_repo.get_packages(); + let mut fixed_packages = platform_repo.get_packages()?; if let Some(ref additional_fixed_repository) = self.additional_fixed_repository { - fixed_packages.extend(additional_fixed_repository.get_packages()); + fixed_packages.extend(additional_fixed_repository.get_packages()?); } // fix the version of all platform packages + additionally installed packages @@ -1489,7 +1501,7 @@ impl Installer { } } - request + Ok(request) } fn require_packages_for_update( @@ -1516,8 +1528,10 @@ impl Installer { IndexMap::new() }; - for locked_package in - CanonicalPackagesTrait::get_packages(&*locked_repository.unwrap().borrow()) + for locked_package in locked_repository + .unwrap() + .borrow_mut() + .get_canonical_packages()? { // exclude alias packages here as for root aliases, both alias and aliased are // present in the lock repo and we only want to require the aliased version @@ -1581,9 +1595,9 @@ impl Installer { /// Replace local repositories with InstalledArrayRepository instances /// /// This is to prevent any accidental modification of the existing repos on disk - fn mock_local_repositories(&self, rm: &mut RepositoryManager) { + fn mock_local_repositories(&self, rm: &mut RepositoryManager) -> anyhow::Result<()> { let mut packages: IndexMap<String, PackageInterfaceHandle> = IndexMap::new(); - for package in rm.get_local_repository().get_packages() { + for package in rm.get_local_repository().get_packages()? { packages.insert(package.to_string(), PackageInterfaceHandle::dup(&package)); } let keys: Vec<String> = packages.keys().cloned().collect(); @@ -1614,6 +1628,8 @@ impl Installer { InstalledArrayRepository::new_with_packages(packages.into_values().collect()) .expect("InstalledArrayRepository::new_with_packages should not fail"), )); + + Ok(()) } fn create_pool_optimizer( diff --git a/crates/shirabe/src/installer/suggested_packages_reporter.rs b/crates/shirabe/src/installer/suggested_packages_reporter.rs index 087e1b5..b2f8876 100644 --- a/crates/shirabe/src/installer/suggested_packages_reporter.rs +++ b/crates/shirabe/src/installer/suggested_packages_reporter.rs @@ -53,11 +53,11 @@ impl SuggestedPackagesReporter { pub fn output( &self, mode: i64, - installed_repo: Option<&InstalledRepository>, + mut installed_repo: Option<&mut InstalledRepository>, only_dependents_of: Option<PackageInterfaceHandle>, - ) { - let suggested_packages = - self.get_filtered_suggestions(installed_repo, only_dependents_of.clone()); + ) -> anyhow::Result<()> { + let suggested_packages = self + .get_filtered_suggestions(installed_repo.as_deref_mut(), only_dependents_of.clone())?; let mut suggesters: IndexMap<String, IndexMap<String, String>> = IndexMap::new(); let mut suggested: IndexMap<String, IndexMap<String, String>> = IndexMap::new(); @@ -80,7 +80,7 @@ impl SuggestedPackagesReporter { self.io.write(&format!("<info>{}</info>", name)); } - return; + return Ok(()); } // Grouped by package @@ -132,37 +132,43 @@ impl SuggestedPackagesReporter { } if let Some(only_dependents_of) = only_dependents_of { - let all_suggested_packages = self.get_filtered_suggestions(installed_repo, None); + let all_suggested_packages = + self.get_filtered_suggestions(installed_repo.as_deref_mut(), None)?; let diff = all_suggested_packages.len() as i64 - suggested_packages.len() as i64; if diff != 0 { self.io.write(&format!("<info>{} additional suggestions</info> by transitive dependencies can be shown with <info>--all</info>", diff)); } } + + Ok(()) } pub fn output_minimalistic( &self, - installed_repo: Option<&InstalledRepository>, + installed_repo: Option<&mut InstalledRepository>, only_dependents_of: Option<PackageInterfaceHandle>, - ) { - let suggested_packages = self.get_filtered_suggestions(installed_repo, only_dependents_of); + ) -> anyhow::Result<()> { + let suggested_packages = + self.get_filtered_suggestions(installed_repo, only_dependents_of)?; if !suggested_packages.is_empty() { self.io.write_error(&format!( "<info>{} package suggestions were added by new dependencies, use `composer suggest` to see details.</info>", suggested_packages.len() )); } + + Ok(()) } fn get_filtered_suggestions( &self, - installed_repo: Option<&InstalledRepository>, + installed_repo: Option<&mut InstalledRepository>, only_dependents_of: Option<PackageInterfaceHandle>, - ) -> Vec<IndexMap<String, String>> { + ) -> anyhow::Result<Vec<IndexMap<String, String>>> { let suggested_packages = self.get_packages(); let mut installed_names: Vec<String> = Vec::new(); if installed_repo.is_some() && !suggested_packages.is_empty() { - for package in installed_repo.unwrap().get_packages() { + for package in installed_repo.unwrap().get_packages()? { installed_names.extend(package.get_names(true)); } } @@ -190,7 +196,7 @@ impl SuggestedPackagesReporter { suggestions.push(suggestion.clone()); } - suggestions + Ok(suggestions) } fn escape_output(&self, string: &str) -> String { diff --git a/crates/shirabe/src/package/locker.rs b/crates/shirabe/src/package/locker.rs index 59b81b1..47a9974 100644 --- a/crates/shirabe/src/package/locker.rs +++ b/crates/shirabe/src/package/locker.rs @@ -966,11 +966,11 @@ impl Locker { Some(FindPackageConstraint::Constraint( link.get_constraint().clone(), )), - ) + )? .is_empty() { let results = installed_repo - .find_packages_with_replacers_and_providers(&link.get_target(), None); + .find_packages_with_replacers_and_providers(&link.get_target(), None)?; if !results.is_empty() { // PHP `reset($results)` returns the first shared package; clone the handle. diff --git a/crates/shirabe/src/package/version/version_selector.rs b/crates/shirabe/src/package/version/version_selector.rs index 31942f9..9e41f97 100644 --- a/crates/shirabe/src/package/version/version_selector.rs +++ b/crates/shirabe/src/package/version/version_selector.rs @@ -36,12 +36,11 @@ pub struct VersionSelector { impl VersionSelector { pub fn new( repository_set: RepositorySet, - platform_repo: Option<&crate::repository::PlatformRepository>, + platform_repo: Option<&mut crate::repository::PlatformRepository>, ) -> anyhow::Result<Self> { let mut platform_constraints: IndexMap<String, Vec<AnyConstraint>> = IndexMap::new(); if let Some(platform_repo) = platform_repo { - for package in <PlatformRepository as RepositoryInterface>::get_packages(platform_repo) - { + for package in platform_repo.get_packages()? { let constraint = SimpleConstraint::new( "==".to_string(), package.get_version().to_string(), @@ -95,7 +94,7 @@ impl VersionSelector { &strtolower(package_name), constraint.as_ref().map(|c| c.clone()), repo_set_flags, - ); + )?; let min_priority = *base_package::STABILITIES.get(preferred_stability).unwrap(); candidates.sort_by(|a, b| { diff --git a/crates/shirabe/src/plugin/plugin_manager.rs b/crates/shirabe/src/plugin/plugin_manager.rs index fb68918..d4c3113 100644 --- a/crates/shirabe/src/plugin/plugin_manager.rs +++ b/crates/shirabe/src/plugin/plugin_manager.rs @@ -138,7 +138,7 @@ impl PluginManager { let root_package = crate::package::RootPackageInterfaceHandle::dup( self.composer_full().borrow().get_package(), ); - self.load_repository(&*repo.borrow(), false, Some(root_package))?; + self.load_repository(&mut *repo.borrow_mut(), false, Some(root_package))?; } if self.global_composer.is_some() && !self.are_plugins_disabled("global") { @@ -150,13 +150,13 @@ impl PluginManager { .get_repository_manager() .borrow() .get_local_repository(); - self.load_repository(&*repo.borrow(), true, None)?; + self.load_repository(&mut *repo.borrow_mut(), true, None)?; } Ok(()) } /// Deactivate all plugins from currently installed plugin packages - pub fn deactivate_installed_plugins(&mut self) { + pub fn deactivate_installed_plugins(&mut self) -> anyhow::Result<()> { // TODO(plugin): deactivation is part of the plugin API if !self.are_plugins_disabled("local") { let repo = self @@ -165,7 +165,7 @@ impl PluginManager { .get_repository_manager() .borrow() .get_local_repository(); - self.deactivate_repository(&*repo.borrow(), false); + self.deactivate_repository(&mut *repo.borrow_mut(), false)?; } if self.global_composer.is_some() && !self.are_plugins_disabled("global") { @@ -177,8 +177,10 @@ impl PluginManager { .get_repository_manager() .borrow() .get_local_repository(); - self.deactivate_repository(&*repo.borrow(), true); + self.deactivate_repository(&mut *repo.borrow_mut(), true)?; } + + Ok(()) } /// Gets all currently active plugin instances @@ -498,12 +500,12 @@ impl PluginManager { fn load_repository( &mut self, - repo: &dyn RepositoryInterface, + repo: &mut dyn RepositoryInterface, is_global_repo: bool, root_package: Option<RootPackageInterfaceHandle>, ) -> anyhow::Result<()> { // TODO(plugin): repository scan for plugin packages - let packages = repo.get_packages(); + let packages = repo.get_packages()?; let mut weights: IndexMap<String, i64> = IndexMap::new(); for package in &packages { @@ -574,9 +576,13 @@ impl PluginManager { Ok(()) } - fn deactivate_repository(&mut self, repo: &dyn RepositoryInterface, _is_global_repo: bool) { + fn deactivate_repository( + &mut self, + repo: &mut dyn RepositoryInterface, + _is_global_repo: bool, + ) -> anyhow::Result<()> { // TODO(plugin): deactivate plugins from a repository - let packages = repo.get_packages(); + let packages = repo.get_packages()?; // PHP: $sortedPackages = array_reverse(PackageSorter::sortPackages($packages)); let mut sorted_packages = PackageSorter::sort_packages( packages.iter().map(|p| p.clone().into()).collect(), @@ -595,6 +601,8 @@ impl PluginManager { self.deactivate_package(package.clone()); } } + + Ok(()) } fn collect_dependencies( @@ -602,11 +610,11 @@ impl PluginManager { installed_repo: &InstalledRepository, mut collected: IndexMap<String, PackageInterfaceHandle>, package: PackageInterfaceHandle, - ) -> IndexMap<String, PackageInterfaceHandle> { + ) -> anyhow::Result<IndexMap<String, PackageInterfaceHandle>> { // TODO(plugin): used by registerPackage to assemble plugin dependency autoload map for (_k, require_link) in &package.get_requires() { for required_package in installed_repo - .find_packages_with_replacers_and_providers(require_link.get_target(), None) + .find_packages_with_replacers_and_providers(require_link.get_target(), None)? { if !collected.contains_key(&required_package.get_name()) { collected.insert(required_package.get_name(), required_package.clone().into()); @@ -614,12 +622,12 @@ impl PluginManager { installed_repo, collected, required_package.clone().into(), - ); + )?; } } } - collected + Ok(collected) } /// Retrieves the path a package is installed to. diff --git a/crates/shirabe/src/repository/advisory_provider_interface.rs b/crates/shirabe/src/repository/advisory_provider_interface.rs index 4b93eca..6b94ca9 100644 --- a/crates/shirabe/src/repository/advisory_provider_interface.rs +++ b/crates/shirabe/src/repository/advisory_provider_interface.rs @@ -11,10 +11,10 @@ pub struct SecurityAdvisoryResult { } pub trait AdvisoryProviderInterface { - fn has_security_advisories(&self) -> bool; + fn has_security_advisories(&mut self) -> anyhow::Result<bool>; fn get_security_advisories( - &self, + &mut self, package_constraint_map: IndexMap<String, AnyConstraint>, allow_partial_advisories: bool, ) -> anyhow::Result<SecurityAdvisoryResult>; diff --git a/crates/shirabe/src/repository/array_repository.rs b/crates/shirabe/src/repository/array_repository.rs index 3a05513..8c23eb3 100644 --- a/crates/shirabe/src/repository/array_repository.rs +++ b/crates/shirabe/src/repository/array_repository.rs @@ -37,6 +37,33 @@ pub struct ArrayRepository { } impl ArrayRepository { + fn get_packages_internal(&self) -> Vec<BasePackageHandle> { + if self.packages.borrow().is_none() { + self.initialize(); + } + + if self.packages.borrow().is_none() { + // TODO(phase-b): propagate the error. + // PHP: throw new \LogicException('initialize failed to initialize the packages array') + panic!( + "{}", + LogicException { + message: "initialize failed to initialize the packages array".to_string(), + code: 0, + } + .message + ); + } + + self.packages + .borrow() + .as_ref() + .unwrap() + .iter() + .map(|p| p.clone()) + .collect() + } + /// @param array<PackageInterface> $packages pub fn new(packages: Vec<PackageInterfaceHandle>) -> Result<Self> { let this = Self { @@ -153,13 +180,13 @@ impl RepositoryInterface for ArrayRepository { } fn load_packages( - &self, + &mut self, package_name_map: IndexMap<String, Option<AnyConstraint>>, acceptable_stabilities: IndexMap<String, i64>, stability_flags: IndexMap<String, i64>, already_loaded: IndexMap<String, IndexMap<String, PackageInterfaceHandle>>, - ) -> LoadPackagesResult { - let packages = self.get_packages(); + ) -> anyhow::Result<LoadPackagesResult> { + let packages = self.get_packages_internal(); let mut result: IndexMap<String, BasePackageHandle> = IndexMap::new(); let mut names_found: IndexMap<String, bool> = IndexMap::new(); @@ -214,17 +241,17 @@ impl RepositoryInterface for ArrayRepository { } } - LoadPackagesResult { + Ok(LoadPackagesResult { names_found: names_found.into_keys().collect(), packages: result, - } + }) } fn find_package( - &self, + &mut self, name: &str, constraint: FindPackageConstraint, - ) -> Option<BasePackageHandle> { + ) -> anyhow::Result<Option<BasePackageHandle>> { let name = strtolower(name); let constraint: AnyConstraint = match constraint { @@ -235,7 +262,7 @@ impl RepositoryInterface for ArrayRepository { } }; - for package in self.get_packages() { + for package in self.get_packages_internal() { if name == package.get_name() { let pkg_constraint = SimpleConstraint::new( "==".to_string(), @@ -243,19 +270,19 @@ impl RepositoryInterface for ArrayRepository { None, ); if constraint.matches(&pkg_constraint.into()) { - return Some(package); + return Ok(Some(package)); } } } - None + Ok(None) } fn find_packages( - &self, + &mut self, name: &str, constraint: Option<FindPackageConstraint>, - ) -> Vec<BasePackageHandle> { + ) -> anyhow::Result<Vec<BasePackageHandle>> { // normalize name let name = strtolower(name); let mut packages = vec![]; @@ -269,7 +296,7 @@ impl RepositoryInterface for ArrayRepository { } }; - for package in self.get_packages() { + for package in self.get_packages_internal() { if name == package.get_name() { if constraint.is_none() || constraint.as_ref().unwrap().matches( @@ -286,10 +313,15 @@ impl RepositoryInterface for ArrayRepository { } } - packages + Ok(packages) } - fn search(&self, query: String, mode: i64, r#type: Option<String>) -> Vec<SearchResult> { + fn search( + &mut self, + query: String, + mode: i64, + r#type: Option<String>, + ) -> anyhow::Result<Vec<SearchResult>> { let regex = if mode == crate::repository::SEARCH_FULLTEXT { let parts = Preg::split("{\\s+}", &preg_quote(&query, None)).unwrap_or_default(); format!("{{(?:{})}}i", implode("|", &parts)) @@ -300,7 +332,7 @@ impl RepositoryInterface for ArrayRepository { }; let mut matches: IndexMap<String, SearchResult> = IndexMap::new(); - for package in self.get_packages() { + for package in self.get_packages_internal() { let mut name = package.get_name(); if mode == crate::repository::SEARCH_VENDOR { // PHP: [$name] = explode('/', $name); @@ -373,13 +405,13 @@ impl RepositoryInterface for ArrayRepository { } } - matches.into_values().collect() + Ok(matches.into_values().collect()) } fn has_package(&self, package: PackageInterfaceHandle) -> bool { if self.package_map.borrow().is_none() { let mut map: IndexMap<String, BasePackageHandle> = IndexMap::new(); - for repo_package in self.get_packages() { + for repo_package in self.get_packages_internal() { map.insert(repo_package.get_unique_name(), repo_package); } *self.package_map.borrow_mut() = Some(map); @@ -392,10 +424,13 @@ impl RepositoryInterface for ArrayRepository { .contains_key(&package.get_unique_name()) } - fn get_providers(&self, package_name: String) -> IndexMap<String, ProviderInfo> { + fn get_providers( + &mut self, + package_name: String, + ) -> anyhow::Result<IndexMap<String, ProviderInfo>> { let mut result: IndexMap<String, ProviderInfo> = IndexMap::new(); - 'candidates: for candidate in self.get_packages() { + 'candidates: for candidate in self.get_packages_internal() { if result.contains_key(&candidate.get_name()) { continue; } @@ -416,33 +451,11 @@ impl RepositoryInterface for ArrayRepository { } } - result + Ok(result) } - fn get_packages(&self) -> Vec<BasePackageHandle> { - if self.packages.borrow().is_none() { - self.initialize(); - } - - if self.packages.borrow().is_none() { - // PHP: throw new \LogicException('initialize failed to initialize the packages array') - panic!( - "{}", - LogicException { - message: "initialize failed to initialize the packages array".to_string(), - code: 0, - } - .message - ); - } - - self.packages - .borrow() - .as_ref() - .unwrap() - .iter() - .map(|p| p.clone()) - .collect() + fn get_packages(&mut self) -> anyhow::Result<Vec<BasePackageHandle>> { + Ok(self.get_packages_internal()) } fn as_any(&self) -> &dyn std::any::Any { diff --git a/crates/shirabe/src/repository/canonical_packages_trait.rs b/crates/shirabe/src/repository/canonical_packages_trait.rs index 5f0ecff..11088aa 100644 --- a/crates/shirabe/src/repository/canonical_packages_trait.rs +++ b/crates/shirabe/src/repository/canonical_packages_trait.rs @@ -1,15 +1,14 @@ //! ref: composer/src/Composer/Repository/CanonicalPackagesTrait.php use crate::package::PackageInterfaceHandle; +use crate::repository::RepositoryInterface; use indexmap::IndexMap; /// Provides get_canonical_packages() to various repository implementations. -pub trait CanonicalPackagesTrait { - fn get_packages(&self) -> Vec<PackageInterfaceHandle>; - +pub trait CanonicalPackagesTrait: RepositoryInterface { /// Get unique packages (at most one package of each name), with aliases resolved and removed. - fn get_canonical_packages(&self) -> Vec<PackageInterfaceHandle> { - let packages = self.get_packages(); + fn get_canonical_packages(&mut self) -> anyhow::Result<Vec<PackageInterfaceHandle>> { + let packages = self.get_packages()?; // get at most one package of each name, preferring non-aliased ones let mut packages_by_name: IndexMap<String, PackageInterfaceHandle> = IndexMap::new(); @@ -34,6 +33,6 @@ pub trait CanonicalPackagesTrait { canonical_packages.push(package); } - canonical_packages + Ok(canonical_packages) } } diff --git a/crates/shirabe/src/repository/composer_repository.rs b/crates/shirabe/src/repository/composer_repository.rs index 591497d..5ef156c 100644 --- a/crates/shirabe/src/repository/composer_repository.rs +++ b/crates/shirabe/src/repository/composer_repository.rs @@ -328,148 +328,6 @@ impl ComposerRepository { self.repo_config.clone() } - /// @inheritDoc - pub fn find_package( - &mut self, - name: String, - constraint: PhpMixed, - ) -> anyhow::Result<Option<BasePackageHandle>> { - // this call initializes loadRootServerFile which is needed for the rest below to work - let has_providers = self.has_providers()?; - - let name = strtolower(&name); - let constraint: AnyConstraint = match constraint { - PhpMixed::String(s) => self.version_parser.parse_constraints(&s)?.clone(), - _ => { - // already a ConstraintInterface object passed as opaque PhpMixed - self.version_parser.parse_constraints("")?.clone() - } - }; - - if self.lazy_providers_url.is_some() { - if self.has_partial_packages()? - && self - .partial_packages_by_name - .as_ref() - .map_or(false, |m| m.contains_key(&name)) - { - let packages = self.what_provides(&name, None, None, IndexMap::new())?; - let packages_vec: Vec<BasePackageHandle> = packages.into_values().collect(); - return Ok( - match self.filter_packages(packages_vec, Some(&constraint), true) { - FindPackageReturn::Package(p) => Some(p), - _ => None, - }, - ); - } - - if self.has_available_package_list && !self.lazy_providers_repo_contains(&name)? { - return Ok(None); - } - - let mut map: IndexMap<String, Option<AnyConstraint>> = IndexMap::new(); - map.insert(name.clone(), Some(constraint)); - let packages = self.load_async_packages(map, None, None, IndexMap::new())?; - - if !packages.packages.is_empty() { - return Ok(packages.packages.into_iter().next().map(|(_, v)| v)); - } - - return Ok(None); - } - - if has_providers { - for provider_name in self.get_provider_names()? { - if name == provider_name { - let packages = - self.what_provides(&provider_name, None, None, IndexMap::new())?; - let packages_vec: Vec<BasePackageHandle> = packages.into_values().collect(); - return Ok( - match self.filter_packages(packages_vec, Some(&constraint), true) { - FindPackageReturn::Package(p) => Some(p), - _ => None, - }, - ); - } - } - - return Ok(None); - } - - Ok(self.inner.find_package( - &name, - crate::repository::FindPackageConstraint::Constraint(constraint), - )) - } - - /// @inheritDoc - pub fn find_packages( - &mut self, - name: String, - constraint: Option<PhpMixed>, - ) -> anyhow::Result<Vec<BasePackageHandle>> { - // this call initializes loadRootServerFile which is needed for the rest below to work - let has_providers = self.has_providers()?; - - let name = strtolower(&name); - let constraint: Option<AnyConstraint> = match constraint { - None => None, - Some(PhpMixed::String(s)) => Some(self.version_parser.parse_constraints(&s)?.clone()), - Some(_) => None, - }; - - if self.lazy_providers_url.is_some() { - if self.has_partial_packages()? - && self - .partial_packages_by_name - .as_ref() - .map_or(false, |m| m.contains_key(&name)) - { - let packages = self.what_provides(&name, None, None, IndexMap::new())?; - let packages_vec: Vec<BasePackageHandle> = packages.into_values().collect(); - return Ok( - match self.filter_packages(packages_vec, constraint.as_ref(), false) { - FindPackageReturn::Packages(v) => v, - _ => vec![], - }, - ); - } - - if self.has_available_package_list && !self.lazy_providers_repo_contains(&name)? { - return Ok(vec![]); - } - - let mut map: IndexMap<String, Option<AnyConstraint>> = IndexMap::new(); - map.insert(name.clone(), constraint); - let result = self.load_async_packages(map, None, None, IndexMap::new())?; - - return Ok(result.packages.into_values().collect()); - } - - if has_providers { - for provider_name in self.get_provider_names()? { - if name == provider_name { - let packages = - self.what_provides(&provider_name, None, None, IndexMap::new())?; - let packages_vec: Vec<BasePackageHandle> = packages.into_values().collect(); - return Ok( - match self.filter_packages(packages_vec, constraint.as_ref(), false) { - FindPackageReturn::Packages(v) => v, - _ => vec![], - }, - ); - } - } - - return Ok(vec![]); - } - - Ok(self.inner.find_packages( - &name, - constraint.map(crate::repository::FindPackageConstraint::Constraint), - )) - } - fn filter_packages( &self, packages: Vec<BasePackageHandle>, @@ -560,7 +418,7 @@ impl ComposerRepository { }.into()); } - Ok(self.inner.get_packages()) + Ok(self.inner.get_packages()?) } /// @param packageFilter Package pattern filter which can include "*" as a wildcard @@ -734,7 +592,7 @@ impl ComposerRepository { acceptable_stabilities, stability_flags, already_loaded, - ); + )?; return Ok(inner_result); } @@ -997,7 +855,7 @@ impl ComposerRepository { } // TODO(phase-b): inner.search returns Vec<SearchResult>; convert to PHP-shaped map - let inner_results = self.inner.search(query, mode, None); + let inner_results = self.inner.search(query, mode, None)?; let converted: Vec<IndexMap<String, PhpMixed>> = inner_results .into_iter() .map(|sr| { @@ -1350,7 +1208,7 @@ impl ComposerRepository { } if Countable::count(&self.inner) > 0 { - for (k, v) in self.inner.get_providers(package_name.to_string()) { + for (k, v) in self.inner.get_providers(package_name.to_string())? { // TODO(phase-b): ProviderInfo -> IndexMap<String, PhpMixed> conversion needed let mut entry: IndexMap<String, PhpMixed> = IndexMap::new(); entry.insert("name".to_string(), PhpMixed::String(v.name)); @@ -3523,3 +3381,277 @@ fn clone_root_data(rd: &RootData) -> RootData { RootData::Data(d) => RootData::Data(d.clone()), } } + +impl shirabe_php_shim::Countable for ComposerRepository { + fn count(&self) -> i64 { + self.inner.count() + } +} + +impl RepositoryInterface for ComposerRepository { + fn has_package(&self, package: PackageInterfaceHandle) -> bool { + self.inner.has_package(package) + } + + /// @inheritDoc + fn find_package( + &mut self, + name: &str, + constraint: crate::repository::FindPackageConstraint, + ) -> anyhow::Result<Option<BasePackageHandle>> { + // this call initializes loadRootServerFile which is needed for the rest below to work + let has_providers = self.has_providers()?; + + let name = strtolower(name); + let constraint: AnyConstraint = match constraint { + crate::repository::FindPackageConstraint::String(s) => { + self.version_parser.parse_constraints(&s)?.clone() + } + crate::repository::FindPackageConstraint::Constraint(c) => c, + }; + + if self.lazy_providers_url.is_some() { + if self.has_partial_packages()? + && self + .partial_packages_by_name + .as_ref() + .map_or(false, |m| m.contains_key(&name)) + { + let packages = self.what_provides(&name, None, None, IndexMap::new())?; + let packages_vec: Vec<BasePackageHandle> = packages.into_values().collect(); + return Ok( + match self.filter_packages(packages_vec, Some(&constraint), true) { + FindPackageReturn::Package(p) => Some(p), + _ => None, + }, + ); + } + + if self.has_available_package_list && !self.lazy_providers_repo_contains(&name)? { + return Ok(None); + } + + let mut map: IndexMap<String, Option<AnyConstraint>> = IndexMap::new(); + map.insert(name.clone(), Some(constraint)); + let packages = self.load_async_packages(map, None, None, IndexMap::new())?; + + if !packages.packages.is_empty() { + return Ok(packages.packages.into_iter().next().map(|(_, v)| v)); + } + + return Ok(None); + } + + if has_providers { + for provider_name in self.get_provider_names()? { + if name == provider_name { + let packages = + self.what_provides(&provider_name, None, None, IndexMap::new())?; + let packages_vec: Vec<BasePackageHandle> = packages.into_values().collect(); + return Ok( + match self.filter_packages(packages_vec, Some(&constraint), true) { + FindPackageReturn::Package(p) => Some(p), + _ => None, + }, + ); + } + } + + return Ok(None); + } + + self.inner.find_package( + &name, + crate::repository::FindPackageConstraint::Constraint(constraint), + ) + } + + /// @inheritDoc + fn find_packages( + &mut self, + name: &str, + constraint: Option<crate::repository::FindPackageConstraint>, + ) -> anyhow::Result<Vec<BasePackageHandle>> { + // this call initializes loadRootServerFile which is needed for the rest below to work + let has_providers = self.has_providers()?; + + let name = strtolower(name); + let constraint: Option<AnyConstraint> = match constraint { + None => None, + Some(crate::repository::FindPackageConstraint::String(s)) => { + Some(self.version_parser.parse_constraints(&s)?.clone()) + } + Some(crate::repository::FindPackageConstraint::Constraint(c)) => Some(c), + }; + + if self.lazy_providers_url.is_some() { + if self.has_partial_packages()? + && self + .partial_packages_by_name + .as_ref() + .map_or(false, |m| m.contains_key(&name)) + { + let packages = self.what_provides(&name, None, None, IndexMap::new())?; + let packages_vec: Vec<BasePackageHandle> = packages.into_values().collect(); + return Ok( + match self.filter_packages(packages_vec, constraint.as_ref(), false) { + FindPackageReturn::Packages(v) => v, + _ => vec![], + }, + ); + } + + if self.has_available_package_list && !self.lazy_providers_repo_contains(&name)? { + return Ok(vec![]); + } + + let mut map: IndexMap<String, Option<AnyConstraint>> = IndexMap::new(); + map.insert(name.clone(), constraint); + let result = self.load_async_packages(map, None, None, IndexMap::new())?; + + return Ok(result.packages.into_values().collect()); + } + + if has_providers { + for provider_name in self.get_provider_names()? { + if name == provider_name { + let packages = + self.what_provides(&provider_name, None, None, IndexMap::new())?; + let packages_vec: Vec<BasePackageHandle> = packages.into_values().collect(); + return Ok( + match self.filter_packages(packages_vec, constraint.as_ref(), false) { + FindPackageReturn::Packages(v) => v, + _ => vec![], + }, + ); + } + } + + return Ok(vec![]); + } + + self.inner.find_packages( + &name, + constraint.map(crate::repository::FindPackageConstraint::Constraint), + ) + } + + fn get_packages(&mut self) -> anyhow::Result<Vec<BasePackageHandle>> { + ComposerRepository::get_packages(self) + } + + 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> { + ComposerRepository::load_packages( + self, + package_name_map, + acceptable_stabilities, + stability_flags, + already_loaded, + ) + } + + fn search( + &mut self, + query: String, + mode: i64, + r#type: Option<String>, + ) -> anyhow::Result<Vec<crate::repository::SearchResult>> { + let raw = ComposerRepository::search(self, query, mode, r#type)?; + Ok(raw + .into_iter() + .map(|m| crate::repository::SearchResult { + name: m + .get("name") + .and_then(|v| v.as_string()) + .unwrap_or("") + .to_string(), + description: m + .get("description") + .and_then(|v| v.as_string()) + .map(|s| s.to_string()), + abandoned: None, + url: m + .get("url") + .and_then(|v| v.as_string()) + .map(|s| s.to_string()), + }) + .collect()) + } + + fn get_providers( + &mut self, + package_name: String, + ) -> anyhow::Result<IndexMap<String, crate::repository::ProviderInfo>> { + let raw = ComposerRepository::get_providers(self, &package_name)?; + Ok(raw + .into_iter() + .map(|(k, m)| { + ( + k, + crate::repository::ProviderInfo { + name: m + .get("name") + .and_then(|v| v.as_string()) + .unwrap_or("") + .to_string(), + description: m + .get("description") + .and_then(|v| v.as_string()) + .map(|s| s.to_string()), + r#type: m + .get("type") + .and_then(|v| v.as_string()) + .unwrap_or("") + .to_string(), + }, + ) + }) + .collect()) + } + + fn get_repo_name(&self) -> String { + ComposerRepository::get_repo_name(self) + } + + fn as_advisory_provider(&self) -> Option<&dyn crate::repository::AdvisoryProviderInterface> { + Some(self) + } + + fn as_advisory_provider_mut( + &mut self, + ) -> Option<&mut dyn crate::repository::AdvisoryProviderInterface> { + Some(self) + } + + fn as_any(&self) -> &dyn std::any::Any { + self + } + + fn set_self_handle(&self, weak: RepositoryInterfaceWeakHandle) { + ComposerRepository::set_self_handle(self, weak); + } +} + +impl crate::repository::AdvisoryProviderInterface for ComposerRepository { + fn has_security_advisories(&mut self) -> anyhow::Result<bool> { + ComposerRepository::has_security_advisories(self) + } + + fn get_security_advisories( + &mut self, + package_constraint_map: IndexMap<String, shirabe_semver::constraint::AnyConstraint>, + allow_partial_advisories: bool, + ) -> anyhow::Result<SecurityAdvisoryResult> { + ComposerRepository::get_security_advisories( + self, + package_constraint_map, + allow_partial_advisories, + ) + } +} diff --git a/crates/shirabe/src/repository/composite_repository.rs b/crates/shirabe/src/repository/composite_repository.rs index 6c167f2..78bbc6a 100644 --- a/crates/shirabe/src/repository/composite_repository.rs +++ b/crates/shirabe/src/repository/composite_repository.rs @@ -84,46 +84,46 @@ impl RepositoryInterface for CompositeRepository { } fn find_package( - &self, + &mut self, name: &str, constraint: FindPackageConstraint, - ) -> Option<BasePackageHandle> { + ) -> anyhow::Result<Option<BasePackageHandle>> { for repository in &self.repositories { - let package = repository.find_package(name, constraint.clone()); + let package = repository.find_package(name, constraint.clone())?; if package.is_some() { - return package; + return Ok(package); } } - None + Ok(None) } fn find_packages( - &self, + &mut self, name: &str, constraint: Option<FindPackageConstraint>, - ) -> Vec<BasePackageHandle> { + ) -> anyhow::Result<Vec<BasePackageHandle>> { let mut packages = vec![]; for repository in &self.repositories { - packages.extend(repository.find_packages(name, constraint.clone())); + packages.extend(repository.find_packages(name, constraint.clone())?); } - packages + Ok(packages) } - fn get_packages(&self) -> Vec<BasePackageHandle> { + fn get_packages(&mut self) -> anyhow::Result<Vec<BasePackageHandle>> { let mut packages = vec![]; for repository in &self.repositories { - packages.extend(repository.get_packages()); + packages.extend(repository.get_packages()?); } - packages + Ok(packages) } fn load_packages( - &self, + &mut self, package_name_map: IndexMap<String, Option<AnyConstraint>>, acceptable_stabilities: IndexMap<String, i64>, stability_flags: IndexMap<String, i64>, already_loaded: IndexMap<String, IndexMap<String, PackageInterfaceHandle>>, - ) -> LoadPackagesResult { + ) -> anyhow::Result<LoadPackagesResult> { let mut all_packages = IndexMap::new(); let mut all_names_found = vec![]; @@ -137,7 +137,7 @@ impl RepositoryInterface for CompositeRepository { acceptable_stabilities.clone(), stability_flags.clone(), already_loaded.clone(), - ); + )?; all_packages.extend(result.packages); all_names_found.extend(result.names_found); } @@ -148,26 +148,34 @@ impl RepositoryInterface for CompositeRepository { .filter(|s| seen.insert(s.clone())) .collect(); - LoadPackagesResult { + Ok(LoadPackagesResult { packages: all_packages, names_found: unique_names, - } + }) } - fn search(&self, query: String, mode: i64, r#type: Option<String>) -> Vec<SearchResult> { + fn search( + &mut self, + query: String, + mode: i64, + r#type: Option<String>, + ) -> anyhow::Result<Vec<SearchResult>> { let mut matches = vec![]; for repository in &self.repositories { - matches.extend(repository.search(query.clone(), mode, r#type.clone())); + matches.extend(repository.search(query.clone(), mode, r#type.clone())?); } - matches + Ok(matches) } - fn get_providers(&self, package_name: String) -> IndexMap<String, ProviderInfo> { + fn get_providers( + &mut self, + package_name: String, + ) -> anyhow::Result<IndexMap<String, ProviderInfo>> { let mut results = IndexMap::new(); for repository in &self.repositories { - results.extend(repository.get_providers(package_name.clone())); + results.extend(repository.get_providers(package_name.clone())?); } - results + Ok(results) } fn as_any(&self) -> &dyn std::any::Any { diff --git a/crates/shirabe/src/repository/filesystem_repository.rs b/crates/shirabe/src/repository/filesystem_repository.rs index db9a8c6..c373bd9 100644 --- a/crates/shirabe/src/repository/filesystem_repository.rs +++ b/crates/shirabe/src/repository/filesystem_repository.rs @@ -463,7 +463,7 @@ impl FilesystemRepository { /// @param array<string, string> $installPaths fn generate_installed_versions( - &self, + &mut self, installation_manager: &InstallationManager, install_paths: &IndexMap<String, Option<String>>, dev_mode: bool, @@ -478,7 +478,7 @@ impl FilesystemRepository { )); let mut packages: Vec<PackageInterfaceHandle> = self .inner - .get_packages() + .get_packages()? .into_iter() .map(|p| p.into()) .collect(); diff --git a/crates/shirabe/src/repository/filter_repository.rs b/crates/shirabe/src/repository/filter_repository.rs index ecf1f0f..a49382a 100644 --- a/crates/shirabe/src/repository/filter_repository.rs +++ b/crates/shirabe/src/repository/filter_repository.rs @@ -151,7 +151,16 @@ impl FilterRepository { impl shirabe_php_shim::Countable for FilterRepository { fn count(&self) -> i64 { if self.repo.count() > 0 { - self.get_packages().len() as i64 + // TODO(phase-b): propagate the error + // self.get_packages()?.len() as i64 + self.repo + .get_packages() + .map(|pkgs| { + pkgs.iter() + .filter(|p| self.is_allowed(&p.get_name())) + .count() as i64 + }) + .unwrap_or(0) } else { 0 } @@ -164,43 +173,43 @@ impl RepositoryInterface for FilterRepository { } fn find_package( - &self, + &mut self, name: &str, constraint: FindPackageConstraint, - ) -> Option<BasePackageHandle> { + ) -> anyhow::Result<Option<BasePackageHandle>> { if !self.is_allowed(name) { - return None; + return Ok(None); } self.repo.find_package(name, constraint) } fn find_packages( - &self, + &mut self, name: &str, constraint: Option<FindPackageConstraint>, - ) -> Vec<BasePackageHandle> { + ) -> anyhow::Result<Vec<BasePackageHandle>> { if !self.is_allowed(name) { - return Vec::new(); + return Ok(Vec::new()); } self.repo.find_packages(name, constraint) } fn load_packages( - &self, + &mut self, mut package_name_map: IndexMap<String, Option<AnyConstraint>>, acceptable_stabilities: IndexMap<String, i64>, stability_flags: IndexMap<String, i64>, already_loaded: IndexMap<String, IndexMap<String, PackageInterfaceHandle>>, - ) -> LoadPackagesResult { + ) -> anyhow::Result<LoadPackagesResult> { package_name_map.retain(|name, _| self.is_allowed(name)); if package_name_map.is_empty() { - return LoadPackagesResult { + return Ok(LoadPackagesResult { names_found: Vec::new(), packages: IndexMap::new(), - }; + }); } let mut result = self.repo.load_packages( @@ -208,46 +217,54 @@ impl RepositoryInterface for FilterRepository { acceptable_stabilities, stability_flags, already_loaded, - ); + )?; if !self.canonical { result.names_found = Vec::new(); } - result + Ok(result) } - fn search(&self, query: String, mode: i64, r#type: Option<String>) -> Vec<SearchResult> { + fn search( + &mut self, + query: String, + mode: i64, + r#type: Option<String>, + ) -> anyhow::Result<Vec<SearchResult>> { let mut result = Vec::new(); - for package in self.repo.search(query, mode, r#type) { + for package in self.repo.search(query, mode, r#type)? { if self.is_allowed(&package.name) { result.push(package); } } - result + Ok(result) } - fn get_packages(&self) -> Vec<BasePackageHandle> { + fn get_packages(&mut self) -> anyhow::Result<Vec<BasePackageHandle>> { let mut result = Vec::new(); - for package in self.repo.get_packages() { + for package in self.repo.get_packages()? { if self.is_allowed(&package.get_name()) { result.push(package); } } - result + Ok(result) } - fn get_providers(&self, package_name: String) -> IndexMap<String, ProviderInfo> { + fn get_providers( + &mut self, + package_name: String, + ) -> anyhow::Result<IndexMap<String, ProviderInfo>> { let mut result = IndexMap::new(); - for (name, provider) in self.repo.get_providers(package_name) { + for (name, provider) in self.repo.get_providers(package_name)? { if self.is_allowed(&provider.name) { result.insert(name, provider); } } - result + Ok(result) } fn get_repo_name(&self) -> String { @@ -264,29 +281,37 @@ impl RepositoryInterface for FilterRepository { } } + fn as_advisory_provider_mut(&mut self) -> Option<&mut dyn AdvisoryProviderInterface> { + if self.repo.borrow().as_advisory_provider().is_some() { + Some(self) + } else { + None + } + } + fn as_any(&self) -> &dyn std::any::Any { self } } impl AdvisoryProviderInterface for FilterRepository { - fn has_security_advisories(&self) -> bool { - let repo = self.repo.borrow(); - if let Some(advisory_repo) = repo.as_advisory_provider() { + fn has_security_advisories(&mut self) -> anyhow::Result<bool> { + let mut repo = self.repo.borrow_mut(); + if let Some(advisory_repo) = repo.as_advisory_provider_mut() { advisory_repo.has_security_advisories() } else { - false + Ok(false) } } fn get_security_advisories( - &self, + &mut self, mut package_constraint_map: IndexMap<String, AnyConstraint>, allow_partial_advisories: bool, ) -> anyhow::Result<SecurityAdvisoryResult> { - let repo = self.repo.borrow(); - if let Some(advisory_repo) = repo.as_advisory_provider() { - package_constraint_map.retain(|name, _| self.is_allowed(name)); + package_constraint_map.retain(|name, _| self.is_allowed(name)); + let mut repo = self.repo.borrow_mut(); + if let Some(advisory_repo) = repo.as_advisory_provider_mut() { advisory_repo.get_security_advisories(package_constraint_map, allow_partial_advisories) } else { Ok(SecurityAdvisoryResult { diff --git a/crates/shirabe/src/repository/handle.rs b/crates/shirabe/src/repository/handle.rs index 73d4493..0d02b83 100644 --- a/crates/shirabe/src/repository/handle.rs +++ b/crates/shirabe/src/repository/handle.rs @@ -74,8 +74,8 @@ impl RepositoryInterfaceHandle { self.0.borrow().get_repo_name() } - pub fn get_packages(&self) -> Vec<BasePackageHandle> { - self.0.borrow().get_packages() + pub fn get_packages(&self) -> anyhow::Result<Vec<BasePackageHandle>> { + self.0.borrow_mut().get_packages() } pub fn has_package(&self, package: PackageInterfaceHandle) -> bool { @@ -86,16 +86,16 @@ impl RepositoryInterfaceHandle { &self, name: &str, constraint: FindPackageConstraint, - ) -> Option<BasePackageHandle> { - self.0.borrow().find_package(name, constraint) + ) -> anyhow::Result<Option<BasePackageHandle>> { + self.0.borrow_mut().find_package(name, constraint) } pub fn find_packages( &self, name: &str, constraint: Option<FindPackageConstraint>, - ) -> Vec<BasePackageHandle> { - self.0.borrow().find_packages(name, constraint) + ) -> anyhow::Result<Vec<BasePackageHandle>> { + self.0.borrow_mut().find_packages(name, constraint) } pub fn load_packages( @@ -104,8 +104,8 @@ impl RepositoryInterfaceHandle { acceptable_stabilities: IndexMap<String, i64>, stability_flags: IndexMap<String, i64>, already_loaded: IndexMap<String, IndexMap<String, PackageInterfaceHandle>>, - ) -> LoadPackagesResult { - self.0.borrow().load_packages( + ) -> anyhow::Result<LoadPackagesResult> { + self.0.borrow_mut().load_packages( package_name_map, acceptable_stabilities, stability_flags, @@ -113,12 +113,20 @@ impl RepositoryInterfaceHandle { ) } - pub fn search(&self, query: String, mode: i64, r#type: Option<String>) -> Vec<SearchResult> { - self.0.borrow().search(query, mode, r#type) + pub fn search( + &self, + query: String, + mode: i64, + r#type: Option<String>, + ) -> anyhow::Result<Vec<SearchResult>> { + self.0.borrow_mut().search(query, mode, r#type) } - pub fn get_providers(&self, package_name: String) -> IndexMap<String, ProviderInfo> { - self.0.borrow().get_providers(package_name) + pub fn get_providers( + &self, + package_name: String, + ) -> anyhow::Result<IndexMap<String, ProviderInfo>> { + self.0.borrow_mut().get_providers(package_name) } // --- InstalledRepositoryInterface helpers (valid only when the wrapped repository is one) --- @@ -137,12 +145,11 @@ impl RepositoryInterfaceHandle { .and_then(|r| r.get_dev_mode()) } - pub fn get_canonical_packages(&self) -> Vec<PackageInterfaceHandle> { - self.0 - .borrow() - .as_installed_repository_interface() - .map(|r| r.get_canonical_packages()) - .unwrap_or_default() + pub fn get_canonical_packages(&self) -> anyhow::Result<Vec<PackageInterfaceHandle>> { + match self.0.borrow_mut().as_installed_repository_interface_mut() { + Some(r) => r.get_canonical_packages(), + None => Ok(Vec::new()), + } } pub fn get_dev_package_names(&self) -> Vec<String> { diff --git a/crates/shirabe/src/repository/installed_array_repository.rs b/crates/shirabe/src/repository/installed_array_repository.rs index 1520497..2d3965b 100644 --- a/crates/shirabe/src/repository/installed_array_repository.rs +++ b/crates/shirabe/src/repository/installed_array_repository.rs @@ -68,7 +68,9 @@ impl WritableRepositoryInterface for InstalledArrayRepository { todo!() } - fn get_canonical_packages(&self) -> Vec<crate::package::PackageInterfaceHandle> { + fn get_canonical_packages( + &mut self, + ) -> anyhow::Result<Vec<crate::package::PackageInterfaceHandle>> { todo!() } @@ -96,35 +98,43 @@ impl RepositoryInterface for InstalledArrayRepository { todo!() } fn find_package( - &self, + &mut self, _name: &str, _constraint: FindPackageConstraint, - ) -> Option<BasePackageHandle> { + ) -> anyhow::Result<Option<BasePackageHandle>> { todo!() } fn find_packages( - &self, + &mut self, _name: &str, _constraint: Option<FindPackageConstraint>, - ) -> Vec<BasePackageHandle> { + ) -> anyhow::Result<Vec<BasePackageHandle>> { todo!() } - fn get_packages(&self) -> Vec<BasePackageHandle> { + fn get_packages(&mut self) -> anyhow::Result<Vec<BasePackageHandle>> { todo!() } fn load_packages( - &self, + &mut self, _package_name_map: IndexMap<String, Option<AnyConstraint>>, _acceptable_stabilities: IndexMap<String, i64>, _stability_flags: IndexMap<String, i64>, _already_loaded: IndexMap<String, IndexMap<String, PackageInterfaceHandle>>, - ) -> LoadPackagesResult { + ) -> anyhow::Result<LoadPackagesResult> { todo!() } - fn search(&self, _query: String, _mode: i64, _type: Option<String>) -> Vec<SearchResult> { + fn search( + &mut self, + _query: String, + _mode: i64, + _type: Option<String>, + ) -> anyhow::Result<Vec<SearchResult>> { todo!() } - fn get_providers(&self, _package_name: String) -> IndexMap<String, ProviderInfo> { + fn get_providers( + &mut self, + _package_name: String, + ) -> anyhow::Result<IndexMap<String, ProviderInfo>> { todo!() } fn get_repo_name(&self) -> String { diff --git a/crates/shirabe/src/repository/installed_filesystem_repository.rs b/crates/shirabe/src/repository/installed_filesystem_repository.rs index 73a9f1a..84bf1ca 100644 --- a/crates/shirabe/src/repository/installed_filesystem_repository.rs +++ b/crates/shirabe/src/repository/installed_filesystem_repository.rs @@ -78,7 +78,9 @@ impl WritableRepositoryInterface for InstalledFilesystemRepository { todo!() } - fn get_canonical_packages(&self) -> Vec<crate::package::PackageInterfaceHandle> { + fn get_canonical_packages( + &mut self, + ) -> anyhow::Result<Vec<crate::package::PackageInterfaceHandle>> { todo!() } @@ -106,35 +108,43 @@ impl RepositoryInterface for InstalledFilesystemRepository { todo!() } fn find_package( - &self, + &mut self, _name: &str, _constraint: FindPackageConstraint, - ) -> Option<BasePackageHandle> { + ) -> anyhow::Result<Option<BasePackageHandle>> { todo!() } fn find_packages( - &self, + &mut self, _name: &str, _constraint: Option<FindPackageConstraint>, - ) -> Vec<BasePackageHandle> { + ) -> anyhow::Result<Vec<BasePackageHandle>> { todo!() } - fn get_packages(&self) -> Vec<BasePackageHandle> { + fn get_packages(&mut self) -> anyhow::Result<Vec<BasePackageHandle>> { todo!() } fn load_packages( - &self, + &mut self, _package_name_map: IndexMap<String, Option<AnyConstraint>>, _acceptable_stabilities: IndexMap<String, i64>, _stability_flags: IndexMap<String, i64>, _already_loaded: IndexMap<String, IndexMap<String, PackageInterfaceHandle>>, - ) -> LoadPackagesResult { + ) -> anyhow::Result<LoadPackagesResult> { todo!() } - fn search(&self, _query: String, _mode: i64, _type: Option<String>) -> Vec<SearchResult> { + fn search( + &mut self, + _query: String, + _mode: i64, + _type: Option<String>, + ) -> anyhow::Result<Vec<SearchResult>> { todo!() } - fn get_providers(&self, _package_name: String) -> IndexMap<String, ProviderInfo> { + fn get_providers( + &mut self, + _package_name: String, + ) -> anyhow::Result<IndexMap<String, ProviderInfo>> { todo!() } fn get_repo_name(&self) -> String { diff --git a/crates/shirabe/src/repository/installed_repository.rs b/crates/shirabe/src/repository/installed_repository.rs index b857bc2..e199556 100644 --- a/crates/shirabe/src/repository/installed_repository.rs +++ b/crates/shirabe/src/repository/installed_repository.rs @@ -53,7 +53,7 @@ impl InstalledRepository { &self, name: &str, constraint: Option<FindPackageConstraint>, - ) -> Vec<BasePackageHandle> { + ) -> anyhow::Result<Vec<BasePackageHandle>> { let name = name.to_lowercase(); let constraint: Option<AnyConstraint> = match constraint { @@ -67,7 +67,7 @@ impl InstalledRepository { let mut matches = vec![]; for repo in self.inner.get_repositories() { - 'candidates: for candidate in repo.get_packages() { + 'candidates: for candidate in repo.get_packages()? { if name == candidate.get_name() { if constraint.is_none() || constraint.as_ref().unwrap().matches( @@ -105,17 +105,17 @@ impl InstalledRepository { } } - matches + Ok(matches) } pub fn get_dependents( - &self, + &mut self, needle: NeedleInput, constraint: Option<AnyConstraint>, invert: bool, recurse: bool, packages_found: Option<Vec<String>>, - ) -> Vec<DependentsEntry> { + ) -> anyhow::Result<Vec<DependentsEntry>> { let mut needles: Vec<String> = match needle { NeedleInput::Single(s) => vec![s.to_lowercase()], NeedleInput::Multiple(v) => v.into_iter().map(|s| s.to_lowercase()).collect(), @@ -125,14 +125,14 @@ impl InstalledRepository { let mut packages_found = packages_found.unwrap_or_else(|| needles.clone()); let mut root_package: Option<BasePackageHandle> = None; - for package in self.inner.get_packages() { + for package in self.inner.get_packages()? { if package.as_root().is_some() { root_package = Some(package.clone()); break; } } - for package in self.inner.get_packages() { + for package in self.inner.get_packages()? { let mut links: IndexMap<String, Link> = package.get_requires(); let mut packages_in_tree = packages_found.clone(); @@ -164,7 +164,7 @@ impl InstalledRepository { false, true, Some(packages_in_tree.clone()), - ) + )? } else { vec![] }; @@ -205,7 +205,7 @@ impl InstalledRepository { false, true, Some(packages_in_tree.clone()), - ) + )? } else { vec![] }; @@ -221,7 +221,7 @@ impl InstalledRepository { if invert && needles.contains(&package.get_name().to_string()) { for link in package.get_conflicts().values() { - for pkg in self.find_packages(link.get_target(), None) { + for pkg in self.find_packages(link.get_target(), None)? { let version = SimpleConstraint::new( "=".to_string(), pkg.get_version().to_string(), @@ -236,7 +236,7 @@ impl InstalledRepository { for link in package.get_conflicts().values() { if needles.contains(&link.get_target().to_string()) { - for pkg in self.find_packages(link.get_target(), None) { + for pkg in self.find_packages(link.get_target(), None)? { let version = SimpleConstraint::new( "=".to_string(), pkg.get_version().to_string(), @@ -267,7 +267,7 @@ impl InstalledRepository { .find_package( link.get_target(), FindPackageConstraint::Constraint(link.get_constraint().clone()), - ) + )? .is_some() { continue; @@ -276,7 +276,7 @@ impl InstalledRepository { let platform_pkg = self.find_package( link.get_target(), FindPackageConstraint::String("*".to_string()), - ); + )?; let description = platform_pkg .as_ref() .map(|p| format!("but {} is installed", p.get_pretty_version())) @@ -300,7 +300,7 @@ impl InstalledRepository { continue; } - for pkg in self.get_packages() { + for pkg in self.get_packages()? { if !pkg.get_names(true).contains(&link.get_target().to_string()) { continue; } @@ -379,7 +379,7 @@ impl InstalledRepository { } // ksort($results) - no-op for a numerically-indexed Vec - results + Ok(results) } pub fn add_repository(&mut self, repository: RepositoryInterfaceHandle) -> anyhow::Result<()> { @@ -425,32 +425,32 @@ impl RepositoryInterface for InstalledRepository { } fn find_package( - &self, + &mut self, name: &str, constraint: FindPackageConstraint, - ) -> Option<BasePackageHandle> { + ) -> anyhow::Result<Option<BasePackageHandle>> { self.inner.find_package(name, constraint) } fn find_packages( - &self, + &mut self, name: &str, constraint: Option<FindPackageConstraint>, - ) -> Vec<BasePackageHandle> { + ) -> anyhow::Result<Vec<BasePackageHandle>> { self.inner.find_packages(name, constraint) } - fn get_packages(&self) -> Vec<BasePackageHandle> { + fn get_packages(&mut self) -> anyhow::Result<Vec<BasePackageHandle>> { self.inner.get_packages() } fn load_packages( - &self, + &mut self, package_name_map: IndexMap<String, Option<AnyConstraint>>, acceptable_stabilities: IndexMap<String, i64>, stability_flags: IndexMap<String, i64>, already_loaded: IndexMap<String, IndexMap<String, PackageInterfaceHandle>>, - ) -> LoadPackagesResult { + ) -> anyhow::Result<LoadPackagesResult> { self.inner.load_packages( package_name_map, acceptable_stabilities, @@ -459,11 +459,19 @@ impl RepositoryInterface for InstalledRepository { ) } - fn search(&self, query: String, mode: i64, r#type: Option<String>) -> Vec<SearchResult> { + fn search( + &mut self, + query: String, + mode: i64, + r#type: Option<String>, + ) -> anyhow::Result<Vec<SearchResult>> { self.inner.search(query, mode, r#type) } - fn get_providers(&self, package_name: String) -> IndexMap<String, ProviderInfo> { + fn get_providers( + &mut self, + package_name: String, + ) -> anyhow::Result<IndexMap<String, ProviderInfo>> { self.inner.get_providers(package_name) } diff --git a/crates/shirabe/src/repository/lock_array_repository.rs b/crates/shirabe/src/repository/lock_array_repository.rs index 08e888a..250ca90 100644 --- a/crates/shirabe/src/repository/lock_array_repository.rs +++ b/crates/shirabe/src/repository/lock_array_repository.rs @@ -17,11 +17,7 @@ pub struct LockArrayRepository { inner: ArrayRepository, } -impl CanonicalPackagesTrait for LockArrayRepository { - fn get_packages(&self) -> Vec<PackageInterfaceHandle> { - RepositoryInterface::get_packages(&self.inner) - } -} +impl CanonicalPackagesTrait for LockArrayRepository {} impl LockArrayRepository { pub fn new(packages: Vec<PackageInterfaceHandle>) -> anyhow::Result<Self> { @@ -47,32 +43,32 @@ impl RepositoryInterface for LockArrayRepository { } fn find_package( - &self, + &mut self, name: &str, constraint: FindPackageConstraint, - ) -> Option<BasePackageHandle> { + ) -> anyhow::Result<Option<BasePackageHandle>> { self.inner.find_package(name, constraint) } fn find_packages( - &self, + &mut self, name: &str, constraint: Option<FindPackageConstraint>, - ) -> Vec<BasePackageHandle> { + ) -> anyhow::Result<Vec<BasePackageHandle>> { self.inner.find_packages(name, constraint) } - fn get_packages(&self) -> Vec<BasePackageHandle> { - RepositoryInterface::get_packages(&self.inner) + fn get_packages(&mut self) -> anyhow::Result<Vec<BasePackageHandle>> { + RepositoryInterface::get_packages(&mut self.inner) } fn load_packages( - &self, + &mut self, package_name_map: IndexMap<String, Option<AnyConstraint>>, acceptable_stabilities: IndexMap<String, i64>, stability_flags: IndexMap<String, i64>, already_loaded: IndexMap<String, IndexMap<String, PackageInterfaceHandle>>, - ) -> LoadPackagesResult { + ) -> anyhow::Result<LoadPackagesResult> { self.inner.load_packages( package_name_map, acceptable_stabilities, @@ -81,11 +77,19 @@ impl RepositoryInterface for LockArrayRepository { ) } - fn search(&self, query: String, mode: i64, r#type: Option<String>) -> Vec<SearchResult> { + fn search( + &mut self, + query: String, + mode: i64, + r#type: Option<String>, + ) -> anyhow::Result<Vec<SearchResult>> { self.inner.search(query, mode, r#type) } - fn get_providers(&self, package_name: String) -> IndexMap<String, ProviderInfo> { + fn get_providers( + &mut self, + package_name: String, + ) -> anyhow::Result<IndexMap<String, ProviderInfo>> { self.inner.get_providers(package_name) } diff --git a/crates/shirabe/src/repository/package_repository.rs b/crates/shirabe/src/repository/package_repository.rs index b5280a8..83e13d0 100644 --- a/crates/shirabe/src/repository/package_repository.rs +++ b/crates/shirabe/src/repository/package_repository.rs @@ -82,12 +82,12 @@ impl PackageRepository { } impl AdvisoryProviderInterface for PackageRepository { - fn has_security_advisories(&self) -> bool { - !self.security_advisories.is_empty() + fn has_security_advisories(&mut self) -> anyhow::Result<bool> { + Ok(!self.security_advisories.is_empty()) } fn get_security_advisories( - &self, + &mut self, package_constraint_map: IndexMap<String, AnyConstraint>, allow_partial_advisories: bool, ) -> anyhow::Result<SecurityAdvisoryResult> { diff --git a/crates/shirabe/src/repository/platform_repository.rs b/crates/shirabe/src/repository/platform_repository.rs index 0d10e3a..957e335 100644 --- a/crates/shirabe/src/repository/platform_repository.rs +++ b/crates/shirabe/src/repository/platform_repository.rs @@ -1615,7 +1615,7 @@ impl PlatformRepository { let overrider = self.inner.find_package( &name, crate::repository::FindPackageConstraint::String("*".to_string()), - ); + )?; let actual_text = if let Some(ref ov) = overrider { if package.get_version() == ov.get_version() { "same as actual".to_string() @@ -1888,14 +1888,14 @@ impl PlatformRepository { } pub fn search( - &self, + &mut self, query: String, mode: i64, r#type: Option<String>, - ) -> Vec<crate::repository::SearchResult> { + ) -> anyhow::Result<Vec<crate::repository::SearchResult>> { // suppress vendor search as there are no vendors to match in platform packages if mode == crate::repository::SEARCH_VENDOR { - return Vec::new(); + return Ok(Vec::new()); } self.inner.search(query, mode, r#type) @@ -1954,32 +1954,32 @@ impl crate::repository::RepositoryInterface for PlatformRepository { } fn find_package( - &self, + &mut self, name: &str, constraint: crate::repository::FindPackageConstraint, - ) -> Option<crate::package::BasePackageHandle> { + ) -> anyhow::Result<Option<crate::package::BasePackageHandle>> { self.inner.find_package(name, constraint) } fn find_packages( - &self, + &mut self, name: &str, constraint: Option<crate::repository::FindPackageConstraint>, - ) -> Vec<crate::package::BasePackageHandle> { + ) -> anyhow::Result<Vec<crate::package::BasePackageHandle>> { self.inner.find_packages(name, constraint) } - fn get_packages(&self) -> Vec<crate::package::BasePackageHandle> { + fn get_packages(&mut self) -> anyhow::Result<Vec<crate::package::BasePackageHandle>> { self.inner.get_packages() } fn load_packages( - &self, + &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, crate::package::PackageInterfaceHandle>>, - ) -> crate::repository::LoadPackagesResult { + ) -> anyhow::Result<crate::repository::LoadPackagesResult> { self.inner.load_packages( package_name_map, acceptable_stabilities, @@ -1989,18 +1989,18 @@ impl crate::repository::RepositoryInterface for PlatformRepository { } fn search( - &self, + &mut self, query: String, mode: i64, r#type: Option<String>, - ) -> Vec<crate::repository::SearchResult> { + ) -> anyhow::Result<Vec<crate::repository::SearchResult>> { self.inner.search(query, mode, r#type) } fn get_providers( - &self, + &mut self, package_name: String, - ) -> IndexMap<String, crate::repository::ProviderInfo> { + ) -> anyhow::Result<IndexMap<String, crate::repository::ProviderInfo>> { self.inner.get_providers(package_name) } diff --git a/crates/shirabe/src/repository/repository_interface.rs b/crates/shirabe/src/repository/repository_interface.rs index e75f54e..249bd85 100644 --- a/crates/shirabe/src/repository/repository_interface.rs +++ b/crates/shirabe/src/repository/repository_interface.rs @@ -56,30 +56,38 @@ pub trait RepositoryInterface: Countable + std::fmt::Debug { fn has_package(&self, package: PackageInterfaceHandle) -> bool; fn find_package( - &self, + &mut self, name: &str, constraint: FindPackageConstraint, - ) -> Option<BasePackageHandle>; + ) -> anyhow::Result<Option<BasePackageHandle>>; fn find_packages( - &self, + &mut self, name: &str, constraint: Option<FindPackageConstraint>, - ) -> Vec<BasePackageHandle>; + ) -> anyhow::Result<Vec<BasePackageHandle>>; - fn get_packages(&self) -> Vec<BasePackageHandle>; + fn get_packages(&mut self) -> anyhow::Result<Vec<BasePackageHandle>>; fn load_packages( - &self, + &mut self, package_name_map: IndexMap<String, Option<AnyConstraint>>, acceptable_stabilities: IndexMap<String, i64>, stability_flags: IndexMap<String, i64>, already_loaded: IndexMap<String, IndexMap<String, PackageInterfaceHandle>>, - ) -> LoadPackagesResult; + ) -> anyhow::Result<LoadPackagesResult>; - fn search(&self, query: String, mode: i64, r#type: Option<String>) -> Vec<SearchResult>; + fn search( + &mut self, + query: String, + mode: i64, + r#type: Option<String>, + ) -> anyhow::Result<Vec<SearchResult>>; - fn get_providers(&self, package_name: String) -> IndexMap<String, ProviderInfo>; + fn get_providers( + &mut self, + package_name: String, + ) -> anyhow::Result<IndexMap<String, ProviderInfo>>; fn get_repo_name(&self) -> String; @@ -87,6 +95,10 @@ pub trait RepositoryInterface: Countable + std::fmt::Debug { None } + fn as_advisory_provider_mut(&mut self) -> Option<&mut dyn AdvisoryProviderInterface> { + None + } + fn as_installed_repository_interface( &self, ) -> Option<&dyn crate::repository::InstalledRepositoryInterface> { diff --git a/crates/shirabe/src/repository/repository_manager.rs b/crates/shirabe/src/repository/repository_manager.rs index dd69731..9b1d9ab 100644 --- a/crates/shirabe/src/repository/repository_manager.rs +++ b/crates/shirabe/src/repository/repository_manager.rs @@ -55,23 +55,23 @@ impl RepositoryManager { &self, name: &str, constraint: &AnyConstraint, - ) -> Option<PackageInterfaceHandle> { + ) -> anyhow::Result<Option<PackageInterfaceHandle>> { for repository in &self.repositories { if let Some(package) = repository.find_package( name, crate::repository::FindPackageConstraint::Constraint(constraint.clone()), - ) { - return Some(package.into()); + )? { + return Ok(Some(package.into())); } } - None + Ok(None) } pub fn find_packages( &self, name: &str, constraint: &AnyConstraint, - ) -> Vec<PackageInterfaceHandle> { + ) -> anyhow::Result<Vec<PackageInterfaceHandle>> { let mut packages: Vec<PackageInterfaceHandle> = vec![]; for repository in self.get_repositories() { for p in repository.find_packages( @@ -79,11 +79,11 @@ impl RepositoryManager { Some(crate::repository::FindPackageConstraint::Constraint( constraint.clone(), )), - ) { + )? { packages.push(p); } } - packages + Ok(packages) } pub fn add_repository(&mut self, repository: RepositoryInterfaceHandle) { diff --git a/crates/shirabe/src/repository/repository_set.rs b/crates/shirabe/src/repository/repository_set.rs index 077c3f6..3cc4b9f 100644 --- a/crates/shirabe/src/repository/repository_set.rs +++ b/crates/shirabe/src/repository/repository_set.rs @@ -206,7 +206,7 @@ impl RepositorySet { name: &str, constraint: Option<AnyConstraint>, flags: i64, - ) -> Vec<BasePackageHandle> { + ) -> anyhow::Result<Vec<BasePackageHandle>> { let ignore_stability = (flags & Self::ALLOW_UNACCEPTABLE_STABILITIES) != 0; let load_from_all_repos = (flags & Self::ALLOW_SHADOWED_REPOSITORIES) != 0; @@ -217,7 +217,7 @@ impl RepositorySet { let constraint_clone = constraint .as_ref() .map(|c| FindPackageConstraint::Constraint(c.clone())); - let found = repository.find_packages(name, constraint_clone); + let found = repository.find_packages(name, constraint_clone)?; packages.push(found); } } else { @@ -243,7 +243,7 @@ impl RepositorySet { acceptable, stability_flags, IndexMap::new(), - ); + )?; packages.push(result.packages.into_values().collect()); for name_found in result.names_found { @@ -264,7 +264,7 @@ impl RepositorySet { // when using loadPackages above (!$loadFromAllRepos) the repos already filter for stability so no need to do it again if ignore_stability || !load_from_all_repos { - return candidates; + return Ok(candidates); } let mut result: Vec<BasePackageHandle> = vec![]; @@ -274,7 +274,7 @@ impl RepositorySet { } } - result + Ok(result) } /// @param string[] $packageNames @@ -375,17 +375,16 @@ impl RepositorySet { let mut repo_advisories: Vec<IndexMap<String, Vec<PartialOrFullSecurityAdvisory>>> = vec![]; for repository in &self.repositories { let attempt: Result<()> = (|| -> Result<()> { - let repo_ref = repository.borrow(); - let Some(advisory_repo) = repo_ref.as_advisory_provider() else { + let mut repo_ref = repository.borrow_mut(); + let Some(advisory_repo) = repo_ref.as_advisory_provider_mut() else { return Ok(()); }; - if !advisory_repo.has_security_advisories() { + if !advisory_repo.has_security_advisories()? { return Ok(()); } let result = advisory_repo.get_security_advisories( - // TODO(phase-b): clone package_constraint_map values - todo!("clone package_constraint_map"), + package_constraint_map.clone(), allow_partial_advisories, )?; repo_advisories.push(result.advisories); @@ -429,16 +428,16 @@ impl RepositorySet { pub fn get_providers( &self, package_name: &str, - ) -> IndexMap<String, crate::repository::ProviderInfo> { + ) -> anyhow::Result<IndexMap<String, crate::repository::ProviderInfo>> { let mut providers: IndexMap<String, crate::repository::ProviderInfo> = IndexMap::new(); for repository in &self.repositories { - let repo_providers = repository.get_providers(package_name.to_string()); + let repo_providers = repository.get_providers(package_name.to_string())?; if !repo_providers.is_empty() { providers.extend(repo_providers); } } - providers + Ok(providers) } /// Check for each given package name whether it would be accepted by this RepositorySet in the given $stability @@ -531,7 +530,7 @@ impl RepositorySet { let mut packages: Vec<BasePackageHandle> = vec![]; for repository in &self.repositories { - for mut package in repository.get_packages() { + for mut package in repository.get_packages()? { let name = package.get_name(); let version = package.get_version(); packages.push(package.clone()); diff --git a/crates/shirabe/src/repository/root_package_repository.rs b/crates/shirabe/src/repository/root_package_repository.rs index 22ca437..985f86e 100644 --- a/crates/shirabe/src/repository/root_package_repository.rs +++ b/crates/shirabe/src/repository/root_package_repository.rs @@ -37,32 +37,32 @@ impl RepositoryInterface for RootPackageRepository { } fn find_package( - &self, + &mut self, name: &str, constraint: crate::repository::FindPackageConstraint, - ) -> Option<BasePackageHandle> { + ) -> anyhow::Result<Option<BasePackageHandle>> { self.inner.find_package(name, constraint) } fn find_packages( - &self, + &mut self, name: &str, constraint: Option<crate::repository::FindPackageConstraint>, - ) -> Vec<BasePackageHandle> { + ) -> anyhow::Result<Vec<BasePackageHandle>> { self.inner.find_packages(name, constraint) } - fn get_packages(&self) -> Vec<BasePackageHandle> { + fn get_packages(&mut self) -> anyhow::Result<Vec<BasePackageHandle>> { self.inner.get_packages() } fn load_packages( - &self, + &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>>, - ) -> crate::repository::LoadPackagesResult { + ) -> anyhow::Result<crate::repository::LoadPackagesResult> { self.inner.load_packages( package_name_map, acceptable_stabilities, @@ -71,11 +71,19 @@ impl RepositoryInterface for RootPackageRepository { ) } - fn search(&self, query: String, mode: i64, r#type: Option<String>) -> Vec<SearchResult> { + fn search( + &mut self, + query: String, + mode: i64, + r#type: Option<String>, + ) -> anyhow::Result<Vec<SearchResult>> { self.inner.search(query, mode, r#type) } - fn get_providers(&self, package_name: String) -> IndexMap<String, ProviderInfo> { + fn get_providers( + &mut self, + package_name: String, + ) -> anyhow::Result<IndexMap<String, ProviderInfo>> { self.inner.get_providers(package_name) } diff --git a/crates/shirabe/src/repository/vcs_repository.rs b/crates/shirabe/src/repository/vcs_repository.rs index 7a570c6..9a39b76 100644 --- a/crates/shirabe/src/repository/vcs_repository.rs +++ b/crates/shirabe/src/repository/vcs_repository.rs @@ -520,7 +520,7 @@ impl VcsRepository { ) .into(), ), - ) { + )? { if is_very_verbose { self.io.write_error(&format!( "<warning>Skipped tag {}, it conflicts with an another tag ({}) as both resolve to {} internally</warning>", @@ -763,7 +763,7 @@ impl VcsRepository { .overwrite_error4("", false, None, io_interface::NORMAL); } - if self.inner.get_packages().is_empty() { + if self.inner.get_packages()?.is_empty() { return Err(InvalidRepositoryException::new(format!( "No valid composer.json was found in any branch or tag of {}, could not load a package from it.", self.url @@ -948,7 +948,7 @@ impl VcsRepository { SimpleConstraint::new("=".to_string(), version_normalized.to_string(), None) .into(), ), - ) { + )? { if is_very_verbose { self.io.write_error(&format!( "<warning>Skipped cached version {}, it conflicts with an another tag ({}) as both resolve to {} internally</warning>", diff --git a/crates/shirabe/src/repository/writable_array_repository.rs b/crates/shirabe/src/repository/writable_array_repository.rs index ac9df8f..1c07b8c 100644 --- a/crates/shirabe/src/repository/writable_array_repository.rs +++ b/crates/shirabe/src/repository/writable_array_repository.rs @@ -76,8 +76,8 @@ impl WritableArrayRepository { Vec::new() } - pub fn get_packages(&self) -> Vec<crate::package::BasePackageHandle> { - crate::repository::RepositoryInterface::get_packages(&self.inner) + pub fn get_packages(&mut self) -> anyhow::Result<Vec<crate::package::BasePackageHandle>> { + self.inner.get_packages() } pub fn get_repo_name(&self) -> String { diff --git a/crates/shirabe/src/repository/writable_repository_interface.rs b/crates/shirabe/src/repository/writable_repository_interface.rs index abbcbe7..ae62e1e 100644 --- a/crates/shirabe/src/repository/writable_repository_interface.rs +++ b/crates/shirabe/src/repository/writable_repository_interface.rs @@ -12,7 +12,7 @@ pub trait WritableRepositoryInterface: RepositoryInterface { fn remove_package(&mut self, package: PackageInterfaceHandle) -> Result<()>; - fn get_canonical_packages(&self) -> Vec<PackageInterfaceHandle>; + fn get_canonical_packages(&mut self) -> Result<Vec<PackageInterfaceHandle>>; fn reload(&mut self); |
