diff --git a/coffee_cmd/src/coffee_term/command_show.rs b/coffee_cmd/src/coffee_term/command_show.rs index 819635ca..f3a09399 100644 --- a/coffee_cmd/src/coffee_term/command_show.rs +++ b/coffee_cmd/src/coffee_term/command_show.rs @@ -102,10 +102,14 @@ pub fn show_nurse_result( NurseStatus::RepositoryLocallyRemoved(_) => { "Removed from local storage".to_string() } + NurseStatus::MovingGlobalRepostoryTo(_) => { + format!("Moving Global repository directory") + } }; let repos_str = match status { NurseStatus::RepositoryLocallyRestored(repos) | NurseStatus::RepositoryLocallyRemoved(repos) => repos.join(", "), + NurseStatus::MovingGlobalRepostoryTo(network) => network.to_owned(), }; table.push([ diff --git a/coffee_core/src/coffee.rs b/coffee_core/src/coffee.rs index c60244de..3a55c782 100644 --- a/coffee_core/src/coffee.rs +++ b/coffee_core/src/coffee.rs @@ -1,8 +1,8 @@ //! Coffee mod implementation use std::collections::HashMap; use std::fmt::Debug; +use std::path::Path; use std::vec::Vec; -use tokio::fs; use async_trait::async_trait; use clightningrpc_common::client::Client; @@ -12,6 +12,7 @@ use log; use serde::de::DeserializeOwned; use serde::{Deserialize, Serialize}; use serde_json::json; +use tokio::fs; use tokio::process::Command; use coffee_github::repository::Github; @@ -20,6 +21,7 @@ use coffee_lib::plugin_manager::PluginManager; use coffee_lib::repository::Repository; use coffee_lib::types::response::*; use coffee_lib::url::URL; +use coffee_lib::utils::move_dir_if_exist; use coffee_lib::{commit_id, error, get_repo_info, sh}; use coffee_storage::model::repository::{Kind, Repository as RepositoryInfo}; use coffee_storage::nosql_db::NoSQlStorage; @@ -497,6 +499,16 @@ impl PluginManager for CoffeeManager { let mut actions = self.patch_repository_locally_absent(repos.to_vec()).await?; nurse_actions.append(&mut actions); } + Defect::CoffeeGlobalrepoCleanup(networks) => { + for (network, path) in networks { + let global_repo = format!("{}/repositories", self.config.root_path); + if !Path::exists(&Path::new(&path)) { + move_dir_if_exist(&global_repo, &path).await?; + } + nurse_actions + .push(NurseStatus::MovingGlobalRepostoryTo(network.to_owned())); + } + } } } let mut nurse = CoffeeNurse { diff --git a/coffee_core/src/config.rs b/coffee_core/src/config.rs index bd43eb1e..78f76944 100644 --- a/coffee_core/src/config.rs +++ b/coffee_core/src/config.rs @@ -66,7 +66,9 @@ impl CoffeeConf { 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?; let repo_dir = format!("{def_path}/{}/repositories", coffee.network); + // older version of coffee has a repository inside the directory move_dir_if_exist(&format!("{def_path}/repositories"), &repo_dir).await?; + // FIXME: nurse should clean up the `{def_path}/repositories`. check_dir_or_make_if_missing(repo_dir).await?; // after we know all the information regarding // the configuration we try to see if there is diff --git a/coffee_core/src/nurse/chain.rs b/coffee_core/src/nurse/chain.rs index 921d3820..24437720 100644 --- a/coffee_core/src/nurse/chain.rs +++ b/coffee_core/src/nurse/chain.rs @@ -33,7 +33,7 @@ use async_trait::async_trait; use coffee_lib::errors::CoffeeError; use coffee_lib::types::response::{ChainOfResponsibilityStatus, Defect}; -use super::strategy::GitRepositoryLocallyAbsentStrategy; +use super::strategy::{CoffeeRepositoryDirCleanUp, GitRepositoryLocallyAbsentStrategy}; use crate::coffee::CoffeeManager; #[async_trait] @@ -52,7 +52,10 @@ impl RecoveryChainOfResponsibility { /// Create a new instance of the chain of responsibility pub async fn new() -> Result { Ok(Self { - handlers: vec![Arc::new(GitRepositoryLocallyAbsentStrategy)], + handlers: vec![ + Arc::new(GitRepositoryLocallyAbsentStrategy), + Arc::new(CoffeeRepositoryDirCleanUp), + ], }) } diff --git a/coffee_core/src/nurse/strategy.rs b/coffee_core/src/nurse/strategy.rs index a1e85d4d..2c12b66d 100644 --- a/coffee_core/src/nurse/strategy.rs +++ b/coffee_core/src/nurse/strategy.rs @@ -74,3 +74,28 @@ impl Handler for GitRepositoryLocallyAbsentStrategy { } } } + +pub struct CoffeeRepositoryDirCleanUp; + +#[async_trait] +impl Handler for CoffeeRepositoryDirCleanUp { + async fn can_be_applied( + self: Arc, + coffee: &CoffeeManager, + ) -> Result, CoffeeError> { + let networks = ["testnet", "signet", "bitcoin", "liquid"]; + // check if the repository subdirectory has the repository directory + // inside the subdirectory. + let mut directory_moving = vec![]; + for network in networks { + let subpath_repo = format!("{}/{network}/repositories", coffee.config.root_path); + if !Path::exists(&Path::new(&subpath_repo)) { + directory_moving.push((network.to_string(), subpath_repo)); + } + } + if directory_moving.is_empty() { + return Ok(None); + } + Ok(Some(Defect::CoffeeGlobalrepoCleanup(directory_moving))) + } +} diff --git a/coffee_lib/src/types/mod.rs b/coffee_lib/src/types/mod.rs index 794dc53a..87faa23e 100644 --- a/coffee_lib/src/types/mod.rs +++ b/coffee_lib/src/types/mod.rs @@ -138,6 +138,7 @@ pub mod response { // A patch operation when a git repository is present in the coffee configuration // but is absent from the local storage. RepositoryLocallyAbsent(Vec), + CoffeeGlobalrepoCleanup(Vec<(String, String)>), // TODO: Add more patch operations } @@ -166,6 +167,16 @@ pub mod response { write!(f, " {}", repo)?; } } + Defect::CoffeeGlobalrepoCleanup(networks) => { + writeln!( + f, + "Global repository migration completed for the networks: {}", + networks + .iter() + .map(|(network, _)| network.to_owned()) + .collect::() + )?; + } } } Ok(()) @@ -180,6 +191,7 @@ pub mod response { pub enum NurseStatus { RepositoryLocallyRestored(Vec), RepositoryLocallyRemoved(Vec), + MovingGlobalRepostoryTo(String), } #[derive(Clone, Debug, Serialize, Deserialize)] @@ -206,6 +218,7 @@ pub mod response { NurseStatus::RepositoryLocallyRestored(repos) => { repositories_locally_restored.append(&mut repos.clone()) } + NurseStatus::MovingGlobalRepostoryTo(_) => {} } } if !repositories_locally_removed.is_empty() { @@ -231,6 +244,12 @@ pub mod response { NurseStatus::RepositoryLocallyRemoved(val) => { write!(f, "Repositories removed locally: {}", val.join(" ")) } + NurseStatus::MovingGlobalRepostoryTo(net) => { + write!( + f, + "Global repository directory moved to subdirectory for network `{net}`" + ) + } } } }