aboutsummaryrefslogtreecommitdiffhomepage
path: root/crates/shirabe/src/installer
diff options
context:
space:
mode:
Diffstat (limited to 'crates/shirabe/src/installer')
-rw-r--r--crates/shirabe/src/installer/binary_installer.rs7
-rw-r--r--crates/shirabe/src/installer/installation_manager.rs91
-rw-r--r--crates/shirabe/src/installer/library_installer.rs182
-rw-r--r--crates/shirabe/src/installer/plugin_installer.rs51
-rw-r--r--crates/shirabe/src/installer/project_installer.rs8
-rw-r--r--crates/shirabe/src/installer/suggested_packages_reporter.rs1
6 files changed, 175 insertions, 165 deletions
diff --git a/crates/shirabe/src/installer/binary_installer.rs b/crates/shirabe/src/installer/binary_installer.rs
index c7b880b..aea0a7c 100644
--- a/crates/shirabe/src/installer/binary_installer.rs
+++ b/crates/shirabe/src/installer/binary_installer.rs
@@ -252,7 +252,7 @@ impl BinaryInstaller {
let bin_path = self
.filesystem
.borrow_mut()
- .find_shortest_path(link, bin, false);
+ .find_shortest_path(link, bin, false, false);
let caller = Self::determine_binary_caller(bin);
// if the target is a php file, we run the unixy proxy file
@@ -288,7 +288,7 @@ impl BinaryInstaller {
let bin_path = self
.filesystem
.borrow_mut()
- .find_shortest_path(link, bin, false);
+ .find_shortest_path(link, bin, false, false);
let bin_dir = ProcessExecutor::escape(&dirname(&bin_path));
let bin_file = basename(&bin_path);
@@ -312,7 +312,7 @@ impl BinaryInstaller {
let bin_path_exported = self
.filesystem
.borrow()
- .find_shortest_path_code(link, bin, false, true);
+ .find_shortest_path_code(link, bin, false, true, false);
let mut stream_proxy_code = String::new();
let mut stream_hint = String::new();
let mut globals_code = format!("$GLOBALS['_composer_bin_dir'] = __DIR__;\n",);
@@ -329,6 +329,7 @@ impl BinaryInstaller {
&format!("{}/autoload.php", vendor_dir_real),
false,
true,
+ false,
),
));
}
diff --git a/crates/shirabe/src/installer/installation_manager.rs b/crates/shirabe/src/installer/installation_manager.rs
index 3789729..3b342a9 100644
--- a/crates/shirabe/src/installer/installation_manager.rs
+++ b/crates/shirabe/src/installer/installation_manager.rs
@@ -42,7 +42,7 @@ pub struct InstallationManager {
notifiable_packages: IndexMap<String, Vec<Box<dyn PackageInterface>>>,
loop_: std::rc::Rc<std::cell::RefCell<Loop>>,
io: Box<dyn IOInterface>,
- event_dispatcher: Option<EventDispatcher>,
+ event_dispatcher: Option<std::rc::Rc<std::cell::RefCell<EventDispatcher>>>,
output_progress: bool,
}
@@ -50,7 +50,7 @@ impl InstallationManager {
pub fn new(
loop_: std::rc::Rc<std::cell::RefCell<Loop>>,
io: Box<dyn IOInterface>,
- event_dispatcher: Option<EventDispatcher>,
+ event_dispatcher: Option<std::rc::Rc<std::cell::RefCell<EventDispatcher>>>,
) -> Self {
Self {
installers: vec![],
@@ -85,7 +85,7 @@ impl InstallationManager {
let _ = installer;
let key: Option<usize> = None;
if let Some(k) = key {
- array_splice(&mut self.installers, k as i64, Some(1), None);
+ array_splice(&mut self.installers, k as i64, Some(1), vec![]);
self.cache = IndexMap::new();
}
}
@@ -109,18 +109,18 @@ impl InstallationManager {
/// @param string $type package type
///
/// @throws \InvalidArgumentException if installer for provided type is not registered
- pub fn get_installer(&mut self, r#type: &str) -> Result<&dyn InstallerInterface> {
+ pub fn get_installer(&mut self, r#type: &str) -> Result<&mut dyn InstallerInterface> {
let r#type = strtolower(r#type);
if self.cache.contains_key(&r#type) {
- return Ok(self.cache.get(&r#type).unwrap().as_ref());
+ return Ok(self.cache.get_mut(&r#type).unwrap().as_mut());
}
for installer in &self.installers {
if installer.supports(&r#type) {
// TODO(phase-b): cache by cloning Box<dyn InstallerInterface> is non-trivial
self.cache.insert(r#type.clone(), installer.clone_box());
- return Ok(self.cache.get(&r#type).unwrap().as_ref());
+ return Ok(self.cache.get_mut(&r#type).unwrap().as_mut());
}
}
@@ -187,9 +187,9 @@ impl InstallationManager {
let signal_handler = SignalHandler::create(
vec![
- SignalHandler::SIGINT,
- SignalHandler::SIGTERM,
- SignalHandler::SIGHUP,
+ SignalHandler::SIGINT.to_string(),
+ SignalHandler::SIGTERM.to_string(),
+ SignalHandler::SIGHUP.to_string(),
],
// TODO(phase-b): closure captures &mut self via &mut cleanup_promises
Box::new(move |signal: String, handler: &SignalHandler| {
@@ -331,7 +331,7 @@ impl InstallationManager {
if op_type != "uninstall" {
let installer = self.get_installer(package.get_type())?;
let promise = installer.download(package, initial_package);
- if let Some(p) = promise {
+ if let Ok(Some(p)) = promise {
promises.push(p);
}
}
@@ -447,8 +447,6 @@ impl InstallationManager {
initial_package = None;
}
- let installer = self.get_installer(package.get_type())?;
-
let event_name = match op_type.as_str() {
"install" => PackageEvents::PRE_PACKAGE_INSTALL,
"update" => PackageEvents::PRE_PACKAGE_UPDATE,
@@ -457,25 +455,26 @@ impl InstallationManager {
};
if run_scripts && self.event_dispatcher.is_some() {
- self.event_dispatcher
- .as_mut()
- .unwrap()
- .dispatch_package_event(
- event_name,
- dev_mode,
- repo,
- all_operations,
- operation.as_ref(),
- );
+ // TODO(phase-b): dispatch_package_event takes Box<dyn RepositoryInterface>/Vec<Box<...>>
+ // but we hold &mut dyn here. Needs structural rework (likely shared Rc on repo and ops).
+ let _ = (
+ event_name,
+ dev_mode,
+ &repo,
+ &all_operations,
+ operation.as_ref(),
+ );
}
let _dispatcher = self.event_dispatcher.as_ref();
let _io = self.io.as_ref();
+ let installer = self.get_installer(package.get_type())?;
let promise = installer.prepare(&op_type, package, initial_package);
let promise = match promise {
- Some(p) => p,
- None => promise::resolve(None),
+ Ok(Some(p)) => p,
+ Ok(None) => promise::resolve(None),
+ Err(e) => return Err(e),
};
// TODO(phase-b): chain `.then(cb1).then(cb2)` with cleanup_promises[index], repo.write, etc.
@@ -527,7 +526,8 @@ impl InstallationManager {
// TODO(phase-b): progress = self.io.get_progress_bar();
progress = Some(());
}
- let _ = self.loop_.borrow_mut().wait(promises, progress);
+ // TODO(phase-b): pass actual ProgressBar when self.io.get_progress_bar() is implemented
+ let _ = self.loop_.borrow_mut().wait(promises, None);
if progress.is_some() {
// progress.clear();
// ProgressBar in non-decorated output does not output a final line-break and clear() does nothing
@@ -545,7 +545,7 @@ impl InstallationManager {
package: &dyn PackageInterface,
) -> Option<Box<dyn PromiseInterface>> {
let installer = self.get_installer(package.get_type()).ok()?;
- let promise = installer.cleanup("install", package, None);
+ let promise = installer.cleanup("install", package, None).ok()?;
promise
}
@@ -560,7 +560,7 @@ impl InstallationManager {
) -> Option<Box<dyn PromiseInterface>> {
let package = operation.get_package();
let installer = self.get_installer(package.get_type()).ok()?;
- let promise = installer.install(repo, package);
+ let promise = installer.install(repo, package).ok()?;
self.mark_for_notification(package);
promise
@@ -582,14 +582,15 @@ impl InstallationManager {
let promise = if initial_type == target_type {
let installer = self.get_installer(initial_type).ok()?;
- let promise = installer.update(repo, initial, target);
+ let promise = installer.update(repo, initial, target).ok()?;
self.mark_for_notification(target);
promise
} else {
let promise = self
.get_installer(initial_type)
.ok()?
- .uninstall(repo, initial);
+ .uninstall(repo, initial)
+ .ok()?;
let promise = match promise {
Some(p) => p,
None => promise::resolve(None),
@@ -615,7 +616,7 @@ impl InstallationManager {
let package = operation.get_package();
let installer = self.get_installer(package.get_type()).ok()?;
- installer.uninstall(repo, package)
+ installer.uninstall(repo, package).ok()?
}
/// Executes markAliasInstalled operation.
@@ -684,9 +685,13 @@ impl InstallationManager {
"Content-type: application/x-www-form-urlencoded".to_string(),
))]),
);
+ let params_vec: Vec<(&str, &str)> = params
+ .iter()
+ .map(|(k, v)| (k.as_str(), v.as_str()))
+ .collect();
http.insert(
"content".to_string(),
- PhpMixed::String(http_build_query(&params, "", Some("&"))),
+ PhpMixed::String(http_build_query(&params_vec, "", "&")),
);
http.insert("timeout".to_string(), PhpMixed::Int(3));
opts.insert(
@@ -696,12 +701,13 @@ impl InstallationManager {
),
);
- promises.push(self.loop_.borrow().get_http_downloader().borrow_mut().add(
- &url,
- &PhpMixed::Array(
- opts.into_iter().map(|(k, v)| (k, Box::new(v))).collect(),
- ),
- )?);
+ promises.push(
+ self.loop_
+ .borrow()
+ .get_http_downloader()
+ .borrow_mut()
+ .add(&url, opts)?,
+ );
}
continue;
@@ -767,10 +773,13 @@ impl InstallationManager {
PhpMixed::Array(http.into_iter().map(|(k, v)| (k, Box::new(v))).collect()),
);
- promises.push(self.loop_.borrow().get_http_downloader().borrow_mut().add(
- repo_url,
- &PhpMixed::Array(opts.into_iter().map(|(k, v)| (k, Box::new(v))).collect()),
- )?);
+ promises.push(
+ self.loop_
+ .borrow()
+ .get_http_downloader()
+ .borrow_mut()
+ .add(repo_url, opts)?,
+ );
}
let _ = self.loop_.borrow_mut().wait(promises, None);
diff --git a/crates/shirabe/src/installer/library_installer.rs b/crates/shirabe/src/installer/library_installer.rs
index 0bc87f9..fc79bdd 100644
--- a/crates/shirabe/src/installer/library_installer.rs
+++ b/crates/shirabe/src/installer/library_installer.rs
@@ -44,8 +44,9 @@ impl LibraryInstaller {
binary_installer: Option<BinaryInstaller>,
) -> Self {
// PHP: $this->downloadManager = $composer instanceof Composer ? $composer->getDownloadManager() : null;
- let download_manager =
- if let Some(full_composer) = composer.as_any().downcast_ref::<Composer>() {
+ // TODO(phase-b): PartialComposer cannot downcast to Composer in this Rust port.
+ let download_manager: Option<std::rc::Rc<std::cell::RefCell<DownloadManager>>> =
+ if let Some(_full_composer) = composer.as_any().downcast_ref::<Composer>() {
// TODO(phase-b): clone or borrow the DownloadManager from the full Composer
Some(todo!("composer.get_download_manager() as DownloadManager"))
} else {
@@ -55,8 +56,12 @@ impl LibraryInstaller {
let filesystem = filesystem
.unwrap_or_else(|| std::rc::Rc::new(std::cell::RefCell::new(Filesystem::new(None))));
let vendor_dir = rtrim(
- // TODO(phase-b): composer.get_config().borrow_mut().get("vendor-dir") returns a PhpMixed/String
- &composer.get_config().borrow_mut().get("vendor-dir"),
+ // TODO(phase-b): Config::get returns PhpMixed; coerce to String via get_str.
+ &composer
+ .get_config()
+ .borrow_mut()
+ .get_str("vendor-dir")
+ .unwrap_or_default(),
Some("/"),
);
let binary_installer = binary_installer.unwrap_or_else(|| {
@@ -64,13 +69,22 @@ impl LibraryInstaller {
// TODO(phase-b): pass io by reference/clone
todo!("io reference"),
rtrim(
- &composer.get_config().borrow_mut().get("bin-dir"),
+ &composer
+ .get_config()
+ .borrow_mut()
+ .get_str("bin-dir")
+ .unwrap_or_default(),
Some("/"),
),
- composer.get_config().borrow_mut().get("bin-compat"),
+ // TODO(phase-b): Config::get returns PhpMixed; coerce to String via get_str.
+ composer
+ .get_config()
+ .borrow_mut()
+ .get_str("bin-compat")
+ .unwrap_or_default(),
// TODO(phase-b): pass filesystem reference
todo!("filesystem reference"),
- vendor_dir.clone(),
+ Some(vendor_dir.clone()),
)
});
@@ -86,12 +100,10 @@ impl LibraryInstaller {
}
/// Make sure binaries are installed for a given package.
- pub fn ensure_binaries_presence(&self, package: &dyn PackageInterface) {
- self.binary_installer.install_binaries(
- package,
- &self.get_install_path(package).unwrap(),
- false,
- );
+ pub fn ensure_binaries_presence(&mut self, package: &dyn PackageInterface) {
+ let install_path = self.get_install_path(package).unwrap();
+ self.binary_installer
+ .install_binaries(package, &install_path, false);
}
/// Returns the base path of the package without target-dir path
@@ -104,7 +116,7 @@ impl LibraryInstaller {
if let Some(target_dir) = target_dir {
if !target_dir.is_empty() {
- return Preg::replace(
+ let replaced = Preg::replace(
&format!(
"{{/*{}/?$}}",
preg_quote(&target_dir, None).replace('/', "/+")
@@ -112,6 +124,7 @@ impl LibraryInstaller {
"",
&install_path,
);
+ return replaced.unwrap_or(install_path);
}
}
@@ -126,9 +139,11 @@ impl LibraryInstaller {
) -> Result<Option<Box<dyn PromiseInterface>>> {
let download_path = self.get_install_path(package).unwrap();
- self.get_download_manager()
- .borrow()
- .install(package, &download_path)
+ Ok(Some(
+ self.get_download_manager()
+ .borrow()
+ .install(package, &download_path)?,
+ ))
}
/// @return PromiseInterface|null
@@ -152,17 +167,13 @@ impl LibraryInstaller {
None => shirabe_external_packages::react::promise::resolve(None),
};
- return Ok(Some(promise.then(Box::new(
- move || -> Result<Box<dyn PromiseInterface>> {
- // TODO(phase-b): capture target/self into the closure
- let promise = self.install_code(target)?;
- if let Some(promise) = promise {
- return Ok(promise);
- }
-
- Ok(shirabe_external_packages::react::promise::resolve(None))
- },
- ))));
+ // TODO(phase-b): promise.then expects Option<Box<dyn FnOnce(Option<PhpMixed>) -> Option<PhpMixed>>>
+ // arguments. Translating the original PHP closure (which captures &self and target)
+ // requires restructuring; tracked separately.
+ let _ = promise;
+ return Ok(Some(todo!(
+ "promise.then(...) chain to install_code(target)"
+ )));
}
self.filesystem
@@ -170,9 +181,11 @@ impl LibraryInstaller {
.rename(&initial_download_path, &target_download_path);
}
- self.get_download_manager()
- .borrow()
- .update(initial, target, &target_download_path)
+ Ok(Some(self.get_download_manager().borrow().update(
+ initial,
+ target,
+ &target_download_path,
+ )?))
}
/// @return PromiseInterface|null
@@ -183,9 +196,11 @@ impl LibraryInstaller {
) -> Result<Option<Box<dyn PromiseInterface>>> {
let download_path = self.get_package_base_path(package);
- self.get_download_manager()
- .borrow()
- .remove(package, &download_path)
+ Ok(Some(
+ self.get_download_manager()
+ .borrow()
+ .remove(package, &download_path)?,
+ ))
}
pub(crate) fn initialize_vendor_dir(&mut self) {
@@ -262,9 +277,11 @@ impl InstallerInterface for LibraryInstaller {
// self.initialize_vendor_dir();
let download_path = self.get_install_path(package).unwrap();
- self.get_download_manager()
- .borrow()
- .download(package, &download_path, prev_package)
+ Ok(Some(self.get_download_manager().borrow().download(
+ package,
+ &download_path,
+ prev_package,
+ )?))
}
fn prepare(
@@ -277,9 +294,12 @@ impl InstallerInterface for LibraryInstaller {
// self.initialize_vendor_dir();
let download_path = self.get_install_path(package).unwrap();
- self.get_download_manager()
- .borrow()
- .prepare(r#type, package, &download_path, prev_package)
+ Ok(Some(self.get_download_manager().borrow().prepare(
+ r#type,
+ package,
+ &download_path,
+ prev_package,
+ )?))
}
fn cleanup(
@@ -292,9 +312,12 @@ impl InstallerInterface for LibraryInstaller {
// self.initialize_vendor_dir();
let download_path = self.get_install_path(package).unwrap();
- self.get_download_manager()
- .borrow()
- .cleanup(r#type, package, &download_path, prev_package)
+ Ok(Some(self.get_download_manager().borrow().cleanup(
+ r#type,
+ package,
+ &download_path,
+ prev_package,
+ )?))
}
fn install(
@@ -317,17 +340,13 @@ impl InstallerInterface for LibraryInstaller {
None => shirabe_external_packages::react::promise::resolve(None),
};
- let binary_installer = &self.binary_installer;
- let install_path = self.get_install_path(package).unwrap();
-
- // TODO(phase-b): capture binary_installer/install_path/package/repo into the closure
- Ok(Some(promise.then(Box::new(move || -> Result<()> {
- binary_installer.install_binaries(package, &install_path, true);
- if !repo.has_package(package) {
- repo.add_package(package.clone_package_box())?;
- }
- Ok(())
- }))))
+ // TODO(phase-b): promise.then expects Option<Box<dyn FnOnce(Option<PhpMixed>) -> Option<PhpMixed>>>
+ // arguments. The original PHP closure captures &mut self/binary_installer/repo/package;
+ // restructuring required.
+ let _ = promise;
+ Ok(Some(todo!(
+ "promise.then(...) chain to install_binaries + repo.add_package"
+ )))
}
fn update(
@@ -354,18 +373,13 @@ impl InstallerInterface for LibraryInstaller {
None => shirabe_external_packages::react::promise::resolve(None),
};
- let binary_installer = &self.binary_installer;
- let install_path = self.get_install_path(target).unwrap();
-
- // TODO(phase-b): capture binary_installer/install_path/target/initial/repo into the closure
- Ok(Some(promise.then(Box::new(move || -> Result<()> {
- binary_installer.install_binaries(target, &install_path, true);
- repo.remove_package(initial)?;
- if !repo.has_package(target) {
- repo.add_package(target.clone_package_box())?;
- }
- Ok(())
- }))))
+ // TODO(phase-b): promise.then expects Option<Box<dyn FnOnce(Option<PhpMixed>) -> Option<PhpMixed>>>
+ // arguments. Closure captures &mut self/binary_installer/repo/initial/target;
+ // restructuring required.
+ let _ = promise;
+ Ok(Some(todo!(
+ "promise.then(...) chain to install_binaries + repo updates"
+ )))
}
fn uninstall(
@@ -387,28 +401,13 @@ impl InstallerInterface for LibraryInstaller {
None => shirabe_external_packages::react::promise::resolve(None),
};
- let binary_installer = &self.binary_installer;
- let download_path = self.get_package_base_path(package);
- let filesystem = &self.filesystem;
-
- // TODO(phase-b): capture binary_installer/filesystem/download_path/package/repo into the closure
- Ok(Some(promise.then(Box::new(move || -> Result<()> {
- binary_installer.remove_binaries(package);
- repo.remove_package(package)?;
-
- if strpos(package.get_name(), "/").is_some() {
- let package_vendor_dir = shirabe_php_shim::dirname(&download_path);
- if shirabe_php_shim::is_dir(&package_vendor_dir)
- && filesystem.borrow().is_dir_empty(&package_vendor_dir)
- {
- Silencer::call(|| {
- rmdir(&package_vendor_dir);
- Ok(())
- })?;
- }
- }
- Ok(())
- }))))
+ // TODO(phase-b): promise.then expects Option<Box<dyn FnOnce(Option<PhpMixed>) -> Option<PhpMixed>>>
+ // arguments. Closure captures binary_installer/filesystem/download_path/package/repo;
+ // restructuring required.
+ let _ = promise;
+ Ok(Some(todo!(
+ "promise.then(...) chain to remove_binaries/remove_package/rmdir"
+ )))
}
fn get_install_path(&self, package: &dyn PackageInterface) -> Option<String> {
@@ -439,7 +438,10 @@ impl InstallerInterface for LibraryInstaller {
}
impl BinaryPresenceInterface for LibraryInstaller {
- fn ensure_binaries_presence(&self, package: &dyn PackageInterface) {
- LibraryInstaller::ensure_binaries_presence(self, package)
+ fn ensure_binaries_presence(&self, _package: &dyn PackageInterface) {
+ // TODO(phase-b): trait takes &self but LibraryInstaller::ensure_binaries_presence
+ // requires &mut self due to BinaryInstaller::install_binaries(&mut self, ...).
+ // Revisit the trait or use interior mutability.
+ todo!()
}
}
diff --git a/crates/shirabe/src/installer/plugin_installer.rs b/crates/shirabe/src/installer/plugin_installer.rs
index bb04947..2ec8cb9 100644
--- a/crates/shirabe/src/installer/plugin_installer.rs
+++ b/crates/shirabe/src/installer/plugin_installer.rs
@@ -57,19 +57,8 @@ impl PluginInstaller {
}
fn get_plugin_manager(&self) -> &PluginManager {
- // TODO(plugin): assert self.inner.composer is fully loaded Composer instance
- assert!(
- self.inner.composer.is_full_composer(),
- "{}",
- LogicException {
- message:
- "PluginInstaller should be initialized with a fully loaded Composer instance."
- .to_string(),
- code: 0,
- }
- );
- // TODO(plugin): return plugin manager from composer
- self.inner.composer.get_plugin_manager()
+ // TODO(plugin): PartialComposer does not expose PluginManager; revisit when wiring plugin support
+ todo!("PartialComposer.get_plugin_manager")
}
fn get_plugin_manager_mut(&mut self) -> &mut PluginManager {
@@ -106,8 +95,8 @@ impl InstallerInterface for PluginInstaller {
.map(|v| matches!(v, PhpMixed::Bool(true)))
.unwrap_or(false);
// TODO(plugin): check if plugin is allowed
- self.get_plugin_manager()
- .is_plugin_allowed(package.get_name(), false, plugin_optional);
+ // TODO(phase-b): is_plugin_allowed needs &mut PluginManager but prepare is &self.
+ let _ = plugin_optional;
}
self.inner.prepare(r#type, package, prev_package)
@@ -145,12 +134,15 @@ impl InstallerInterface for PluginInstaller {
};
// TODO(plugin): register package in plugin manager after install, rollback on failure
- Ok(Some(promise.then(Box::new(move || -> Result<()> {
- Platform::workaround_filesystem_issues();
- // self.get_plugin_manager().register_package(package, true)?;
- // On error: self.rollback_install(e, repo, package)?;
- Ok(())
- }))))
+ Ok(Some(promise.then(
+ Some(Box::new(move |_v| -> Option<PhpMixed> {
+ Platform::workaround_filesystem_issues();
+ // self.get_plugin_manager().register_package(package, true)?;
+ // On error: self.rollback_install(e, repo, package)?;
+ None
+ })),
+ None,
+ )))
}
fn update(
@@ -166,13 +158,16 @@ impl InstallerInterface for PluginInstaller {
};
// TODO(plugin): deactivate initial and register target in plugin manager after update, rollback on failure
- Ok(Some(promise.then(Box::new(move || -> Result<()> {
- Platform::workaround_filesystem_issues();
- // self.get_plugin_manager().deactivate_package(initial);
- // self.get_plugin_manager().register_package(target, true)?;
- // On error: self.rollback_install(e, repo, target)?;
- Ok(())
- }))))
+ Ok(Some(promise.then(
+ Some(Box::new(move |_v| -> Option<PhpMixed> {
+ Platform::workaround_filesystem_issues();
+ // self.get_plugin_manager().deactivate_package(initial);
+ // self.get_plugin_manager().register_package(target, true)?;
+ // On error: self.rollback_install(e, repo, target)?;
+ None
+ })),
+ None,
+ )))
}
fn uninstall(
diff --git a/crates/shirabe/src/installer/project_installer.rs b/crates/shirabe/src/installer/project_installer.rs
index 906e2c0..6f794af 100644
--- a/crates/shirabe/src/installer/project_installer.rs
+++ b/crates/shirabe/src/installer/project_installer.rs
@@ -97,9 +97,11 @@ impl InstallerInterface for ProjectInstaller {
_repo: &mut dyn InstalledRepositoryInterface,
package: &dyn PackageInterface,
) -> anyhow::Result<Option<Box<dyn PromiseInterface>>> {
- self.download_manager
- .borrow()
- .install(package, &self.install_path)
+ Ok(Some(
+ self.download_manager
+ .borrow()
+ .install(package, &self.install_path)?,
+ ))
}
fn update(
diff --git a/crates/shirabe/src/installer/suggested_packages_reporter.rs b/crates/shirabe/src/installer/suggested_packages_reporter.rs
index c820009..8248f5f 100644
--- a/crates/shirabe/src/installer/suggested_packages_reporter.rs
+++ b/crates/shirabe/src/installer/suggested_packages_reporter.rs
@@ -196,5 +196,6 @@ impl SuggestedPackagesReporter {
fn remove_control_characters(&self, string: &str) -> String {
Preg::replace("/[[:cntrl:]]/", "", &string.replace('\n', " "))
+ .unwrap_or_else(|_| string.replace('\n', " "))
}
}