1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
|
//! ref: composer/src/Composer/Downloader/RarDownloader.php
use crate::downloader::archive_downloader::ArchiveDownloader;
use crate::downloader::file_downloader::FileDownloader;
use crate::package::package_interface::PackageInterface;
use crate::util::ini_helper::IniHelper;
use crate::util::platform::Platform;
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,
};
pub struct RarDownloader {
inner: FileDownloader,
cleanup_executed: IndexMap<String, bool>,
}
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))
}
}
|