diff options
| author | nsfisis <nsfisis@gmail.com> | 2026-05-17 02:53:53 +0900 |
|---|---|---|
| committer | nsfisis <nsfisis@gmail.com> | 2026-05-17 02:53:53 +0900 |
| commit | a1c7e6908a26e10f6e1f23a51721664b5e2d838d (patch) | |
| tree | c575c76f1b43359ed74913da4c6a2636643f1ba0 /crates/shirabe/src/installer | |
| parent | 7f606f36fef0c0467c3c0db3d0da33af486dae8a (diff) | |
| download | php-shirabe-a1c7e6908a26e10f6e1f23a51721664b5e2d838d.tar.gz php-shirabe-a1c7e6908a26e10f6e1f23a51721664b5e2d838d.tar.zst php-shirabe-a1c7e6908a26e10f6e1f23a51721664b5e2d838d.zip | |
chore(style): cargo fmt
Diffstat (limited to 'crates/shirabe/src/installer')
| -rw-r--r-- | crates/shirabe/src/installer/binary_installer.rs | 39 | ||||
| -rw-r--r-- | crates/shirabe/src/installer/installation_manager.rs | 82 | ||||
| -rw-r--r-- | crates/shirabe/src/installer/installer_event.rs | 9 | ||||
| -rw-r--r-- | crates/shirabe/src/installer/installer_interface.rs | 47 | ||||
| -rw-r--r-- | crates/shirabe/src/installer/library_installer.rs | 9 | ||||
| -rw-r--r-- | crates/shirabe/src/installer/metapackage_installer.rs | 99 | ||||
| -rw-r--r-- | crates/shirabe/src/installer/noop_installer.rs | 79 | ||||
| -rw-r--r-- | crates/shirabe/src/installer/package_event.rs | 2 | ||||
| -rw-r--r-- | crates/shirabe/src/installer/plugin_installer.rs | 85 | ||||
| -rw-r--r-- | crates/shirabe/src/installer/project_installer.rs | 71 | ||||
| -rw-r--r-- | crates/shirabe/src/installer/suggested_packages_reporter.rs | 47 |
11 files changed, 410 insertions, 159 deletions
diff --git a/crates/shirabe/src/installer/binary_installer.rs b/crates/shirabe/src/installer/binary_installer.rs index eb533a4..0e5b3d9 100644 --- a/crates/shirabe/src/installer/binary_installer.rs +++ b/crates/shirabe/src/installer/binary_installer.rs @@ -2,9 +2,9 @@ use shirabe_external_packages::composer::pcre::preg::Preg; use shirabe_php_shim::{ - basename, basename_with_suffix, chmod, dirname, fclose, fgets, file_exists, file_get_contents, - file_put_contents, fopen, is_dir, is_file, is_link, realpath, rmdir, substr, trim, umask, - PhpMixed, + PhpMixed, basename, basename_with_suffix, chmod, dirname, fclose, fgets, file_exists, + file_get_contents, file_put_contents, fopen, is_dir, is_file, is_link, realpath, rmdir, substr, + trim, umask, }; use crate::io::io_interface::IOInterface; @@ -166,10 +166,9 @@ impl BinaryInstaller { let handle = fopen(bin, "r"); let line = fgets(handle.clone()).unwrap_or_default(); fclose(handle); - if let Some(m) = Preg::is_match_strict_groups( - r"{^#!/(?:usr/bin/env )?(?:[^/]+/)*(.+)$}m", - &line, - ) { + if let Some(m) = + Preg::is_match_strict_groups(r"{^#!/(?:usr/bin/env )?(?:[^/]+/)*(.+)$}m", &line) + { return trim(m.get(1).map(|s| s.as_str()).unwrap_or(""), None); } @@ -246,7 +245,10 @@ impl BinaryInstaller { SET BIN_TARGET=%~dp0/{}\r\n\ SET COMPOSER_RUNTIME_BIN_DIR=%~dp0\r\n\ {} \"%BIN_TARGET%\" %*\r\n", - trim(&ProcessExecutor::escape(&basename_with_suffix(link, ".bat")), Some("\"'")), + trim( + &ProcessExecutor::escape(&basename_with_suffix(link, ".bat")), + Some("\"'") + ), caller, ); } @@ -273,12 +275,10 @@ impl BinaryInstaller { let bin_contents = file_get_contents(bin).unwrap_or_default(); // For php files, we generate a PHP proxy instead of a shell one, // which allows calling the proxy with a custom php process - if let Some(m) = Preg::is_match_with_indexed_captures( - r"{^(#!.*\r?\n)?[\r\n\t ]*<\?php}", - &bin_contents, - ) - .ok() - .flatten() + if let Some(m) = + Preg::is_match_with_indexed_captures(r"{^(#!.*\r?\n)?[\r\n\t ]*<\?php}", &bin_contents) + .ok() + .flatten() { // carry over the existing shebang if present, otherwise add our own let proxy_code = if m.get(1).is_none() { @@ -291,9 +291,7 @@ impl BinaryInstaller { .find_shortest_path_code(link, bin, false, true); let mut stream_proxy_code = String::new(); let mut stream_hint = String::new(); - let mut globals_code = format!( - "$GLOBALS['_composer_bin_dir'] = __DIR__;\n", - ); + let mut globals_code = format!("$GLOBALS['_composer_bin_dir'] = __DIR__;\n",); let mut phpunit_hack1 = String::new(); let mut phpunit_hack2 = String::new(); // Don't expose autoload path when vendor dir was not set in custom installers @@ -326,11 +324,14 @@ impl BinaryInstaller { phpunit_hack1 = "'phpvfscomposer://'.".to_string(); phpunit_hack2 = " $data = str_replace('__DIR__', var_export(dirname($this->realpath), true), $data); - $data = str_replace('__FILE__', var_export($this->realpath, true), $data);".to_string(); + $data = str_replace('__FILE__', var_export($this->realpath, true), $data);" + .to_string(); } } if trim(m.get(0).map(|s| s.as_str()).unwrap_or(""), None) != "<?php" { - stream_hint = format!(" using a stream wrapper to prevent the shebang from being output on PHP<8\n *"); + stream_hint = format!( + " using a stream wrapper to prevent the shebang from being output on PHP<8\n *" + ); stream_proxy_code = format!( "if (PHP_VERSION_ID < 80000) {{\n if (!class_exists('Composer\\BinProxyWrapper')) {{\n /**\n * @internal\n */\n final class BinProxyWrapper\n {{\n private $handle;\n private $position;\n private $realpath;\n\n public function stream_open($path, $mode, $options, &$opened_path)\n {{\n // get rid of phpvfscomposer:// prefix for __FILE__ & __DIR__ resolution\n $opened_path = substr($path, 17);\n $this->realpath = realpath($opened_path) ?: $opened_path;\n $opened_path = {phpunit_hack1}$this->realpath;\n $this->handle = fopen($this->realpath, $mode);\n $this->position = 0;\n\n return (bool) $this->handle;\n }}\n\n public function stream_read($count)\n {{\n $data = fread($this->handle, $count);\n\n if ($this->position === 0) {{\n $data = preg_replace('{{^#!.*\\r?\\n}}', '', $data);\n }}{phpunit_hack2}\n\n $this->position += strlen($data);\n\n return $data;\n }}\n\n public function stream_cast($castAs)\n {{\n return $this->handle;\n }}\n\n public function stream_close()\n {{\n fclose($this->handle);\n }}\n\n public function stream_lock($operation)\n {{\n return $operation ? flock($this->handle, $operation) : true;\n }}\n\n public function stream_seek($offset, $whence)\n {{\n if (0 === fseek($this->handle, $offset, $whence)) {{\n $this->position = ftell($this->handle);\n return true;\n }}\n\n return false;\n }}\n\n public function stream_tell()\n {{\n return $this->position;\n }}\n\n public function stream_eof()\n {{\n return feof($this->handle);\n }}\n\n public function stream_stat()\n {{\n return array();\n }}\n\n public function stream_set_option($option, $arg1, $arg2)\n {{\n return true;\n }}\n\n public function url_stat($path, $flags)\n {{\n $path = substr($path, 17);\n if (file_exists($path)) {{\n return stat($path);\n }}\n\n return false;\n }}\n }}\n }}\n\n if (\n (function_exists('stream_get_wrappers') && in_array('phpvfscomposer', stream_get_wrappers(), true))\n || (function_exists('stream_wrapper_register') && stream_wrapper_register('phpvfscomposer', 'Composer\\BinProxyWrapper'))\n ) {{\n return include(\"phpvfscomposer://\" . {bin_path_exported});\n }}\n}}\n", phpunit_hack1 = phpunit_hack1, diff --git a/crates/shirabe/src/installer/installation_manager.rs b/crates/shirabe/src/installer/installation_manager.rs index 52831aa..519091f 100644 --- a/crates/shirabe/src/installer/installation_manager.rs +++ b/crates/shirabe/src/installer/installation_manager.rs @@ -6,8 +6,8 @@ use shirabe_external_packages::react::promise; use shirabe_external_packages::react::promise::promise_interface::PromiseInterface; use shirabe_external_packages::seld::signal::signal_handler::SignalHandler; use shirabe_php_shim::{ - array_search_mixed, array_splice, array_unshift, count, http_build_query, json_encode, - str_contains, str_replace, strpos, strtolower, ucfirst, InvalidArgumentException, PhpMixed, + InvalidArgumentException, PhpMixed, array_search_mixed, array_splice, array_unshift, count, + http_build_query, json_encode, str_contains, str_replace, strpos, strtolower, ucfirst, }; use crate::dependency_resolver::operation::install_operation::InstallOperation; @@ -143,7 +143,9 @@ impl InstallationManager { && self.is_package_installed(repo, alias.get_alias_of())?); } - Ok(self.get_installer(package.get_type())?.is_installed(repo, package)) + Ok(self + .get_installer(package.get_type())? + .is_installed(repo, package)) } /// Install binary for the given package. @@ -177,8 +179,10 @@ impl InstallationManager { download_only: bool, ) -> Result<()> { // @var array<callable(): ?PromiseInterface<void|null>> $cleanupPromises - let mut cleanup_promises: IndexMap<i64, Box<dyn Fn() -> Option<Box<dyn PromiseInterface>>>> = - IndexMap::new(); + let mut cleanup_promises: IndexMap< + i64, + Box<dyn Fn() -> Option<Box<dyn PromiseInterface>>>, + > = IndexMap::new(); let signal_handler = SignalHandler::create( vec![ @@ -452,13 +456,16 @@ impl InstallationManager { }; if run_scripts && self.event_dispatcher.is_some() { - self.event_dispatcher.as_mut().unwrap().dispatch_package_event( - event_name, - dev_mode, - repo, - all_operations, - operation.as_ref(), - ); + self.event_dispatcher + .as_mut() + .unwrap() + .dispatch_package_event( + event_name, + dev_mode, + repo, + all_operations, + operation.as_ref(), + ); } let _dispatcher = self.event_dispatcher.as_ref(); @@ -524,11 +531,8 @@ impl InstallationManager { // progress.clear(); // ProgressBar in non-decorated output does not output a final line-break and clear() does nothing if !self.io.is_decorated() { - self.io.write_error( - PhpMixed::String(String::new()), - true, - IOInterface::NORMAL, - ); + self.io + .write_error(PhpMixed::String(String::new()), true, IOInterface::NORMAL); } } } @@ -536,7 +540,10 @@ impl InstallationManager { /// Executes download operation. /// /// @phpstan-return PromiseInterface<void|null>|null - pub fn download(&mut self, package: &dyn PackageInterface) -> Option<Box<dyn PromiseInterface>> { + pub fn download( + &mut self, + package: &dyn PackageInterface, + ) -> Option<Box<dyn PromiseInterface>> { let installer = self.get_installer(package.get_type()).ok()?; let promise = installer.cleanup("install", package, None); @@ -579,7 +586,10 @@ impl InstallationManager { self.mark_for_notification(target); promise } else { - let promise = self.get_installer(initial_type).ok()?.uninstall(repo, initial); + let promise = self + .get_installer(initial_type) + .ok()? + .uninstall(repo, initial); let promise = match promise { Some(p) => p, None => promise::resolve(None), @@ -667,10 +677,7 @@ impl InstallationManager { let mut opts: IndexMap<String, PhpMixed> = IndexMap::new(); opts.insert("retry-auth-failure".to_string(), PhpMixed::Bool(false)); let mut http: IndexMap<String, PhpMixed> = IndexMap::new(); - http.insert( - "method".to_string(), - PhpMixed::String("POST".to_string()), - ); + http.insert("method".to_string(), PhpMixed::String("POST".to_string())); http.insert( "header".to_string(), PhpMixed::List(vec![Box::new(PhpMixed::String( @@ -685,15 +692,16 @@ impl InstallationManager { opts.insert( "http".to_string(), PhpMixed::Array( - http.into_iter() - .map(|(k, v)| (k, Box::new(v))) - .collect(), + http.into_iter().map(|(k, v)| (k, Box::new(v))).collect(), ), ); - promises.push(self.loop_.get_http_downloader().add(&url, &PhpMixed::Array( - opts.into_iter().map(|(k, v)| (k, Box::new(v))).collect(), - ))); + promises.push(self.loop_.get_http_downloader().add( + &url, + &PhpMixed::Array( + opts.into_iter().map(|(k, v)| (k, Box::new(v))).collect(), + ), + )); } continue; @@ -715,8 +723,7 @@ impl InstallationManager { if let Some(metadata) = FileDownloader::download_metadata().get(package.get_name()) { - package_notification - .insert("downloaded".to_string(), metadata.clone()); + package_notification.insert("downloaded".to_string(), metadata.clone()); } else { package_notification .insert("downloaded".to_string(), PhpMixed::Bool(false)); @@ -757,16 +764,13 @@ impl InstallationManager { http.insert("timeout".to_string(), PhpMixed::Int(6)); opts.insert( "http".to_string(), - PhpMixed::Array( - http.into_iter() - .map(|(k, v)| (k, Box::new(v))) - .collect(), - ), + PhpMixed::Array(http.into_iter().map(|(k, v)| (k, Box::new(v))).collect()), ); - promises.push(self.loop_.get_http_downloader().add(repo_url, &PhpMixed::Array( - opts.into_iter().map(|(k, v)| (k, Box::new(v))).collect(), - ))); + promises.push(self.loop_.get_http_downloader().add( + repo_url, + &PhpMixed::Array(opts.into_iter().map(|(k, v)| (k, Box::new(v))).collect()), + )); } self.loop_.wait(promises, None); diff --git a/crates/shirabe/src/installer/installer_event.rs b/crates/shirabe/src/installer/installer_event.rs index 3d0dccc..456a4bd 100644 --- a/crates/shirabe/src/installer/installer_event.rs +++ b/crates/shirabe/src/installer/installer_event.rs @@ -25,7 +25,14 @@ impl InstallerEvent { transaction: Transaction, ) -> Self { let inner = Event::new(event_name, vec![], vec![]); - Self { inner, composer, io, dev_mode, execute_operations, transaction } + Self { + inner, + composer, + io, + dev_mode, + execute_operations, + transaction, + } } pub fn get_composer(&self) -> &Composer { diff --git a/crates/shirabe/src/installer/installer_interface.rs b/crates/shirabe/src/installer/installer_interface.rs index fc651bb..16cf10c 100644 --- a/crates/shirabe/src/installer/installer_interface.rs +++ b/crates/shirabe/src/installer/installer_interface.rs @@ -1,25 +1,56 @@ //! ref: composer/src/Composer/Installer/InstallerInterface.php -use shirabe_external_packages::react::promise::promise_interface::PromiseInterface; use crate::package::package_interface::PackageInterface; use crate::repository::installed_repository_interface::InstalledRepositoryInterface; +use shirabe_external_packages::react::promise::promise_interface::PromiseInterface; pub trait InstallerInterface { fn supports(&self, package_type: &str) -> bool; - fn is_installed(&self, repo: &dyn InstalledRepositoryInterface, package: &dyn PackageInterface) -> bool; + fn is_installed( + &self, + repo: &dyn InstalledRepositoryInterface, + package: &dyn PackageInterface, + ) -> bool; - fn download(&self, package: &dyn PackageInterface, prev_package: Option<&dyn PackageInterface>) -> anyhow::Result<Option<Box<dyn PromiseInterface>>>; + fn download( + &self, + package: &dyn PackageInterface, + prev_package: Option<&dyn PackageInterface>, + ) -> anyhow::Result<Option<Box<dyn PromiseInterface>>>; - fn prepare(&self, r#type: &str, package: &dyn PackageInterface, prev_package: Option<&dyn PackageInterface>) -> anyhow::Result<Option<Box<dyn PromiseInterface>>>; + fn prepare( + &self, + r#type: &str, + package: &dyn PackageInterface, + prev_package: Option<&dyn PackageInterface>, + ) -> anyhow::Result<Option<Box<dyn PromiseInterface>>>; - fn install(&self, repo: &mut dyn InstalledRepositoryInterface, package: &dyn PackageInterface) -> anyhow::Result<Option<Box<dyn PromiseInterface>>>; + fn install( + &self, + repo: &mut dyn InstalledRepositoryInterface, + package: &dyn PackageInterface, + ) -> anyhow::Result<Option<Box<dyn PromiseInterface>>>; - fn update(&self, repo: &mut dyn InstalledRepositoryInterface, initial: &dyn PackageInterface, target: &dyn PackageInterface) -> anyhow::Result<Option<Box<dyn PromiseInterface>>>; + fn update( + &self, + repo: &mut dyn InstalledRepositoryInterface, + initial: &dyn PackageInterface, + target: &dyn PackageInterface, + ) -> anyhow::Result<Option<Box<dyn PromiseInterface>>>; - fn uninstall(&self, repo: &mut dyn InstalledRepositoryInterface, package: &dyn PackageInterface) -> anyhow::Result<Option<Box<dyn PromiseInterface>>>; + fn uninstall( + &self, + repo: &mut dyn InstalledRepositoryInterface, + package: &dyn PackageInterface, + ) -> anyhow::Result<Option<Box<dyn PromiseInterface>>>; - fn cleanup(&self, r#type: &str, package: &dyn PackageInterface, prev_package: Option<&dyn PackageInterface>) -> anyhow::Result<Option<Box<dyn PromiseInterface>>>; + fn cleanup( + &self, + r#type: &str, + package: &dyn PackageInterface, + prev_package: Option<&dyn PackageInterface>, + ) -> anyhow::Result<Option<Box<dyn PromiseInterface>>>; fn get_install_path(&self, package: &dyn PackageInterface) -> Option<String>; } diff --git a/crates/shirabe/src/installer/library_installer.rs b/crates/shirabe/src/installer/library_installer.rs index cc6e7a6..af11ef6 100644 --- a/crates/shirabe/src/installer/library_installer.rs +++ b/crates/shirabe/src/installer/library_installer.rs @@ -6,7 +6,7 @@ use anyhow::Result; use shirabe_external_packages::composer::pcre::preg::Preg; use shirabe_external_packages::react::promise::promise_interface::PromiseInterface; use shirabe_php_shim::{ - is_link, preg_quote, realpath, rmdir, rtrim, strpos, InvalidArgumentException, LogicException, + InvalidArgumentException, LogicException, is_link, preg_quote, realpath, rmdir, rtrim, strpos, }; use crate::composer::Composer; @@ -84,8 +84,11 @@ impl LibraryInstaller { /// Make sure binaries are installed for a given package. pub fn ensure_binaries_presence(&self, package: &dyn PackageInterface) { - self.binary_installer - .install_binaries(package, &self.get_install_path(package).unwrap(), false); + self.binary_installer.install_binaries( + package, + &self.get_install_path(package).unwrap(), + false, + ); } /// Returns the base path of the package without target-dir path diff --git a/crates/shirabe/src/installer/metapackage_installer.rs b/crates/shirabe/src/installer/metapackage_installer.rs index 8be21e7..0a5f872 100644 --- a/crates/shirabe/src/installer/metapackage_installer.rs +++ b/crates/shirabe/src/installer/metapackage_installer.rs @@ -1,8 +1,5 @@ //! ref: composer/src/Composer/Installer/MetapackageInstaller.php -use anyhow::Result; -use shirabe_php_shim::InvalidArgumentException; -use shirabe_external_packages::react::promise::promise_interface::PromiseInterface; use crate::dependency_resolver::operation::install_operation::InstallOperation; use crate::dependency_resolver::operation::uninstall_operation::UninstallOperation; use crate::dependency_resolver::operation::update_operation::UpdateOperation; @@ -10,6 +7,9 @@ use crate::installer::installer_interface::InstallerInterface; use crate::io::io_interface::IOInterface; use crate::package::package_interface::PackageInterface; use crate::repository::installed_repository_interface::InstalledRepositoryInterface; +use anyhow::Result; +use shirabe_external_packages::react::promise::promise_interface::PromiseInterface; +use shirabe_php_shim::InvalidArgumentException; #[derive(Debug)] pub struct MetapackageInstaller { @@ -27,59 +27,116 @@ impl InstallerInterface for MetapackageInstaller { package_type == "metapackage" } - fn is_installed(&self, repo: &dyn InstalledRepositoryInterface, package: &dyn PackageInterface) -> bool { + fn is_installed( + &self, + repo: &dyn InstalledRepositoryInterface, + package: &dyn PackageInterface, + ) -> bool { repo.has_package(package) } - fn download(&self, _package: &dyn PackageInterface, _prev_package: Option<&dyn PackageInterface>) -> Result<Option<Box<dyn PromiseInterface>>> { - Ok(Some(shirabe_external_packages::react::promise::resolve(None))) + fn download( + &self, + _package: &dyn PackageInterface, + _prev_package: Option<&dyn PackageInterface>, + ) -> Result<Option<Box<dyn PromiseInterface>>> { + Ok(Some(shirabe_external_packages::react::promise::resolve( + None, + ))) } - fn prepare(&self, _type: &str, _package: &dyn PackageInterface, _prev_package: Option<&dyn PackageInterface>) -> Result<Option<Box<dyn PromiseInterface>>> { - Ok(Some(shirabe_external_packages::react::promise::resolve(None))) + fn prepare( + &self, + _type: &str, + _package: &dyn PackageInterface, + _prev_package: Option<&dyn PackageInterface>, + ) -> Result<Option<Box<dyn PromiseInterface>>> { + Ok(Some(shirabe_external_packages::react::promise::resolve( + None, + ))) } - fn cleanup(&self, _type: &str, _package: &dyn PackageInterface, _prev_package: Option<&dyn PackageInterface>) -> Result<Option<Box<dyn PromiseInterface>>> { - Ok(Some(shirabe_external_packages::react::promise::resolve(None))) + fn cleanup( + &self, + _type: &str, + _package: &dyn PackageInterface, + _prev_package: Option<&dyn PackageInterface>, + ) -> Result<Option<Box<dyn PromiseInterface>>> { + Ok(Some(shirabe_external_packages::react::promise::resolve( + None, + ))) } - fn install(&self, repo: &mut dyn InstalledRepositoryInterface, package: &dyn PackageInterface) -> Result<Option<Box<dyn PromiseInterface>>> { - self.io.write_error(&format!(" - {}", InstallOperation::format(package, false)), true, IOInterface::NORMAL); + fn install( + &self, + repo: &mut dyn InstalledRepositoryInterface, + package: &dyn PackageInterface, + ) -> Result<Option<Box<dyn PromiseInterface>>> { + self.io.write_error( + &format!(" - {}", InstallOperation::format(package, false)), + true, + IOInterface::NORMAL, + ); repo.add_package(package.clone_box()); - Ok(Some(shirabe_external_packages::react::promise::resolve(None))) + Ok(Some(shirabe_external_packages::react::promise::resolve( + None, + ))) } - fn update(&self, repo: &mut dyn InstalledRepositoryInterface, initial: &dyn PackageInterface, target: &dyn PackageInterface) -> Result<Option<Box<dyn PromiseInterface>>> { + fn update( + &self, + repo: &mut dyn InstalledRepositoryInterface, + initial: &dyn PackageInterface, + target: &dyn PackageInterface, + ) -> Result<Option<Box<dyn PromiseInterface>>> { if !repo.has_package(initial) { return Err(InvalidArgumentException { message: format!("Package is not installed: {}", initial), code: 0, - }.into()); + } + .into()); } - self.io.write_error(&format!(" - {}", UpdateOperation::format(initial, target, false)), true, IOInterface::NORMAL); + self.io.write_error( + &format!(" - {}", UpdateOperation::format(initial, target, false)), + true, + IOInterface::NORMAL, + ); repo.remove_package(initial); repo.add_package(target.clone_box()); - Ok(Some(shirabe_external_packages::react::promise::resolve(None))) + Ok(Some(shirabe_external_packages::react::promise::resolve( + None, + ))) } - fn uninstall(&self, repo: &mut dyn InstalledRepositoryInterface, package: &dyn PackageInterface) -> Result<Option<Box<dyn PromiseInterface>>> { + fn uninstall( + &self, + repo: &mut dyn InstalledRepositoryInterface, + package: &dyn PackageInterface, + ) -> Result<Option<Box<dyn PromiseInterface>>> { if !repo.has_package(package) { return Err(InvalidArgumentException { message: format!("Package is not installed: {}", package), code: 0, - }.into()); + } + .into()); } - self.io.write_error(&format!(" - {}", UninstallOperation::format(package, false)), true, IOInterface::NORMAL); + self.io.write_error( + &format!(" - {}", UninstallOperation::format(package, false)), + true, + IOInterface::NORMAL, + ); repo.remove_package(package); - Ok(Some(shirabe_external_packages::react::promise::resolve(None))) + Ok(Some(shirabe_external_packages::react::promise::resolve( + None, + ))) } fn get_install_path(&self, _package: &dyn PackageInterface) -> Option<String> { diff --git a/crates/shirabe/src/installer/noop_installer.rs b/crates/shirabe/src/installer/noop_installer.rs index fd30f4a..09e6afd 100644 --- a/crates/shirabe/src/installer/noop_installer.rs +++ b/crates/shirabe/src/installer/noop_installer.rs @@ -1,10 +1,10 @@ //! ref: composer/src/Composer/Installer/NoopInstaller.php -use shirabe_php_shim::InvalidArgumentException; -use shirabe_external_packages::react::promise::promise_interface::PromiseInterface; use crate::installer::installer_interface::InstallerInterface; use crate::package::package_interface::PackageInterface; use crate::repository::installed_repository_interface::InstalledRepositoryInterface; +use shirabe_external_packages::react::promise::promise_interface::PromiseInterface; +use shirabe_php_shim::InvalidArgumentException; #[derive(Debug)] pub struct NoopInstaller; @@ -14,36 +14,72 @@ impl InstallerInterface for NoopInstaller { true } - fn is_installed(&self, repo: &dyn InstalledRepositoryInterface, package: &dyn PackageInterface) -> bool { + fn is_installed( + &self, + repo: &dyn InstalledRepositoryInterface, + package: &dyn PackageInterface, + ) -> bool { repo.has_package(package) } - fn download(&self, _package: &dyn PackageInterface, _prev_package: Option<&dyn PackageInterface>) -> anyhow::Result<Option<Box<dyn PromiseInterface>>> { - Ok(Some(shirabe_external_packages::react::promise::resolve(None))) + fn download( + &self, + _package: &dyn PackageInterface, + _prev_package: Option<&dyn PackageInterface>, + ) -> anyhow::Result<Option<Box<dyn PromiseInterface>>> { + Ok(Some(shirabe_external_packages::react::promise::resolve( + None, + ))) } - fn prepare(&self, _type: &str, _package: &dyn PackageInterface, _prev_package: Option<&dyn PackageInterface>) -> anyhow::Result<Option<Box<dyn PromiseInterface>>> { - Ok(Some(shirabe_external_packages::react::promise::resolve(None))) + fn prepare( + &self, + _type: &str, + _package: &dyn PackageInterface, + _prev_package: Option<&dyn PackageInterface>, + ) -> anyhow::Result<Option<Box<dyn PromiseInterface>>> { + Ok(Some(shirabe_external_packages::react::promise::resolve( + None, + ))) } - fn cleanup(&self, _type: &str, _package: &dyn PackageInterface, _prev_package: Option<&dyn PackageInterface>) -> anyhow::Result<Option<Box<dyn PromiseInterface>>> { - Ok(Some(shirabe_external_packages::react::promise::resolve(None))) + fn cleanup( + &self, + _type: &str, + _package: &dyn PackageInterface, + _prev_package: Option<&dyn PackageInterface>, + ) -> anyhow::Result<Option<Box<dyn PromiseInterface>>> { + Ok(Some(shirabe_external_packages::react::promise::resolve( + None, + ))) } - fn install(&self, repo: &mut dyn InstalledRepositoryInterface, package: &dyn PackageInterface) -> anyhow::Result<Option<Box<dyn PromiseInterface>>> { + fn install( + &self, + repo: &mut dyn InstalledRepositoryInterface, + package: &dyn PackageInterface, + ) -> anyhow::Result<Option<Box<dyn PromiseInterface>>> { if !repo.has_package(package) { repo.add_package(package.clone_box()); } - Ok(Some(shirabe_external_packages::react::promise::resolve(None))) + Ok(Some(shirabe_external_packages::react::promise::resolve( + None, + ))) } - fn update(&self, repo: &mut dyn InstalledRepositoryInterface, initial: &dyn PackageInterface, target: &dyn PackageInterface) -> anyhow::Result<Option<Box<dyn PromiseInterface>>> { + fn update( + &self, + repo: &mut dyn InstalledRepositoryInterface, + initial: &dyn PackageInterface, + target: &dyn PackageInterface, + ) -> anyhow::Result<Option<Box<dyn PromiseInterface>>> { if !repo.has_package(initial) { return Err(InvalidArgumentException { message: format!("Package is not installed: {}", initial), code: 0, - }.into()); + } + .into()); } repo.remove_package(initial); @@ -51,19 +87,28 @@ impl InstallerInterface for NoopInstaller { repo.add_package(target.clone_box()); } - Ok(Some(shirabe_external_packages::react::promise::resolve(None))) + Ok(Some(shirabe_external_packages::react::promise::resolve( + None, + ))) } - fn uninstall(&self, repo: &mut dyn InstalledRepositoryInterface, package: &dyn PackageInterface) -> anyhow::Result<Option<Box<dyn PromiseInterface>>> { + fn uninstall( + &self, + repo: &mut dyn InstalledRepositoryInterface, + package: &dyn PackageInterface, + ) -> anyhow::Result<Option<Box<dyn PromiseInterface>>> { if !repo.has_package(package) { return Err(InvalidArgumentException { message: format!("Package is not installed: {}", package), code: 0, - }.into()); + } + .into()); } repo.remove_package(package); - Ok(Some(shirabe_external_packages::react::promise::resolve(None))) + Ok(Some(shirabe_external_packages::react::promise::resolve( + None, + ))) } fn get_install_path(&self, package: &dyn PackageInterface) -> Option<String> { diff --git a/crates/shirabe/src/installer/package_event.rs b/crates/shirabe/src/installer/package_event.rs index 537e97e..2bf1c6b 100644 --- a/crates/shirabe/src/installer/package_event.rs +++ b/crates/shirabe/src/installer/package_event.rs @@ -1,11 +1,11 @@ //! ref: composer/src/Composer/Installer/PackageEvent.php -use indexmap::IndexMap; use crate::composer::Composer; use crate::dependency_resolver::operation::operation_interface::OperationInterface; use crate::event_dispatcher::event::Event; use crate::io::io_interface::IOInterface; use crate::repository::repository_interface::RepositoryInterface; +use indexmap::IndexMap; #[derive(Debug)] pub struct PackageEvent { diff --git a/crates/shirabe/src/installer/plugin_installer.rs b/crates/shirabe/src/installer/plugin_installer.rs index 55a936a..1fd2334 100644 --- a/crates/shirabe/src/installer/plugin_installer.rs +++ b/crates/shirabe/src/installer/plugin_installer.rs @@ -1,8 +1,5 @@ //! ref: composer/src/Composer/Installer/PluginInstaller.php -use anyhow::Result; -use shirabe_php_shim::{empty, LogicException, PhpMixed, UnexpectedValueException}; -use shirabe_external_packages::react::promise::promise_interface::PromiseInterface; use crate::installer::binary_installer::BinaryInstaller; use crate::installer::installer_interface::InstallerInterface; use crate::installer::library_installer::LibraryInstaller; @@ -13,6 +10,9 @@ use crate::plugin::plugin_manager::PluginManager; use crate::repository::installed_repository_interface::InstalledRepositoryInterface; use crate::util::filesystem::Filesystem; use crate::util::platform::Platform; +use anyhow::Result; +use shirabe_external_packages::react::promise::promise_interface::PromiseInterface; +use shirabe_php_shim::{LogicException, PhpMixed, UnexpectedValueException, empty}; #[derive(Debug)] pub struct PluginInstaller { @@ -27,7 +27,13 @@ impl PluginInstaller { binary_installer: Option<BinaryInstaller>, ) -> Self { Self { - inner: LibraryInstaller::new(io, composer, Some("composer-plugin".to_string()), fs, binary_installer), + inner: LibraryInstaller::new( + io, + composer, + Some("composer-plugin".to_string()), + fs, + binary_installer, + ), } } @@ -36,8 +42,16 @@ impl PluginInstaller { self.get_plugin_manager().disable_plugins(); } - fn rollback_install(&self, e: anyhow::Error, repo: &mut dyn InstalledRepositoryInterface, package: &dyn PackageInterface) -> Result<()> { - self.inner.io.write_error(&format!("Plugin initialization failed ({}), uninstalling plugin", e)); + fn rollback_install( + &self, + e: anyhow::Error, + repo: &mut dyn InstalledRepositoryInterface, + package: &dyn PackageInterface, + ) -> Result<()> { + self.inner.io.write_error(&format!( + "Plugin initialization failed ({}), uninstalling plugin", + e + )); self.inner.uninstall(repo, package)?; Err(e) } @@ -48,7 +62,9 @@ impl PluginInstaller { self.inner.composer.is_full_composer(), "{}", LogicException { - message: "PluginInstaller should be initialized with a fully loaded Composer instance.".to_string(), + message: + "PluginInstaller should be initialized with a fully loaded Composer instance." + .to_string(), code: 0, } ); @@ -62,24 +78,41 @@ impl InstallerInterface for PluginInstaller { package_type == "composer-plugin" || package_type == "composer-installer" } - fn is_installed(&self, repo: &dyn InstalledRepositoryInterface, package: &dyn PackageInterface) -> bool { + fn is_installed( + &self, + repo: &dyn InstalledRepositoryInterface, + package: &dyn PackageInterface, + ) -> bool { self.inner.is_installed(repo, package) } - fn prepare(&self, r#type: &str, package: &dyn PackageInterface, prev_package: Option<&dyn PackageInterface>) -> Result<Option<Box<dyn PromiseInterface>>> { - if (r#type == "install" || r#type == "update") && !self.get_plugin_manager().are_plugins_disabled("local") { - let plugin_optional = package.get_extra() + fn prepare( + &self, + r#type: &str, + package: &dyn PackageInterface, + prev_package: Option<&dyn PackageInterface>, + ) -> Result<Option<Box<dyn PromiseInterface>>> { + if (r#type == "install" || r#type == "update") + && !self.get_plugin_manager().are_plugins_disabled("local") + { + let plugin_optional = package + .get_extra() .get("plugin-optional") .map(|v| matches!(v, PhpMixed::Bool(true))) .unwrap_or(false); // TODO(plugin): check if plugin is allowed - self.get_plugin_manager().is_plugin_allowed(package.get_name(), false, plugin_optional); + self.get_plugin_manager() + .is_plugin_allowed(package.get_name(), false, plugin_optional); } self.inner.prepare(r#type, package, prev_package) } - fn download(&self, package: &dyn PackageInterface, prev_package: Option<&dyn PackageInterface>) -> Result<Option<Box<dyn PromiseInterface>>> { + fn download( + &self, + package: &dyn PackageInterface, + prev_package: Option<&dyn PackageInterface>, + ) -> Result<Option<Box<dyn PromiseInterface>>> { let extra = package.get_extra(); let class = extra.get("class").cloned().unwrap_or(PhpMixed::Null); if empty(&class) { @@ -95,7 +128,11 @@ impl InstallerInterface for PluginInstaller { self.inner.download(package, prev_package) } - fn install(&self, repo: &mut dyn InstalledRepositoryInterface, package: &dyn PackageInterface) -> Result<Option<Box<dyn PromiseInterface>>> { + fn install( + &self, + repo: &mut dyn InstalledRepositoryInterface, + package: &dyn PackageInterface, + ) -> Result<Option<Box<dyn PromiseInterface>>> { let promise = self.inner.install(repo, package)?; let promise = match promise { Some(p) => p, @@ -111,7 +148,12 @@ impl InstallerInterface for PluginInstaller { })))) } - fn update(&self, repo: &mut dyn InstalledRepositoryInterface, initial: &dyn PackageInterface, target: &dyn PackageInterface) -> Result<Option<Box<dyn PromiseInterface>>> { + fn update( + &self, + repo: &mut dyn InstalledRepositoryInterface, + initial: &dyn PackageInterface, + target: &dyn PackageInterface, + ) -> Result<Option<Box<dyn PromiseInterface>>> { let promise = self.inner.update(repo, initial, target)?; let promise = match promise { Some(p) => p, @@ -128,14 +170,23 @@ impl InstallerInterface for PluginInstaller { })))) } - fn uninstall(&self, repo: &mut dyn InstalledRepositoryInterface, package: &dyn PackageInterface) -> Result<Option<Box<dyn PromiseInterface>>> { + fn uninstall( + &self, + repo: &mut dyn InstalledRepositoryInterface, + package: &dyn PackageInterface, + ) -> Result<Option<Box<dyn PromiseInterface>>> { // TODO(plugin): uninstall package from plugin manager self.get_plugin_manager().uninstall_package(package); self.inner.uninstall(repo, package) } - fn cleanup(&self, r#type: &str, package: &dyn PackageInterface, prev_package: Option<&dyn PackageInterface>) -> Result<Option<Box<dyn PromiseInterface>>> { + fn cleanup( + &self, + r#type: &str, + package: &dyn PackageInterface, + prev_package: Option<&dyn PackageInterface>, + ) -> Result<Option<Box<dyn PromiseInterface>>> { self.inner.cleanup(r#type, package, prev_package) } diff --git a/crates/shirabe/src/installer/project_installer.rs b/crates/shirabe/src/installer/project_installer.rs index 6472472..1a097b0 100644 --- a/crates/shirabe/src/installer/project_installer.rs +++ b/crates/shirabe/src/installer/project_installer.rs @@ -1,12 +1,12 @@ //! ref: composer/src/Composer/Installer/ProjectInstaller.php -use shirabe_external_packages::react::promise::promise_interface::PromiseInterface; -use shirabe_php_shim::InvalidArgumentException; use crate::downloader::download_manager::DownloadManager; use crate::installer::installer_interface::InstallerInterface; use crate::package::package_interface::PackageInterface; use crate::repository::installed_repository_interface::InstalledRepositoryInterface; use crate::util::filesystem::Filesystem; +use shirabe_external_packages::react::promise::promise_interface::PromiseInterface; +use shirabe_php_shim::InvalidArgumentException; #[derive(Debug)] pub struct ProjectInstaller { @@ -31,49 +31,88 @@ impl InstallerInterface for ProjectInstaller { true } - fn is_installed(&self, _repo: &dyn InstalledRepositoryInterface, _package: &dyn PackageInterface) -> bool { + fn is_installed( + &self, + _repo: &dyn InstalledRepositoryInterface, + _package: &dyn PackageInterface, + ) -> bool { false } - fn download(&self, package: &dyn PackageInterface, prev_package: Option<&dyn PackageInterface>) -> anyhow::Result<Option<Box<dyn PromiseInterface>>> { + fn download( + &self, + package: &dyn PackageInterface, + prev_package: Option<&dyn PackageInterface>, + ) -> anyhow::Result<Option<Box<dyn PromiseInterface>>> { let install_path = &self.install_path; - if std::path::Path::new(install_path).exists() && !self.filesystem.is_dir_empty(install_path) { + if std::path::Path::new(install_path).exists() + && !self.filesystem.is_dir_empty(install_path) + { return Err(InvalidArgumentException { message: format!("Project directory {} is not empty.", install_path), code: 0, - }.into()); + } + .into()); } if !std::path::Path::new(install_path).is_dir() { std::fs::create_dir_all(install_path)?; } - self.download_manager.download(package, install_path, prev_package) + self.download_manager + .download(package, install_path, prev_package) } - fn prepare(&self, r#type: &str, package: &dyn PackageInterface, prev_package: Option<&dyn PackageInterface>) -> anyhow::Result<Option<Box<dyn PromiseInterface>>> { - self.download_manager.prepare(r#type, package, &self.install_path, prev_package) + fn prepare( + &self, + r#type: &str, + package: &dyn PackageInterface, + prev_package: Option<&dyn PackageInterface>, + ) -> anyhow::Result<Option<Box<dyn PromiseInterface>>> { + self.download_manager + .prepare(r#type, package, &self.install_path, prev_package) } - fn cleanup(&self, r#type: &str, package: &dyn PackageInterface, prev_package: Option<&dyn PackageInterface>) -> anyhow::Result<Option<Box<dyn PromiseInterface>>> { - self.download_manager.cleanup(r#type, package, &self.install_path, prev_package) + fn cleanup( + &self, + r#type: &str, + package: &dyn PackageInterface, + prev_package: Option<&dyn PackageInterface>, + ) -> anyhow::Result<Option<Box<dyn PromiseInterface>>> { + self.download_manager + .cleanup(r#type, package, &self.install_path, prev_package) } - fn install(&self, _repo: &mut dyn InstalledRepositoryInterface, package: &dyn PackageInterface) -> anyhow::Result<Option<Box<dyn PromiseInterface>>> { + fn install( + &self, + _repo: &mut dyn InstalledRepositoryInterface, + package: &dyn PackageInterface, + ) -> anyhow::Result<Option<Box<dyn PromiseInterface>>> { self.download_manager.install(package, &self.install_path) } - fn update(&self, _repo: &mut dyn InstalledRepositoryInterface, _initial: &dyn PackageInterface, _target: &dyn PackageInterface) -> anyhow::Result<Option<Box<dyn PromiseInterface>>> { + fn update( + &self, + _repo: &mut dyn InstalledRepositoryInterface, + _initial: &dyn PackageInterface, + _target: &dyn PackageInterface, + ) -> anyhow::Result<Option<Box<dyn PromiseInterface>>> { Err(InvalidArgumentException { message: "not supported".to_string(), code: 0, - }.into()) + } + .into()) } - fn uninstall(&self, _repo: &mut dyn InstalledRepositoryInterface, _package: &dyn PackageInterface) -> anyhow::Result<Option<Box<dyn PromiseInterface>>> { + fn uninstall( + &self, + _repo: &mut dyn InstalledRepositoryInterface, + _package: &dyn PackageInterface, + ) -> anyhow::Result<Option<Box<dyn PromiseInterface>>> { Err(InvalidArgumentException { message: "not supported".to_string(), code: 0, - }.into()) + } + .into()) } fn get_install_path(&self, _package: &dyn PackageInterface) -> Option<String> { diff --git a/crates/shirabe/src/installer/suggested_packages_reporter.rs b/crates/shirabe/src/installer/suggested_packages_reporter.rs index 77b4c34..cfee20b 100644 --- a/crates/shirabe/src/installer/suggested_packages_reporter.rs +++ b/crates/shirabe/src/installer/suggested_packages_reporter.rs @@ -1,11 +1,11 @@ //! ref: composer/src/Composer/Installer/SuggestedPackagesReporter.php -use indexmap::IndexMap; -use shirabe_external_packages::composer::pcre::preg::Preg; -use shirabe_external_packages::symfony::component::console::formatter::output_formatter::OutputFormatter; use crate::io::io_interface::IOInterface; use crate::package::package_interface::PackageInterface; use crate::repository::installed_repository::InstalledRepository; +use indexmap::IndexMap; +use shirabe_external_packages::composer::pcre::preg::Preg; +use shirabe_external_packages::symfony::component::console::formatter::output_formatter::OutputFormatter; #[derive(Debug)] pub struct SuggestedPackagesReporter { @@ -48,7 +48,12 @@ impl SuggestedPackagesReporter { self } - pub fn output(&self, mode: i64, installed_repo: Option<&InstalledRepository>, only_dependents_of: Option<&dyn PackageInterface>) { + pub fn output( + &self, + mode: i64, + installed_repo: Option<&InstalledRepository>, + only_dependents_of: Option<&dyn PackageInterface>, + ) { let suggested_packages = self.get_filtered_suggestions(installed_repo, only_dependents_of); let mut suggesters: IndexMap<String, IndexMap<String, String>> = IndexMap::new(); @@ -78,7 +83,8 @@ impl SuggestedPackagesReporter { // Grouped by package if mode & Self::MODE_BY_PACKAGE != 0 { for (suggester, suggestions) in &suggesters { - self.io.write(&format!("<comment>{}</comment> suggests:", suggester)); + self.io + .write(&format!("<comment>{}</comment> suggests:", suggester)); for (suggestion, reason) in suggestions { self.io.write(&format!( @@ -102,7 +108,10 @@ impl SuggestedPackagesReporter { self.io.write(&"-".repeat(78)); } for (suggestion, suggesters) in &suggested { - self.io.write(&format!("<comment>{}</comment> is suggested by:", suggestion)); + self.io.write(&format!( + "<comment>{}</comment> is suggested by:", + suggestion + )); for (suggester, reason) in suggesters { self.io.write(&format!( @@ -128,7 +137,11 @@ impl SuggestedPackagesReporter { } } - pub fn output_minimalistic(&self, installed_repo: Option<&InstalledRepository>, only_dependents_of: Option<&dyn PackageInterface>) { + pub fn output_minimalistic( + &self, + installed_repo: Option<&InstalledRepository>, + only_dependents_of: Option<&dyn PackageInterface>, + ) { let suggested_packages = self.get_filtered_suggestions(installed_repo, only_dependents_of); if !suggested_packages.is_empty() { self.io.write_error(&format!( @@ -138,7 +151,11 @@ impl SuggestedPackagesReporter { } } - fn get_filtered_suggestions(&self, installed_repo: Option<&InstalledRepository>, only_dependents_of: Option<&dyn PackageInterface>) -> Vec<IndexMap<String, String>> { + fn get_filtered_suggestions( + &self, + installed_repo: Option<&InstalledRepository>, + only_dependents_of: Option<&dyn PackageInterface>, + ) -> 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() { @@ -149,7 +166,9 @@ impl SuggestedPackagesReporter { let mut source_filter: Vec<String> = Vec::new(); if let Some(only_dependents_of) = only_dependents_of { - source_filter = only_dependents_of.get_requires().values() + source_filter = only_dependents_of + .get_requires() + .values() .chain(only_dependents_of.get_dev_requires().values()) .map(|link| link.get_target().to_string()) .collect(); @@ -171,16 +190,10 @@ impl SuggestedPackagesReporter { } fn escape_output(&self, string: &str) -> String { - OutputFormatter::escape( - &self.remove_control_characters(string) - ) + OutputFormatter::escape(&self.remove_control_characters(string)) } fn remove_control_characters(&self, string: &str) -> String { - Preg::replace( - "/[[:cntrl:]]/", - "", - &string.replace('\n', " "), - ) + Preg::replace("/[[:cntrl:]]/", "", &string.replace('\n', " ")) } } |
