From 0c7f7e31513efa0ba63ce957ebb9d046a0875e4c Mon Sep 17 00:00:00 2001 From: Tarek Date: Sat, 29 Jul 2023 07:15:01 +0300 Subject: [PATCH] feat(core): install plugins in a separate directory This commit: 1- modifies the install method to copy the plugin folder to ~/.coffee//plugins/ 2- modifies the remove method to remove the plugin folder when uninstalling This also allows for future enhancements to the upgrade method Signed-off-by: Tarek --- Cargo.lock | 7 +++ coffee_core/Cargo.toml | 1 + coffee_core/src/coffee.rs | 76 ++++++++++++++++++++++++--------- coffee_core/src/config.rs | 1 + coffee_github/src/repository.rs | 2 + 5 files changed, 68 insertions(+), 19 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 431d3738..cc795bc5 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -637,6 +637,7 @@ dependencies = [ "coffee_lib", "coffee_storage", "env_logger", + "fs_extra", "log", "serde", "serde_json", @@ -1052,6 +1053,12 @@ dependencies = [ "winapi", ] +[[package]] +name = "fs_extra" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42703706b716c37f96a77aea830392ad231f44c9e9a67872fa5548707e11b11c" + [[package]] name = "futures" version = "0.3.28" diff --git a/coffee_core/Cargo.toml b/coffee_core/Cargo.toml index af477514..3556bdbb 100644 --- a/coffee_core/Cargo.toml +++ b/coffee_core/Cargo.toml @@ -6,6 +6,7 @@ edition = "2021" [dependencies] tokio = { version = "1.22.0", features = ["full"] } +fs_extra = "1.3.0" async-trait = "0.1.57" coffee_lib = { path = "../coffee_lib" } coffee_github = { path = "../coffee_github" } diff --git a/coffee_core/src/coffee.rs b/coffee_core/src/coffee.rs index 1eccc522..fb31410d 100644 --- a/coffee_core/src/coffee.rs +++ b/coffee_core/src/coffee.rs @@ -1,5 +1,6 @@ //! Coffee mod implementation use coffee_storage::nosql_db::NoSQlStorage; +use fs_extra::dir; use std::collections::HashMap; use std::fmt::Debug; use std::vec::Vec; @@ -223,27 +224,61 @@ impl PluginManager for CoffeeManager { for repo in self.repos.values() { if let Some(mut plugin) = repo.get_plugin_by_name(plugin) { log::trace!("{:#?}", plugin); - let result = plugin.configure(verbose).await; - log::debug!("result from plugin configure: {:?}", result); - match result { - Ok(path) => { - log::debug!("runnable plugin path {path}"); - if !try_dynamic { - self.config.plugins.push(plugin); - log::debug!("path coffee conf: {}", self.coffee_cln_config.path); - self.coffee_cln_config - .add_conf("plugin", &path.to_owned()) - .map_err(|err| CoffeeError::new(1, &err.cause))?; - log::debug!("coffee conf updated: {}", self.coffee_cln_config); - self.flush().await?; - self.update_conf().await?; - } else { - self.start_plugin(&path).await?; + + // old_root_path is the path where the plugin is cloned and currently stored + // eg. ~/.coffee/repositories// + let old_root_path = plugin.root_path.clone(); + // new_root_path is the path where the plugin will be installed specific to the network + // eg. ~/.coffee//plugins/ + let new_root_path = format!( + "{}/{}/plugins/{}", + self.config.root_path, + self.config.network, + plugin.name() + ); + dir::copy( + &old_root_path, + format!("{}/{}/plugins/", self.config.root_path, self.config.network), + &dir::CopyOptions::new(), + ) + .map_err(|err| error!("{}", err.to_string()))?; + + let old_exec_path = plugin.exec_path.clone(); + + match old_exec_path.strip_prefix(&old_root_path) { + Some(relative_path) => { + let new_exec_path = format!("{}{}", new_root_path, relative_path); + plugin.root_path = new_root_path; + plugin.exec_path = new_exec_path; + + log::debug!("plugin: {:?}", plugin); + let result = plugin.configure(verbose).await; + log::debug!("result from plugin configure: {:?}", result); + match result { + Ok(path) => { + log::debug!("runnable plugin path {path}"); + if !try_dynamic { + self.config.plugins.push(plugin); + log::debug!( + "path coffee conf: {}", + self.coffee_cln_config.path + ); + self.coffee_cln_config + .add_conf("plugin", &path.to_owned()) + .map_err(|err| CoffeeError::new(1, &err.cause))?; + log::debug!("coffee conf updated: {}", self.coffee_cln_config); + self.flush().await?; + self.update_conf().await?; + } else { + self.start_plugin(&path).await?; + } + return Ok(()); + } + Err(err) => return Err(err), } - return Ok(()); } - Err(err) => return Err(err), - } + None => return Err(error!("exec path not found")), + }; } } Err(error!( @@ -257,6 +292,7 @@ impl PluginManager for CoffeeManager { if let Some(index) = plugins.iter().position(|x| x.name() == plugin) { let plugin = plugins[index].clone(); let exec_path = plugin.exec_path.clone(); + fs::remove_dir_all(plugin.root_path.clone()).await?; log::debug!("runnable plugin path: {exec_path}"); plugins.remove(index); log::debug!("coffee cln config: {}", self.coffee_cln_config); @@ -278,6 +314,8 @@ impl PluginManager for CoffeeManager { } async fn upgrade(&mut self, repo: &str) -> Result { + // TODO: upgrade should now be able to upgrade a single plugin + // without affecting other plugins installed from the same repo let repository = self .repos .get(repo) diff --git a/coffee_core/src/config.rs b/coffee_core/src/config.rs index f908ac3b..81d479a7 100644 --- a/coffee_core/src/config.rs +++ b/coffee_core/src/config.rs @@ -58,6 +58,7 @@ impl CoffeeConf { coffee.bind_cmd_line_params(conf)?; check_dir_or_make_if_missing(format!("{def_path}/{}", coffee.network)).await?; + check_dir_or_make_if_missing(format!("{def_path}/{}/plugins", coffee.network)).await?; check_dir_or_make_if_missing(format!("{def_path}/repositories")).await?; // after we know all the information regarding // the configuration we try to see if there is diff --git a/coffee_github/src/repository.rs b/coffee_github/src/repository.rs index c613fd59..3d8fb77d 100644 --- a/coffee_github/src/repository.rs +++ b/coffee_github/src/repository.rs @@ -228,6 +228,8 @@ impl Repository for Github { let mut plugins_effected: Vec = vec![]; let remote_repo = self.list().await?; + // FIXME: upgrading the repository must also upgrade the commit + // field of all plugins cloned from this repository. let plugins = plugins.clone(); // FIXME: mark inside a repository what plugin is installed, and remove