diff options
Diffstat (limited to 'crates/shirabe/src/downloader')
| -rw-r--r-- | crates/shirabe/src/downloader/archive_downloader.rs | 4 | ||||
| -rw-r--r-- | crates/shirabe/src/downloader/download_manager.rs | 2 | ||||
| -rw-r--r-- | crates/shirabe/src/downloader/file_downloader.rs | 37 | ||||
| -rw-r--r-- | crates/shirabe/src/downloader/filesystem_exception.rs | 8 | ||||
| -rw-r--r-- | crates/shirabe/src/downloader/git_downloader.rs | 88 | ||||
| -rw-r--r-- | crates/shirabe/src/downloader/gzip_downloader.rs | 58 | ||||
| -rw-r--r-- | crates/shirabe/src/downloader/max_file_size_exceeded_exception.rs | 15 | ||||
| -rw-r--r-- | crates/shirabe/src/downloader/path_downloader.rs | 10 | ||||
| -rw-r--r-- | crates/shirabe/src/downloader/phar_downloader.rs | 94 | ||||
| -rw-r--r-- | crates/shirabe/src/downloader/rar_downloader.rs | 111 | ||||
| -rw-r--r-- | crates/shirabe/src/downloader/tar_downloader.rs | 94 | ||||
| -rw-r--r-- | crates/shirabe/src/downloader/transport_exception.rs | 8 | ||||
| -rw-r--r-- | crates/shirabe/src/downloader/vcs_downloader.rs | 2 | ||||
| -rw-r--r-- | crates/shirabe/src/downloader/xz_downloader.rs | 110 | ||||
| -rw-r--r-- | crates/shirabe/src/downloader/zip_downloader.rs | 18 |
15 files changed, 604 insertions, 55 deletions
diff --git a/crates/shirabe/src/downloader/archive_downloader.rs b/crates/shirabe/src/downloader/archive_downloader.rs index 03edffe..02cd8a9 100644 --- a/crates/shirabe/src/downloader/archive_downloader.rs +++ b/crates/shirabe/src/downloader/archive_downloader.rs @@ -99,7 +99,7 @@ pub trait ArchiveDownloader { self.inner_mut().add_cleanup_path(package, &temporary_dir); // avoid cleaning up $path if installing in "." for eg create-project as we can not // delete the directory we are currently in on windows - if !is_dir(path) || realpath(path) != Platform::get_cwd() { + if !is_dir(path) || realpath(path) != Platform::get_cwd(false).unwrap_or_default() { self.inner_mut().add_cleanup_path(package, path); } @@ -116,7 +116,7 @@ pub trait ArchiveDownloader { // clean up filesystem.remove_directory(&temporary_dir); - if is_dir(path) && realpath(path) != Platform::get_cwd() { + if is_dir(path) && realpath(path) != Platform::get_cwd(false).unwrap_or_default() { filesystem.remove_directory(path); } self.inner_mut() diff --git a/crates/shirabe/src/downloader/download_manager.rs b/crates/shirabe/src/downloader/download_manager.rs index c03f704..db3484e 100644 --- a/crates/shirabe/src/downloader/download_manager.rs +++ b/crates/shirabe/src/downloader/download_manager.rs @@ -45,7 +45,7 @@ impl DownloadManager { prefer_source: bool, filesystem: Option<Filesystem>, ) -> Self { - let filesystem = filesystem.unwrap_or_else(Filesystem::new); + let filesystem = filesystem.unwrap_or_else(|| Filesystem::new(None)); Self { io, prefer_source, diff --git a/crates/shirabe/src/downloader/file_downloader.rs b/crates/shirabe/src/downloader/file_downloader.rs index e6b471f..85e43fc 100644 --- a/crates/shirabe/src/downloader/file_downloader.rs +++ b/crates/shirabe/src/downloader/file_downloader.rs @@ -239,7 +239,7 @@ impl DownloaderInterface for FileDownloader { for dir in &dirs_to_clean_up { if is_dir(dir) && self.filesystem.is_dir_empty(dir)? - && realpath(dir).as_deref() != Some(&Platform::get_cwd()) + && realpath(dir).as_deref() != Some(&Platform::get_cwd(false).unwrap_or_default()) { self.filesystem.remove_directory_php(dir)?; } @@ -257,7 +257,7 @@ impl DownloaderInterface for FileDownloader { ) -> Result<Box<dyn PromiseInterface>> { if output { self.io - .write_error(&format!(" - {}", InstallOperation::format(package))); + .write_error(&format!(" - {}", InstallOperation::format(package, false))); } let vendor_dir = self @@ -277,7 +277,7 @@ impl DownloaderInterface for FileDownloader { .normalize_path(&format!("{}{}", path, DIRECTORY_SEPARATOR)); strpos(&normalized_vendor, &normalized_path).is_some() } { - self.filesystem.empty_directory(path)?; + self.filesystem.empty_directory(path, true)?; } self.filesystem.ensure_directory_exists(path)?; self.filesystem.rename( @@ -294,17 +294,16 @@ impl DownloaderInterface for FileDownloader { for bin in package.get_binaries() { let bin_path = format!("{}/{}", path, bin); if file_exists(&bin_path) && !is_executable(&bin_path) { - Silencer::call_named( - "chmod", - &[ - PhpMixed::String(bin_path), - PhpMixed::Int((0o777 & !umask()) as i64), - ], - ); + // TODO(phase-b): Silencer::call_named for native PHP function + let _ = Silencer::call(|| { + let _ = bin_path; + let _ = umask(); + Ok(()) + }); } } - Ok(react_promise_resolve(PhpMixed::Null)) + Ok(react_promise_resolve(Some(PhpMixed::Null))) } /// @inheritDoc @@ -316,7 +315,7 @@ impl DownloaderInterface for FileDownloader { ) -> Result<Box<dyn PromiseInterface>> { self.io.write_error(&format!( " - {}{}", - UpdateOperation::format(initial, target), + UpdateOperation::format(initial, target, false), self.get_install_operation_appendix(target, path) )); @@ -334,8 +333,10 @@ impl DownloaderInterface for FileDownloader { output: bool, ) -> Result<Box<dyn PromiseInterface>> { if output { - self.io - .write_error(&format!(" - {}", UninstallOperation::format(package))); + self.io.write_error(&format!( + " - {}", + UninstallOperation::format(package, false) + )); } let _promise = self.filesystem.remove_directory_async(path)?; @@ -394,12 +395,12 @@ impl ChangeReportInterface for FileDownloader { } let mut comparer = Comparer::new(); - comparer.set_source(&format!("{}_compare", target_dir)); - comparer.set_update(&target_dir); + comparer.set_source(format!("{}_compare", target_dir)); + comparer.set_update(target_dir.clone()); comparer.do_compare(); - output = comparer.get_changed_as_string(true); + output = comparer.get_changed_as_string(true, false); self.filesystem - .remove_directory(&format!("{}_compare", target_dir), false)?; + .remove_directory(&format!("{}_compare", target_dir))?; Ok(()) })(); if let Err(err) = result { diff --git a/crates/shirabe/src/downloader/filesystem_exception.rs b/crates/shirabe/src/downloader/filesystem_exception.rs index f861306..f0aa831 100644 --- a/crates/shirabe/src/downloader/filesystem_exception.rs +++ b/crates/shirabe/src/downloader/filesystem_exception.rs @@ -13,3 +13,11 @@ impl FilesystemException { }) } } + +impl std::fmt::Display for FilesystemException { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + self.0.fmt(f) + } +} + +impl std::error::Error for FilesystemException {} diff --git a/crates/shirabe/src/downloader/git_downloader.rs b/crates/shirabe/src/downloader/git_downloader.rs index 45849cb..fb41b0c 100644 --- a/crates/shirabe/src/downloader/git_downloader.rs +++ b/crates/shirabe/src/downloader/git_downloader.rs @@ -250,9 +250,7 @@ impl GitDownloader { } } - self.inner - .io - .write_error(PhpMixed::String(msg), true, io_interface::NORMAL); + self.inner.io.write_error3(&msg, true, io_interface::NORMAL); self.git_util.run_commands(commands, url, &path, true); @@ -334,9 +332,7 @@ impl GitDownloader { } } - self.inner - .io - .write_error(PhpMixed::String(msg), true, io_interface::NORMAL); + self.inner.io.write_error3(&msg, true, io_interface::NORMAL); let mut output = String::new(); if self.inner.process.execute( @@ -1250,7 +1246,7 @@ impl GitDownloader { self.inner .io - .write_error(PhpMixed::String(output), true, io_interface::NORMAL); + .write_error3(&output, true, io_interface::NORMAL); } pub(crate) fn normalize_path(&self, path: &str) -> String { @@ -1305,3 +1301,81 @@ impl DvcsDownloaderInterface for GitDownloader { GitDownloader::get_unpushed_changes(self, package, &path) } } + +// TODO(phase-b): GitDownloader extends VcsDownloader which implements DownloaderInterface. +// Delegating each trait method to todo!() until the inner VcsDownloaderBase exposes the +// matching impl surface. +impl crate::downloader::downloader_interface::DownloaderInterface for GitDownloader { + fn get_installation_source(&self) -> String { + todo!() + } + + fn download( + &self, + _package: &dyn PackageInterface, + _path: &str, + _prev_package: Option<&dyn PackageInterface>, + _output: bool, + ) -> anyhow::Result< + Box<dyn shirabe_external_packages::react::promise::promise_interface::PromiseInterface>, + > { + todo!() + } + + fn prepare( + &self, + _type: &str, + _package: &dyn PackageInterface, + _path: &str, + _prev_package: Option<&dyn PackageInterface>, + ) -> anyhow::Result< + Box<dyn shirabe_external_packages::react::promise::promise_interface::PromiseInterface>, + > { + todo!() + } + + fn install( + &self, + _package: &dyn PackageInterface, + _path: &str, + _output: bool, + ) -> anyhow::Result< + Box<dyn shirabe_external_packages::react::promise::promise_interface::PromiseInterface>, + > { + todo!() + } + + fn update( + &self, + _initial: &dyn PackageInterface, + _target: &dyn PackageInterface, + _path: &str, + ) -> anyhow::Result< + Box<dyn shirabe_external_packages::react::promise::promise_interface::PromiseInterface>, + > { + todo!() + } + + fn remove( + &self, + _package: &dyn PackageInterface, + _path: &str, + _output: bool, + ) -> anyhow::Result< + Box<dyn shirabe_external_packages::react::promise::promise_interface::PromiseInterface>, + > { + todo!() + } + + fn cleanup( + &self, + _type: &str, + _package: &dyn PackageInterface, + _path: &str, + _prev_package: Option<&dyn PackageInterface>, + ) -> anyhow::Result< + Box<dyn shirabe_external_packages::react::promise::promise_interface::PromiseInterface>, + > { + todo!() + } +} diff --git a/crates/shirabe/src/downloader/gzip_downloader.rs b/crates/shirabe/src/downloader/gzip_downloader.rs index ca50827..2a485de 100644 --- a/crates/shirabe/src/downloader/gzip_downloader.rs +++ b/crates/shirabe/src/downloader/gzip_downloader.rs @@ -1,25 +1,57 @@ //! ref: composer/src/Composer/Downloader/GzipDownloader.php +use crate::cache::Cache; +use crate::config::Config; use crate::downloader::archive_downloader::ArchiveDownloader; use crate::downloader::file_downloader::FileDownloader; +use crate::event_dispatcher::event_dispatcher::EventDispatcher; +use crate::io::io_interface::IOInterface; use crate::package::package_interface::PackageInterface; +use crate::util::filesystem::Filesystem; +use crate::util::http_downloader::HttpDownloader; use crate::util::platform::Platform; +use crate::util::process_executor::ProcessExecutor; use anyhow::Result; use indexmap::IndexMap; use shirabe_external_packages::react::promise::promise_interface::PromiseInterface; use shirabe_php_shim::{ - DIRECTORY_SEPARATOR, PATHINFO_FILENAME, PHP_URL_PATH, RuntimeException, extension_loaded, - fclose, fopen, fwrite, gzclose, gzopen, gzread, implode, parse_url, pathinfo, strtr, + DIRECTORY_SEPARATOR, PATHINFO_FILENAME, PHP_URL_PATH, PhpMixed, RuntimeException, + extension_loaded, fclose, fopen, fwrite, gzclose, gzopen, gzread, implode, parse_url, pathinfo, + strtr, }; +#[derive(Debug)] pub struct GzipDownloader { inner: FileDownloader, cleanup_executed: IndexMap<String, bool>, } impl GzipDownloader { + pub fn new( + io: Box<dyn IOInterface>, + config: Config, + http_downloader: HttpDownloader, + event_dispatcher: Option<EventDispatcher>, + cache: Option<Cache>, + filesystem: Filesystem, + process: ProcessExecutor, + ) -> Self { + Self { + inner: FileDownloader::new( + io, + config, + http_downloader, + event_dispatcher, + cache, + Some(filesystem), + Some(process), + ), + cleanup_executed: IndexMap::new(), + } + } + pub(crate) fn extract( - &self, + &mut self, package: &dyn PackageInterface, file: &str, path: &str, @@ -31,7 +63,12 @@ impl GzipDownloader { ), PATHINFO_FILENAME, ); - let target_filepath = format!("{}{}{}", path, DIRECTORY_SEPARATOR, filename); + let target_filepath = format!( + "{}{}{}", + path, + DIRECTORY_SEPARATOR, + filename.as_string().unwrap_or_default() + ); if !Platform::is_windows() { let command = vec![ @@ -42,7 +79,18 @@ impl GzipDownloader { target_filepath.clone(), ]; - if self.inner.process.execute(&command, &mut String::new()) == 0 { + let mut process_output = PhpMixed::Null; + if self.inner.process.execute( + PhpMixed::List( + command + .iter() + .map(|s| Box::new(PhpMixed::String(s.clone()))) + .collect(), + ), + Some(&mut process_output), + None, + )? == 0 + { return Ok(shirabe_external_packages::react::promise::resolve(None)); } diff --git a/crates/shirabe/src/downloader/max_file_size_exceeded_exception.rs b/crates/shirabe/src/downloader/max_file_size_exceeded_exception.rs index 1613432..4e18761 100644 --- a/crates/shirabe/src/downloader/max_file_size_exceeded_exception.rs +++ b/crates/shirabe/src/downloader/max_file_size_exceeded_exception.rs @@ -2,4 +2,19 @@ use crate::downloader::transport_exception::TransportException; +#[derive(Debug)] pub struct MaxFileSizeExceededException(pub TransportException); + +impl MaxFileSizeExceededException { + pub fn new(message: String) -> Self { + Self(TransportException::new(message, 0)) + } +} + +impl std::fmt::Display for MaxFileSizeExceededException { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + self.0.fmt(f) + } +} + +impl std::error::Error for MaxFileSizeExceededException {} diff --git a/crates/shirabe/src/downloader/path_downloader.rs b/crates/shirabe/src/downloader/path_downloader.rs index c50d390..a525df0 100644 --- a/crates/shirabe/src/downloader/path_downloader.rs +++ b/crates/shirabe/src/downloader/path_downloader.rs @@ -140,7 +140,7 @@ impl PathDownloader { let (mut current_strategy, allowed_strategies) = self.compute_allowed_strategies(&transport_options)?; - let symfony_filesystem = SymfonyFilesystem::new(); + let symfony_filesystem = SymfonyFilesystem::new(None); self.inner.filesystem.remove_directory(&path); if output { @@ -254,14 +254,12 @@ impl PathDownloader { io_interface::NORMAL, ); } - let iterator = ArchivableFilesFinder::new(&real_url, vec![]); + let iterator = ArchivableFilesFinder::new(&real_url, vec![], false)?; symfony_filesystem.mirror(&real_url, &path, Some(&iterator)); } if output { - self.inner - .io - .write_error(PhpMixed::String("".to_string()), true, io_interface::NORMAL); + self.inner.io.write_error3("", true, io_interface::NORMAL); } Ok(shirabe_external_packages::react::promise::resolve(None)) @@ -328,7 +326,7 @@ impl PathDownloader { // can happen when using custom installers, see https://github.com/composer/composer/pull/9116 // not using realpath here as we do not want to resolve the symlink to the original dist url // it points to - let fs = Filesystem::new(); + let fs = Filesystem::new(None); let abs_path = if fs.is_absolute_path(&path) { path.clone() } else { diff --git a/crates/shirabe/src/downloader/phar_downloader.rs b/crates/shirabe/src/downloader/phar_downloader.rs index 5316fc1..649841d 100644 --- a/crates/shirabe/src/downloader/phar_downloader.rs +++ b/crates/shirabe/src/downloader/phar_downloader.rs @@ -1,8 +1,16 @@ //! ref: composer/src/Composer/Downloader/PharDownloader.php +use crate::cache::Cache; +use crate::config::Config; use crate::downloader::archive_downloader::ArchiveDownloader; +use crate::downloader::downloader_interface::DownloaderInterface; use crate::downloader::file_downloader::FileDownloader; +use crate::event_dispatcher::event_dispatcher::EventDispatcher; +use crate::io::io_interface::IOInterface; use crate::package::package_interface::PackageInterface; +use crate::util::filesystem::Filesystem; +use crate::util::http_downloader::HttpDownloader; +use crate::util::process_executor::ProcessExecutor; use anyhow::Result; use indexmap::IndexMap; use shirabe_external_packages::react::promise::promise_interface::PromiseInterface; @@ -15,6 +23,29 @@ pub struct PharDownloader { } impl PharDownloader { + pub fn new( + io: Box<dyn IOInterface>, + config: Config, + http_downloader: HttpDownloader, + event_dispatcher: Option<EventDispatcher>, + cache: Option<Cache>, + filesystem: Filesystem, + process: ProcessExecutor, + ) -> Self { + Self { + inner: FileDownloader::new( + io, + config, + http_downloader, + event_dispatcher, + cache, + Some(filesystem), + Some(process), + ), + cleanup_executed: IndexMap::new(), + } + } + pub(crate) fn extract( &self, package: &dyn PackageInterface, @@ -32,3 +63,66 @@ impl PharDownloader { Ok(shirabe_external_packages::react::promise::resolve(None)) } } + +impl DownloaderInterface for PharDownloader { + fn get_installation_source(&self) -> String { + self.inner.get_installation_source() + } + + fn download( + &self, + package: &dyn PackageInterface, + path: &str, + prev_package: Option<&dyn PackageInterface>, + output: bool, + ) -> Result<Box<dyn PromiseInterface>> { + self.inner.download(package, path, prev_package, output) + } + + fn prepare( + &self, + r#type: &str, + package: &dyn PackageInterface, + path: &str, + prev_package: Option<&dyn PackageInterface>, + ) -> Result<Box<dyn PromiseInterface>> { + self.inner.prepare(r#type, package, path, prev_package) + } + + fn install( + &self, + package: &dyn PackageInterface, + path: &str, + output: bool, + ) -> Result<Box<dyn PromiseInterface>> { + self.inner.install(package, path, output) + } + + fn update( + &self, + initial: &dyn PackageInterface, + target: &dyn PackageInterface, + path: &str, + ) -> Result<Box<dyn PromiseInterface>> { + self.inner.update(initial, target, path) + } + + fn remove( + &self, + package: &dyn PackageInterface, + path: &str, + output: bool, + ) -> Result<Box<dyn PromiseInterface>> { + self.inner.remove(package, path, output) + } + + fn cleanup( + &self, + r#type: &str, + package: &dyn PackageInterface, + path: &str, + prev_package: Option<&dyn PackageInterface>, + ) -> Result<Box<dyn PromiseInterface>> { + self.inner.cleanup(r#type, package, path, prev_package) + } +} diff --git a/crates/shirabe/src/downloader/rar_downloader.rs b/crates/shirabe/src/downloader/rar_downloader.rs index 308b6fa..51feadb 100644 --- a/crates/shirabe/src/downloader/rar_downloader.rs +++ b/crates/shirabe/src/downloader/rar_downloader.rs @@ -1,25 +1,56 @@ //! ref: composer/src/Composer/Downloader/RarDownloader.php +use crate::cache::Cache; +use crate::config::Config; use crate::downloader::archive_downloader::ArchiveDownloader; use crate::downloader::file_downloader::FileDownloader; +use crate::event_dispatcher::event_dispatcher::EventDispatcher; +use crate::io::io_interface::IOInterface; use crate::package::package_interface::PackageInterface; +use crate::util::filesystem::Filesystem; +use crate::util::http_downloader::HttpDownloader; use crate::util::ini_helper::IniHelper; use crate::util::platform::Platform; +use crate::util::process_executor::ProcessExecutor; use anyhow::Result; use indexmap::IndexMap; use shirabe_external_packages::react::promise::promise_interface::PromiseInterface; use shirabe_php_shim::{ - RarArchive, RuntimeException, UnexpectedValueException, class_exists, implode, + PhpMixed, RarArchive, RuntimeException, UnexpectedValueException, class_exists, implode, }; +#[derive(Debug)] pub struct RarDownloader { inner: FileDownloader, cleanup_executed: IndexMap<String, bool>, } impl RarDownloader { + pub fn new( + io: Box<dyn IOInterface>, + config: Config, + http_downloader: HttpDownloader, + event_dispatcher: Option<EventDispatcher>, + cache: Option<Cache>, + filesystem: Filesystem, + process: ProcessExecutor, + ) -> Self { + Self { + inner: FileDownloader::new( + io, + config, + http_downloader, + event_dispatcher, + cache, + Some(filesystem), + Some(process), + ), + cleanup_executed: IndexMap::new(), + } + } + pub(crate) fn extract( - &self, + &mut self, _package: &dyn PackageInterface, file: &str, path: &str, @@ -35,7 +66,18 @@ impl RarDownloader { path.to_string(), ]; - if self.inner.process.execute(&command, &mut String::new()) == 0 { + let mut process_output = PhpMixed::Null; + if self.inner.process.execute( + PhpMixed::List( + command + .iter() + .map(|s| Box::new(PhpMixed::String(s.clone()))) + .collect(), + ), + Some(&mut process_output), + None, + )? == 0 + { return Ok(shirabe_external_packages::react::promise::resolve(None)); } @@ -101,3 +143,66 @@ impl RarDownloader { Ok(shirabe_external_packages::react::promise::resolve(None)) } } + +impl crate::downloader::downloader_interface::DownloaderInterface for RarDownloader { + fn get_installation_source(&self) -> String { + self.inner.get_installation_source() + } + + fn download( + &self, + package: &dyn PackageInterface, + path: &str, + prev_package: Option<&dyn PackageInterface>, + output: bool, + ) -> Result<Box<dyn PromiseInterface>> { + self.inner.download(package, path, prev_package, output) + } + + fn prepare( + &self, + r#type: &str, + package: &dyn PackageInterface, + path: &str, + prev_package: Option<&dyn PackageInterface>, + ) -> Result<Box<dyn PromiseInterface>> { + self.inner.prepare(r#type, package, path, prev_package) + } + + fn install( + &self, + package: &dyn PackageInterface, + path: &str, + output: bool, + ) -> Result<Box<dyn PromiseInterface>> { + self.inner.install(package, path, output) + } + + fn update( + &self, + initial: &dyn PackageInterface, + target: &dyn PackageInterface, + path: &str, + ) -> Result<Box<dyn PromiseInterface>> { + self.inner.update(initial, target, path) + } + + fn remove( + &self, + package: &dyn PackageInterface, + path: &str, + output: bool, + ) -> Result<Box<dyn PromiseInterface>> { + self.inner.remove(package, path, output) + } + + fn cleanup( + &self, + r#type: &str, + package: &dyn PackageInterface, + path: &str, + prev_package: Option<&dyn PackageInterface>, + ) -> Result<Box<dyn PromiseInterface>> { + self.inner.cleanup(r#type, package, path, prev_package) + } +} diff --git a/crates/shirabe/src/downloader/tar_downloader.rs b/crates/shirabe/src/downloader/tar_downloader.rs index d8531e0..aaa7153 100644 --- a/crates/shirabe/src/downloader/tar_downloader.rs +++ b/crates/shirabe/src/downloader/tar_downloader.rs @@ -1,8 +1,16 @@ //! ref: composer/src/Composer/Downloader/TarDownloader.php +use crate::cache::Cache; +use crate::config::Config; use crate::downloader::archive_downloader::ArchiveDownloader; +use crate::downloader::downloader_interface::DownloaderInterface; use crate::downloader::file_downloader::FileDownloader; +use crate::event_dispatcher::event_dispatcher::EventDispatcher; +use crate::io::io_interface::IOInterface; use crate::package::package_interface::PackageInterface; +use crate::util::filesystem::Filesystem; +use crate::util::http_downloader::HttpDownloader; +use crate::util::process_executor::ProcessExecutor; use anyhow::Result; use indexmap::IndexMap; use shirabe_external_packages::react::promise::promise_interface::PromiseInterface; @@ -15,6 +23,29 @@ pub struct TarDownloader { } impl TarDownloader { + pub fn new( + io: Box<dyn IOInterface>, + config: Config, + http_downloader: HttpDownloader, + event_dispatcher: Option<EventDispatcher>, + cache: Option<Cache>, + filesystem: Filesystem, + process: ProcessExecutor, + ) -> Self { + Self { + inner: FileDownloader::new( + io, + config, + http_downloader, + event_dispatcher, + cache, + Some(filesystem), + Some(process), + ), + cleanup_executed: IndexMap::new(), + } + } + pub(crate) fn extract( &self, package: &dyn PackageInterface, @@ -27,3 +58,66 @@ impl TarDownloader { Ok(shirabe_external_packages::react::promise::resolve(None)) } } + +impl DownloaderInterface for TarDownloader { + fn get_installation_source(&self) -> String { + self.inner.get_installation_source() + } + + fn download( + &self, + package: &dyn PackageInterface, + path: &str, + prev_package: Option<&dyn PackageInterface>, + output: bool, + ) -> Result<Box<dyn PromiseInterface>> { + self.inner.download(package, path, prev_package, output) + } + + fn prepare( + &self, + r#type: &str, + package: &dyn PackageInterface, + path: &str, + prev_package: Option<&dyn PackageInterface>, + ) -> Result<Box<dyn PromiseInterface>> { + self.inner.prepare(r#type, package, path, prev_package) + } + + fn install( + &self, + package: &dyn PackageInterface, + path: &str, + output: bool, + ) -> Result<Box<dyn PromiseInterface>> { + self.inner.install(package, path, output) + } + + fn update( + &self, + initial: &dyn PackageInterface, + target: &dyn PackageInterface, + path: &str, + ) -> Result<Box<dyn PromiseInterface>> { + self.inner.update(initial, target, path) + } + + fn remove( + &self, + package: &dyn PackageInterface, + path: &str, + output: bool, + ) -> Result<Box<dyn PromiseInterface>> { + self.inner.remove(package, path, output) + } + + fn cleanup( + &self, + r#type: &str, + package: &dyn PackageInterface, + path: &str, + prev_package: Option<&dyn PackageInterface>, + ) -> Result<Box<dyn PromiseInterface>> { + self.inner.cleanup(r#type, package, path, prev_package) + } +} diff --git a/crates/shirabe/src/downloader/transport_exception.rs b/crates/shirabe/src/downloader/transport_exception.rs index e4f04f3..382da01 100644 --- a/crates/shirabe/src/downloader/transport_exception.rs +++ b/crates/shirabe/src/downloader/transport_exception.rs @@ -24,6 +24,14 @@ impl TransportException { } } + pub fn get_code(&self) -> i64 { + self.code + } + + pub fn get_message(&self) -> &str { + &self.message + } + pub fn set_headers(&mut self, headers: Vec<String>) { self.headers = Some(headers); } diff --git a/crates/shirabe/src/downloader/vcs_downloader.rs b/crates/shirabe/src/downloader/vcs_downloader.rs index 5e19016..346603a 100644 --- a/crates/shirabe/src/downloader/vcs_downloader.rs +++ b/crates/shirabe/src/downloader/vcs_downloader.rs @@ -385,7 +385,7 @@ pub trait VcsDownloader: io_interface::NORMAL, ); self.io_mut() - .write_error(PhpMixed::String(logs), true, io_interface::NORMAL); + .write_error3(&logs, true, io_interface::NORMAL); } } diff --git a/crates/shirabe/src/downloader/xz_downloader.rs b/crates/shirabe/src/downloader/xz_downloader.rs index 1ad0bb1..61a7f14 100644 --- a/crates/shirabe/src/downloader/xz_downloader.rs +++ b/crates/shirabe/src/downloader/xz_downloader.rs @@ -1,11 +1,19 @@ //! ref: composer/src/Composer/Downloader/XzDownloader.php +use crate::cache::Cache; +use crate::config::Config; use crate::downloader::archive_downloader::ArchiveDownloader; use crate::downloader::file_downloader::FileDownloader; +use crate::event_dispatcher::event_dispatcher::EventDispatcher; +use crate::io::io_interface::IOInterface; use crate::package::package_interface::PackageInterface; +use crate::util::filesystem::Filesystem; +use crate::util::http_downloader::HttpDownloader; +use crate::util::process_executor::ProcessExecutor; use anyhow::{Result, bail}; use indexmap::IndexMap; use shirabe_external_packages::react::promise::promise_interface::PromiseInterface; +use shirabe_php_shim::PhpMixed; #[derive(Debug)] pub struct XzDownloader { @@ -14,16 +22,49 @@ pub struct XzDownloader { } impl XzDownloader { + pub fn new( + io: Box<dyn IOInterface>, + config: Config, + http_downloader: HttpDownloader, + event_dispatcher: Option<EventDispatcher>, + cache: Option<Cache>, + filesystem: Filesystem, + process: ProcessExecutor, + ) -> Self { + Self { + inner: FileDownloader::new( + io, + config, + http_downloader, + event_dispatcher, + cache, + Some(filesystem), + Some(process), + ), + cleanup_executed: IndexMap::new(), + } + } + pub(crate) fn extract( - &self, + &mut self, package: &dyn PackageInterface, file: &str, path: &str, ) -> Result<Box<dyn PromiseInterface>> { let command = vec!["tar", "-xJf", file, "-C", path]; - let mut ignored_output = String::new(); - if self.inner.process.execute(&command, &mut ignored_output) == 0 { + let mut ignored_output = PhpMixed::Null; + if self.inner.process.execute( + PhpMixed::List( + command + .iter() + .map(|s| Box::new(PhpMixed::String(s.to_string()))) + .collect(), + ), + Some(&mut ignored_output), + None, + )? == 0 + { return Ok(shirabe_external_packages::react::promise::resolve(None)); } @@ -36,3 +77,66 @@ impl XzDownloader { bail!(process_error); } } + +impl crate::downloader::downloader_interface::DownloaderInterface for XzDownloader { + fn get_installation_source(&self) -> String { + self.inner.get_installation_source() + } + + fn download( + &self, + package: &dyn PackageInterface, + path: &str, + prev_package: Option<&dyn PackageInterface>, + output: bool, + ) -> Result<Box<dyn PromiseInterface>> { + self.inner.download(package, path, prev_package, output) + } + + fn prepare( + &self, + r#type: &str, + package: &dyn PackageInterface, + path: &str, + prev_package: Option<&dyn PackageInterface>, + ) -> Result<Box<dyn PromiseInterface>> { + self.inner.prepare(r#type, package, path, prev_package) + } + + fn install( + &self, + package: &dyn PackageInterface, + path: &str, + output: bool, + ) -> Result<Box<dyn PromiseInterface>> { + self.inner.install(package, path, output) + } + + fn update( + &self, + initial: &dyn PackageInterface, + target: &dyn PackageInterface, + path: &str, + ) -> Result<Box<dyn PromiseInterface>> { + self.inner.update(initial, target, path) + } + + fn remove( + &self, + package: &dyn PackageInterface, + path: &str, + output: bool, + ) -> Result<Box<dyn PromiseInterface>> { + self.inner.remove(package, path, output) + } + + fn cleanup( + &self, + r#type: &str, + package: &dyn PackageInterface, + path: &str, + prev_package: Option<&dyn PackageInterface>, + ) -> Result<Box<dyn PromiseInterface>> { + self.inner.cleanup(r#type, package, path, prev_package) + } +} diff --git a/crates/shirabe/src/downloader/zip_downloader.rs b/crates/shirabe/src/downloader/zip_downloader.rs index 90e5639..7f779c8 100644 --- a/crates/shirabe/src/downloader/zip_downloader.rs +++ b/crates/shirabe/src/downloader/zip_downloader.rs @@ -152,13 +152,13 @@ impl ZipDownloader { if !is_windows_guard.unwrap() && unzip_commands_empty { if proc_open_missing { - self.inner.inner.io.write_error("<warning>proc_open is disabled so 'unzip' and '7z' commands cannot be used, zip files are being unpacked using the PHP zip extension.</warning>"); - self.inner.inner.io.write_error("<warning>This may cause invalid reports of corrupted archives. Besides, any UNIX permissions (e.g. executable) defined in the archives will be lost.</warning>"); - self.inner.inner.io.write_error("<warning>Enabling proc_open and installing 'unzip' or '7z' (21.01+) may remediate them.</warning>"); + self.inner.io.write_error("<warning>proc_open is disabled so 'unzip' and '7z' commands cannot be used, zip files are being unpacked using the PHP zip extension.</warning>"); + self.inner.io.write_error("<warning>This may cause invalid reports of corrupted archives. Besides, any UNIX permissions (e.g. executable) defined in the archives will be lost.</warning>"); + self.inner.io.write_error("<warning>Enabling proc_open and installing 'unzip' or '7z' (21.01+) may remediate them.</warning>"); } else { - self.inner.inner.io.write_error("<warning>As there is no 'unzip' nor '7z' command installed zip files are being unpacked using the PHP zip extension.</warning>"); - self.inner.inner.io.write_error("<warning>This may cause invalid reports of corrupted archives. Besides, any UNIX permissions (e.g. executable) defined in the archives will be lost.</warning>"); - self.inner.inner.io.write_error("<warning>Installing 'unzip' or '7z' (21.01+) may remediate them.</warning>"); + self.inner.io.write_error("<warning>As there is no 'unzip' nor '7z' command installed zip files are being unpacked using the PHP zip extension.</warning>"); + self.inner.io.write_error("<warning>This may cause invalid reports of corrupted archives. Besides, any UNIX permissions (e.g. executable) defined in the archives will be lost.</warning>"); + self.inner.io.write_error("<warning>Installing 'unzip' or '7z' (21.01+) may remediate them.</warning>"); } } } @@ -226,7 +226,7 @@ impl ZipDownloader { Preg::is_match_strict_groups(r"^\s*7-Zip(?:\s\[64\])?\s([0-9.]+)", &output) { if version_compare(&m[1], "21.01", "<") { - self.inner.inner.io.write_error(&format!( + self.inner.io.write_error(&format!( " <warning>Unzipping using {} {} may result in incorrect file permissions. Install {} 21.01+ or unzip to ensure you get correct permissions.</warning>", executable, m[1], executable, )); @@ -235,7 +235,7 @@ impl ZipDownloader { } } - let io = &self.inner.inner.io; + let io = &self.inner.io; let try_fallback = |process_error: anyhow::Error| -> Result<Box<dyn PromiseInterface>> { if is_last_chance { return Err(process_error); @@ -297,7 +297,7 @@ impl ZipDownloader { self.extract_with_zip_archive(package, file, path) }; - match self.inner.inner.process.execute_async(&command) { + match self.inner.process.execute_async(&command) { Ok(promise) => Ok(promise.then( Box::new(move |process: Process| -> Result<()> { if !process.is_successful() { |
