diff options
| author | nsfisis <nsfisis@gmail.com> | 2026-05-14 19:53:15 +0900 |
|---|---|---|
| committer | nsfisis <nsfisis@gmail.com> | 2026-05-14 19:53:15 +0900 |
| commit | 5350d7f77f3e3c270cfefd5c90f8805def09dc0c (patch) | |
| tree | 87063fd40716889a1052634b9105f63e45390323 /crates | |
| parent | d5c9d8d6abe901e9b7258fd74fdc9dcc29d9dcab (diff) | |
| download | php-shirabe-5350d7f77f3e3c270cfefd5c90f8805def09dc0c.tar.gz php-shirabe-5350d7f77f3e3c270cfefd5c90f8805def09dc0c.tar.zst php-shirabe-5350d7f77f3e3c270cfefd5c90f8805def09dc0c.zip | |
feat(port): port RarDownloader.php
Diffstat (limited to 'crates')
| -rw-r--r-- | crates/shirabe-php-shim/src/lib.rs | 30 | ||||
| -rw-r--r-- | crates/shirabe/src/downloader/rar_downloader.rs | 82 |
2 files changed, 112 insertions, 0 deletions
diff --git a/crates/shirabe-php-shim/src/lib.rs b/crates/shirabe-php-shim/src/lib.rs index c2a20cf..758dd1c 100644 --- a/crates/shirabe-php-shim/src/lib.rs +++ b/crates/shirabe-php-shim/src/lib.rs @@ -219,3 +219,33 @@ impl PharData { todo!() } } + +pub fn class_exists(name: &str) -> bool { + todo!() +} + +#[derive(Debug)] +pub struct RarEntry; + +impl RarEntry { + pub fn extract(&self, path: &str) -> bool { + todo!() + } +} + +#[derive(Debug)] +pub struct RarArchive; + +impl RarArchive { + pub fn open(file: &str) -> Option<Self> { + todo!() + } + + pub fn get_entries(&self) -> Option<Vec<RarEntry>> { + todo!() + } + + pub fn close(&self) { + todo!() + } +} diff --git a/crates/shirabe/src/downloader/rar_downloader.rs b/crates/shirabe/src/downloader/rar_downloader.rs index 1470763..1aaa71c 100644 --- a/crates/shirabe/src/downloader/rar_downloader.rs +++ b/crates/shirabe/src/downloader/rar_downloader.rs @@ -1 +1,83 @@ //! ref: composer/src/Composer/Downloader/RarDownloader.php + +use anyhow::Result; +use shirabe_external_packages::react::promise::promise_interface::PromiseInterface; +use shirabe_php_shim::{class_exists, implode, RarArchive, RuntimeException, UnexpectedValueException}; +use crate::downloader::archive_downloader::ArchiveDownloader; +use crate::package::package_interface::PackageInterface; +use crate::util::ini_helper::IniHelper; +use crate::util::platform::Platform; + +pub struct RarDownloader { + inner: ArchiveDownloader, +} + +impl RarDownloader { + pub(crate) fn extract(&self, _package: &dyn PackageInterface, file: &str, path: &str) -> Result<Box<dyn PromiseInterface>> { + let mut process_error: Option<String> = None; + + if !Platform::is_windows() { + let command = vec![ + "sh".to_string(), + "-c".to_string(), + r#"unrar x -- "$0" "$1" >/dev/null && chmod -R u+w "$1""#.to_string(), + file.to_string(), + path.to_string(), + ]; + + if self.inner.process.execute(&command, &mut String::new()) == 0 { + return Ok(shirabe_external_packages::react::promise::resolve(None)); + } + + process_error = Some(format!( + "Failed to execute {}\n\n{}", + implode(" ", &command), + self.inner.process.get_error_output(), + )); + } + + if !class_exists("RarArchive") { + let ini_message = IniHelper::get_message(); + let error = if !Platform::is_windows() { + format!("Could not decompress the archive, enable the PHP rar extension.\n{}", ini_message) + } else { + format!( + "Could not decompress the archive, enable the PHP rar extension or install unrar.\n{}\n{}", + ini_message, + process_error.as_deref().unwrap_or(""), + ) + }; + return Err(RuntimeException { message: error, code: 0 }.into()); + } + + let rar_archive = RarArchive::open(file); + if rar_archive.is_none() { + return Err(UnexpectedValueException { + message: format!("Could not open RAR archive: {}", file), + code: 0, + }.into()); + } + let rar_archive = rar_archive.unwrap(); + + let entries = rar_archive.get_entries(); + if entries.is_none() { + return Err(RuntimeException { + message: "Could not retrieve RAR archive entries".to_string(), + code: 0, + }.into()); + } + + for entry in entries.unwrap() { + if !entry.extract(path) { + return Err(RuntimeException { + message: "Could not extract entry".to_string(), + code: 0, + }.into()); + } + } + + rar_archive.close(); + + Ok(shirabe_external_packages::react::promise::resolve(None)) + } +} |
