//! ref: composer/src/Composer/Downloader/XzDownloader.php use crate::cache::Cache; use crate::config::Config; use crate::downloader::ArchiveDownloader; use crate::downloader::FileDownloader; use crate::event_dispatcher::EventDispatcher; use crate::io::IOInterface; use crate::package::PackageInterface; use crate::util::Filesystem; use crate::util::HttpDownloader; use crate::util::ProcessExecutor; use anyhow::{Result, bail}; use indexmap::IndexMap; use shirabe_php_shim::PhpMixed; #[derive(Debug)] pub struct XzDownloader { inner: FileDownloader, cleanup_executed: IndexMap, } impl XzDownloader { pub fn new( io: Box, config: std::rc::Rc>, http_downloader: std::rc::Rc>, event_dispatcher: Option>>, cache: Option>>, filesystem: std::rc::Rc>, process: std::rc::Rc>, ) -> Self { Self { inner: FileDownloader::new( io, config, http_downloader, event_dispatcher, cache, Some(filesystem), Some(process), ), cleanup_executed: IndexMap::new(), } } pub(crate) async fn extract( &mut self, package: &dyn PackageInterface, file: &str, path: &str, ) -> Result> { let command = vec!["tar", "-xJf", file, "-C", path]; let mut ignored_output = PhpMixed::Null; if self.inner.process.borrow_mut().execute( PhpMixed::List( command .iter() .map(|s| Box::new(PhpMixed::String(s.to_string()))) .collect(), ), Some(&mut ignored_output), (), )? == 0 { return Ok(shirabe_external_packages::react::promise::resolve(None)); } let process_error = format!( "Failed to execute {}\n\n{}", command.join(" "), self.inner.process.borrow().get_error_output() ); bail!(process_error); } } impl crate::downloader::DownloaderInterface for XzDownloader { fn get_installation_source(&self) -> String { self.inner.get_installation_source() } async fn download( &self, package: &dyn PackageInterface, path: &str, prev_package: Option<&dyn PackageInterface>, output: bool, ) -> Result> { self.inner.download(package, path, prev_package, output) } async fn prepare( &self, r#type: &str, package: &dyn PackageInterface, path: &str, prev_package: Option<&dyn PackageInterface>, ) -> Result> { self.inner.prepare(r#type, package, path, prev_package) } async fn install( &self, package: &dyn PackageInterface, path: &str, output: bool, ) -> Result> { self.inner.install(package, path, output) } async fn update( &self, initial: &dyn PackageInterface, target: &dyn PackageInterface, path: &str, ) -> Result> { self.inner.update(initial, target, path) } async fn remove( &self, package: &dyn PackageInterface, path: &str, output: bool, ) -> Result> { self.inner.remove(package, path, output) } async fn cleanup( &self, r#type: &str, package: &dyn PackageInterface, path: &str, prev_package: Option<&dyn PackageInterface>, ) -> Result> { self.inner.cleanup(r#type, package, path, prev_package) } }