aboutsummaryrefslogtreecommitdiffhomepage
path: root/crates/shirabe/src/installer/installation_manager.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/shirabe/src/installer/installation_manager.rs')
-rw-r--r--crates/shirabe/src/installer/installation_manager.rs196
1 files changed, 67 insertions, 129 deletions
diff --git a/crates/shirabe/src/installer/installation_manager.rs b/crates/shirabe/src/installer/installation_manager.rs
index 2d60997c..4eb905ed 100644
--- a/crates/shirabe/src/installer/installation_manager.rs
+++ b/crates/shirabe/src/installer/installation_manager.rs
@@ -1,9 +1,9 @@
//! ref: composer/src/Composer/Installer/InstallationManager.php
+use crate::dependency_resolver::operation::AnyOperation;
use crate::dependency_resolver::operation::InstallOperation;
use crate::dependency_resolver::operation::MarkAliasInstalledOperation;
use crate::dependency_resolver::operation::MarkAliasUninstalledOperation;
-use crate::dependency_resolver::operation::OperationInterface;
use crate::dependency_resolver::operation::UninstallOperation;
use crate::dependency_resolver::operation::UpdateOperation;
use crate::downloader::FileDownloader;
@@ -240,7 +240,7 @@ impl InstallationManager {
pub fn execute(
&mut self,
repo: &mut dyn InstalledRepositoryInterface,
- operations: Vec<std::rc::Rc<dyn OperationInterface>>,
+ operations: Vec<AnyOperation>,
dev_mode: bool,
run_scripts: bool,
download_only: bool,
@@ -253,18 +253,16 @@ impl InstallationManager {
let _ = (dev_mode, run_scripts, download_only);
for operation in operations {
let trace = shirabe_php_shim::strip_tags(&operation.to_string());
- match operation.get_operation_type().as_str() {
- "install" => {
- let op = operation.as_install_operation().expect("install operation");
+ match operation {
+ AnyOperation::Install(op) => {
let package = op.get_package();
mock.installed.push(package.clone());
mock.trace.push(trace);
repo.add_package(PackageInterfaceHandle::dup(&package));
}
- "update" => {
- let op = operation.as_update_operation().expect("update operation");
- let initial = op.get_initial_package().clone();
- let target = op.get_target_package().clone();
+ AnyOperation::Update(op) => {
+ let initial = op.get_initial_package();
+ let target = op.get_target_package();
mock.updated.push((initial.clone(), target.clone()));
mock.trace.push(trace);
repo.remove_package(initial);
@@ -272,38 +270,26 @@ impl InstallationManager {
repo.add_package(PackageInterfaceHandle::dup(&target));
}
}
- "uninstall" => {
- let op = operation
- .as_uninstall_operation()
- .expect("uninstall operation");
+ AnyOperation::Uninstall(op) => {
let package = op.get_package();
mock.uninstalled.push(package.clone());
mock.trace.push(trace);
repo.remove_package(package);
}
- "markAliasInstalled" => {
- let op = operation
- .as_any()
- .downcast_ref::<MarkAliasInstalledOperation>()
- .expect("markAliasInstalled operation");
- let package = op.get_package();
- mock.installed.push(package.clone().into());
+ AnyOperation::MarkAliasInstalled(op) => {
+ let package: PackageInterfaceHandle = op.get_package().into();
+ mock.installed.push(package.clone());
mock.trace.push(trace);
- if !repo.has_package(package.clone().into()) {
- repo.add_package(PackageInterfaceHandle::dup(&package.into()));
+ if !repo.has_package(package.clone()) {
+ repo.add_package(PackageInterfaceHandle::dup(&package));
}
}
- "markAliasUninstalled" => {
- let op = operation
- .as_any()
- .downcast_ref::<MarkAliasUninstalledOperation>()
- .expect("markAliasUninstalled operation");
- let package = op.get_package();
- mock.uninstalled.push(package.clone().into());
+ AnyOperation::MarkAliasUninstalled(op) => {
+ let package: PackageInterfaceHandle = op.get_package().into();
+ mock.uninstalled.push(package.clone());
mock.trace.push(trace);
- repo.remove_package(package.into());
+ repo.remove_package(package);
}
- other => panic!("unknown operation type: {}", other),
}
}
return Ok(());
@@ -333,7 +319,7 @@ impl InstallationManager {
}),
);
- let all_operations: Vec<std::rc::Rc<dyn OperationInterface>> = operations.clone();
+ let all_operations: Vec<AnyOperation> = operations.clone();
// The concurrent operation chains share the repository; each chain borrows it only in
// synchronous sections, never across an await.
@@ -343,18 +329,15 @@ impl InstallationManager {
let result: anyhow::Result<()> = (|| -> anyhow::Result<()> {
// execute operations in batches to make sure download-modifying-plugins are installed
// before the other packages get downloaded
- let mut batches: Vec<IndexMap<i64, std::rc::Rc<dyn OperationInterface>>> = vec![];
- let mut batch: IndexMap<i64, std::rc::Rc<dyn OperationInterface>> = IndexMap::new();
+ let mut batches: Vec<IndexMap<i64, AnyOperation>> = vec![];
+ let mut batch: IndexMap<i64, AnyOperation> = IndexMap::new();
for (index, operation) in operations.into_iter().enumerate() {
let index = index as i64;
- let package: Option<PackageInterfaceHandle> =
- if let Some(update) = operation.as_update_operation() {
- Some(update.get_target_package())
- } else {
- operation
- .as_install_operation()
- .map(|install| install.get_package())
- };
+ let package: Option<PackageInterfaceHandle> = match &operation {
+ AnyOperation::Update(update) => Some(update.get_target_package()),
+ AnyOperation::Install(install) => Some(install.get_package()),
+ _ => None,
+ };
if let Some(package) = package
&& package.get_type() == "composer-plugin"
{
@@ -423,7 +406,7 @@ impl InstallationManager {
async fn download_and_execute_batch(
&self,
repo: &std::cell::RefCell<&mut dyn InstalledRepositoryInterface>,
- operations: IndexMap<i64, std::rc::Rc<dyn OperationInterface>>,
+ operations: IndexMap<i64, AnyOperation>,
cleanup_promises: &mut IndexMap<
i64,
Box<
@@ -435,7 +418,7 @@ impl InstallationManager {
dev_mode: bool,
run_scripts: bool,
download_only: bool,
- all_operations: Vec<std::rc::Rc<dyn OperationInterface>>,
+ all_operations: Vec<AnyOperation>,
) -> anyhow::Result<()> {
let mut promises: Vec<
std::pin::Pin<Box<dyn std::future::Future<Output = anyhow::Result<()>>>>,
@@ -445,24 +428,15 @@ impl InstallationManager {
let op_type = operation.get_operation_type();
// ignoring alias ops as they don't need to execute anything at this stage
- if !["update", "install", "uninstall"].contains(&op_type.as_str()) {
+ if !["update", "install", "uninstall"].contains(&op_type) {
continue;
}
- let package: PackageInterfaceHandle;
- let initial_package: Option<PackageInterfaceHandle>;
- if op_type == "update" {
- // @var UpdateOperation $operation
- let update_op = operation
- .as_update_operation()
- .expect("op_type == \"update\" implies UpdateOperation");
- package = update_op.get_target_package();
- initial_package = Some(update_op.get_initial_package());
- } else {
- // @var InstallOperation|MarkAliasInstalledOperation|MarkAliasUninstalledOperation|UninstallOperation $operation
- package = operation.get_package();
- initial_package = None;
- }
+ let package = operation.get_target_package();
+ let initial_package: Option<PackageInterfaceHandle> = match operation {
+ AnyOperation::Update(update_op) => Some(update_op.get_initial_package()),
+ _ => None,
+ };
let installer = self.get_installer(&package.get_type())?;
// PHP: $cleanupPromises[$index] = static function () use ($opType, $installer, $package, $initialPackage) {
@@ -474,7 +448,6 @@ impl InstallationManager {
>,
> = {
let installer = installer.clone();
- let op_type = op_type.clone();
let package = package.clone();
let initial_package = initial_package.clone();
Box::new(move || {
@@ -488,14 +461,13 @@ impl InstallationManager {
}
let installer = installer.clone();
- let op_type = op_type.clone();
let package = package.clone();
let initial_package = initial_package.clone();
let fut: std::pin::Pin<
Box<dyn std::future::Future<Output = anyhow::Result<()>>>,
> = Box::pin(async move {
installer
- .cleanup(&op_type, package, initial_package)
+ .cleanup(op_type, package, initial_package)
.await
.map(|_| ())
});
@@ -530,17 +502,14 @@ impl InstallationManager {
// execute operations in batches to make sure every plugin is installed in the
// right order and activated before the packages depending on it are installed
- let mut batches: Vec<IndexMap<i64, std::rc::Rc<dyn OperationInterface>>> = vec![];
- let mut batch: IndexMap<i64, std::rc::Rc<dyn OperationInterface>> = IndexMap::new();
+ let mut batches: Vec<IndexMap<i64, AnyOperation>> = vec![];
+ let mut batch: IndexMap<i64, AnyOperation> = IndexMap::new();
for (index, operation) in operations {
- let package: Option<PackageInterfaceHandle> =
- if let Some(update) = operation.as_update_operation() {
- Some(update.get_target_package())
- } else {
- operation
- .as_install_operation()
- .map(|install| install.get_package())
- };
+ let package: Option<PackageInterfaceHandle> = match &operation {
+ AnyOperation::Update(update) => Some(update.get_target_package()),
+ AnyOperation::Install(install) => Some(install.get_package()),
+ _ => None,
+ };
if let Some(package) = package {
let pkg_type = package.get_type();
if pkg_type == "composer-plugin" || pkg_type == "composer-installer" {
@@ -579,7 +548,7 @@ impl InstallationManager {
async fn execute_batch(
&self,
repo: &std::cell::RefCell<&mut dyn InstalledRepositoryInterface>,
- operations: IndexMap<i64, std::rc::Rc<dyn OperationInterface>>,
+ operations: IndexMap<i64, AnyOperation>,
cleanup_promises: &IndexMap<
i64,
Box<
@@ -590,7 +559,7 @@ impl InstallationManager {
>,
dev_mode: bool,
run_scripts: bool,
- all_operations: &[std::rc::Rc<dyn OperationInterface>],
+ all_operations: &[AnyOperation],
) -> anyhow::Result<()> {
let mut promises: Vec<
std::pin::Pin<Box<dyn std::future::Future<Output = anyhow::Result<()>> + '_>>,
@@ -600,7 +569,7 @@ impl InstallationManager {
let op_type = operation.get_operation_type();
// ignoring alias ops as they don't need to execute anything
- if !["update", "install", "uninstall"].contains(&op_type.as_str()) {
+ if !["update", "install", "uninstall"].contains(&op_type) {
// output alias ops in debug verbosity as they have no output otherwise
if self.io.is_debug() {
self.io.write_error3(
@@ -609,23 +578,11 @@ impl InstallationManager {
io_interface::NORMAL,
);
}
- match op_type.as_str() {
- "markAliasInstalled" => {
- let op = operation
- .as_any()
- .downcast_ref::<MarkAliasInstalledOperation>()
- .expect(
- "op_type == \"markAliasInstalled\" implies MarkAliasInstalledOperation",
- );
+ match &operation {
+ AnyOperation::MarkAliasInstalled(op) => {
self.mark_alias_installed(&mut **repo.borrow_mut(), op);
}
- "markAliasUninstalled" => {
- let op = operation
- .as_any()
- .downcast_ref::<MarkAliasUninstalledOperation>()
- .expect(
- "op_type == \"markAliasUninstalled\" implies MarkAliasUninstalledOperation",
- );
+ AnyOperation::MarkAliasUninstalled(op) => {
self.mark_alias_uninstalled(&mut **repo.borrow_mut(), op);
}
_ => {}
@@ -634,20 +591,13 @@ impl InstallationManager {
continue;
}
- let package: PackageInterfaceHandle;
- let initial_package: Option<PackageInterfaceHandle>;
- if op_type == "update" {
- let update_op = operation
- .as_update_operation()
- .expect("op_type == \"update\" implies UpdateOperation");
- package = update_op.get_target_package();
- initial_package = Some(update_op.get_initial_package());
- } else {
- package = operation.get_package();
- initial_package = None;
- }
+ let package = operation.get_target_package();
+ let initial_package: Option<PackageInterfaceHandle> = match &operation {
+ AnyOperation::Update(update_op) => Some(update_op.get_initial_package()),
+ _ => None,
+ };
- let event_name = match op_type.as_str() {
+ let event_name = match op_type {
"install" => PackageEvents::PRE_PACKAGE_INSTALL,
"update" => PackageEvents::PRE_PACKAGE_UPDATE,
"uninstall" => PackageEvents::PRE_PACKAGE_UNINSTALL,
@@ -658,13 +608,7 @@ impl InstallationManager {
// TODO(phase-c): dispatch_package_event takes Box<dyn RepositoryInterface>/Vec<Box<...>>
// but we hold a RefCell'd &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 _ = (event_name, dev_mode, &repo, &all_operations, &operation);
}
let installer = self.get_installer(&package.get_type())?;
@@ -679,29 +623,23 @@ impl InstallationManager {
promises.push(Box::pin(async move {
let chain_result: anyhow::Result<()> = async {
installer
- .prepare(&op_type, package.clone(), initial_package.clone())
+ .prepare(op_type, package.clone(), initial_package.clone())
.await?;
- match op_type.as_str() {
- "install" => {
- let op = operation
- .as_install_operation()
- .expect("op_type == \"install\" implies InstallOperation");
+ match &operation {
+ AnyOperation::Install(op) => {
self.install(repo, op).await?;
}
- "update" => {
- let op = operation
- .as_update_operation()
- .expect("op_type == \"update\" implies UpdateOperation");
+ AnyOperation::Update(op) => {
self.update(repo, op).await?;
}
- "uninstall" => {
- let op = operation
- .as_uninstall_operation()
- .expect("op_type == \"uninstall\" implies UninstallOperation");
+ AnyOperation::Uninstall(op) => {
self.uninstall(repo, op).await?;
}
- _ => unreachable!("op_type is one of install/update/uninstall"),
+ AnyOperation::MarkAliasInstalled(_)
+ | AnyOperation::MarkAliasUninstalled(_) => {
+ unreachable!("alias operations were skipped above")
+ }
}
if let Some(cleanup) = cleanup_promises.get(&index)
@@ -718,7 +656,7 @@ impl InstallationManager {
if let Err(e) = chain_result {
self.io.write_error(&format!(
" <error>{} of {} failed</error>",
- shirabe_php_shim::ucfirst(&op_type),
+ shirabe_php_shim::ucfirst(op_type),
package.get_pretty_name()
));
return Err(e);
@@ -727,7 +665,7 @@ impl InstallationManager {
// PHP: ->then(fn() => $repo->write($devMode, $this)) persists the repository after each op.
repo.borrow_mut().write(dev_mode, self);
- let event_name_post = match op_type.as_str() {
+ let event_name_post = match op_type {
"install" => PackageEvents::POST_PACKAGE_INSTALL,
"update" => PackageEvents::POST_PACKAGE_UPDATE,
"uninstall" => PackageEvents::POST_PACKAGE_UNINSTALL,
@@ -1087,7 +1025,7 @@ pub trait InstallationManagerInterface: std::fmt::Debug {
fn execute(
&mut self,
repo: &mut dyn InstalledRepositoryInterface,
- operations: Vec<std::rc::Rc<dyn OperationInterface>>,
+ operations: Vec<AnyOperation>,
dev_mode: bool,
run_scripts: bool,
download_only: bool,
@@ -1129,7 +1067,7 @@ impl InstallationManagerInterface for InstallationManager {
fn execute(
&mut self,
repo: &mut dyn InstalledRepositoryInterface,
- operations: Vec<std::rc::Rc<dyn OperationInterface>>,
+ operations: Vec<AnyOperation>,
dev_mode: bool,
run_scripts: bool,
download_only: bool,