aboutsummaryrefslogtreecommitdiffhomepage
path: root/crates
diff options
context:
space:
mode:
authornsfisis <nsfisis@gmail.com>2026-05-14 19:53:15 +0900
committernsfisis <nsfisis@gmail.com>2026-05-14 19:53:15 +0900
commit5350d7f77f3e3c270cfefd5c90f8805def09dc0c (patch)
tree87063fd40716889a1052634b9105f63e45390323 /crates
parentd5c9d8d6abe901e9b7258fd74fdc9dcc29d9dcab (diff)
downloadphp-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.rs30
-rw-r--r--crates/shirabe/src/downloader/rar_downloader.rs82
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))
+ }
+}