Skip to content

Commit 2a1fa61

Browse files
core: fixing the nurse run command
Signed-off-by: Vincenzo Palazzo <[email protected]>
1 parent b1d3a6a commit 2a1fa61

File tree

12 files changed

+136
-67
lines changed

12 files changed

+136
-67
lines changed

coffee_cmd/src/coffee_term/command_show.rs

+50-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,10 @@ use term::Element;
77

88
use coffee_lib::error;
99
use coffee_lib::errors::CoffeeError;
10-
use coffee_lib::types::response::{CoffeeList, CoffeeNurse, CoffeeRemote, CoffeeTip, NurseStatus};
10+
use coffee_lib::types::response::{
11+
ChainOfResponsibilityStatus, CoffeeList, CoffeeNurse, CoffeeRemote, CoffeeTip, Defect,
12+
NurseStatus,
13+
};
1114

1215
pub fn show_list(coffee_list: Result<CoffeeList, CoffeeError>) -> Result<(), CoffeeError> {
1316
let remotes = coffee_list?;
@@ -86,6 +89,52 @@ pub fn show_remote_list(remote_list: Result<CoffeeRemote, CoffeeError>) -> Resul
8689
Ok(())
8790
}
8891

92+
pub fn show_nurse_verify(nurse_verify: &ChainOfResponsibilityStatus) -> Result<(), CoffeeError> {
93+
if nurse_verify.defects.is_empty() {
94+
term::success!("Coffee configuration is not corrupt! No need to run coffee nurse");
95+
} else {
96+
let mut table = radicle_term::Table::new(TableOptions::bordered());
97+
table.push([
98+
term::format::dim(String::from("●")),
99+
term::format::bold(String::from("Defects")),
100+
term::format::bold(String::from("Affected repositories")),
101+
]);
102+
table.divider();
103+
104+
for defect in nurse_verify.defects.iter() {
105+
match defect {
106+
Defect::RepositoryLocallyAbsent(repos) => {
107+
let defect = "Repository missing locally";
108+
for repo in repos {
109+
table.push([
110+
term::format::positive("●").into(),
111+
term::format::bold(defect.to_owned()),
112+
term::format::highlight(repo.clone()),
113+
]);
114+
}
115+
}
116+
Defect::CoffeeGlobalrepoCleanup(networks) => {
117+
let defect = format!(
118+
"Global repository migration completed for the networks: {}",
119+
networks
120+
.iter()
121+
.map(|(network, _)| format!("{network} "))
122+
.collect::<String>()
123+
.trim_end()
124+
);
125+
table.push([
126+
term::format::positive("●").into(),
127+
term::format::bold(defect.to_owned()),
128+
term::format::highlight("_".to_owned()),
129+
]);
130+
}
131+
}
132+
}
133+
table.print();
134+
}
135+
Ok(())
136+
}
137+
89138
pub fn show_nurse_result(
90139
nurse_result: Result<CoffeeNurse, CoffeeError>,
91140
) -> Result<(), CoffeeError> {

coffee_cmd/src/main.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -160,9 +160,9 @@ async fn run(args: CoffeeArgs, mut coffee: CoffeeManager) -> Result<(), CoffeeEr
160160
CoffeeCommand::Nurse { verify } => {
161161
if verify {
162162
let result = coffee.nurse_verify().await?;
163-
term::info!("{}", result);
163+
coffee_term::show_nurse_verify(&result)?;
164164
if !result.is_sane() {
165-
term::info!("Coffee local directory is damaged, please run `coffee nurse` to try to fix it");
165+
term::warning(term::style("Coffee local directory is damaged, please run `coffee nurse` to try to fix it").bold());
166166
}
167167
} else {
168168
let nurse_result = coffee.nurse().await;

coffee_core/src/coffee.rs

+11-10
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ use coffee_lib::plugin_manager::PluginManager;
2121
use coffee_lib::repository::Repository;
2222
use coffee_lib::types::response::*;
2323
use coffee_lib::url::URL;
24-
use coffee_lib::utils::{copy_dir_if_exist, rm_dir_if_exist};
24+
use coffee_lib::utils::{check_dir_or_make_if_missing, copy_dir_if_exist, rm_dir_if_exist};
2525
use coffee_lib::{commit_id, error, get_repo_info, sh};
2626
use coffee_storage::model::repository::{Kind, Repository as RepositoryInfo};
2727
use coffee_storage::nosql_db::NoSQlStorage;
@@ -80,8 +80,8 @@ pub struct CoffeeManager {
8080
}
8181

8282
impl CoffeeManager {
83-
pub async fn new(conf: &dyn CoffeeArgs) -> Result<Self, CoffeeError> {
84-
let conf = CoffeeConf::new(conf).await?;
83+
pub async fn new(conf_args: &dyn CoffeeArgs) -> Result<Self, CoffeeError> {
84+
let conf = CoffeeConf::new(conf_args).await?;
8585
let mut coffee = CoffeeManager {
8686
config: conf.clone(),
8787
coffee_cln_config: CLNConf::new(conf.config_path, true),
@@ -98,6 +98,7 @@ impl CoffeeManager {
9898
/// when coffee is configured, run an inventory to collect all the necessary information
9999
/// about the coffee ecosystem.
100100
async fn inventory(&mut self) -> Result<(), CoffeeError> {
101+
let skip_verify = self.config.skip_verify;
101102
let _ = self
102103
.storage
103104
.load::<CoffeeStorageInfo>(&self.config.network)
@@ -123,7 +124,7 @@ impl CoffeeManager {
123124
if let Err(err) = self.coffee_cln_config.parse() {
124125
log::error!("{}", err.cause);
125126
}
126-
if !self.config.skip_verify {
127+
if !skip_verify {
127128
// Check for the chain of responsibility
128129
let status = self.recovery_strategies.scan(self).await?;
129130
log::debug!("Chain of responsibility status: {:?}", status);
@@ -427,15 +428,10 @@ impl PluginManager for CoffeeManager {
427428
}
428429

429430
async fn add_remote(&mut self, name: &str, url: &str) -> Result<(), CoffeeError> {
430-
// FIXME: we should allow some error here like
431-
// for the add remote command the no found error for the `repository`
432-
// directory is fine.
433-
434431
if self.repos.contains_key(name) {
435432
return Err(error!("repository with name: {name} already exists"));
436433
}
437-
let local_path = format!("{}/{}", self.config.root_path, self.config.network);
438-
let url = URL::new(&local_path, url, name);
434+
let url = URL::new(&self.config.path(), url, name);
439435
log::debug!("remote adding: {} {}", name, &url.url_string);
440436
let mut repo = Github::new(name, &url);
441437
repo.init().await?;
@@ -551,6 +547,8 @@ impl PluginManager for CoffeeManager {
551547
Defect::CoffeeGlobalrepoCleanup(networks) => {
552548
let global_repo = format!("{}/repositories", self.config.root_path);
553549
for (network, path) in networks {
550+
log::info!("{network} - {path}");
551+
check_dir_or_make_if_missing(path.to_owned()).await?;
554552
if !Path::exists(Path::new(&path)) {
555553
copy_dir_if_exist(&global_repo, path).await?;
556554
}
@@ -565,6 +563,8 @@ impl PluginManager for CoffeeManager {
565563
status: nurse_actions,
566564
};
567565
nurse.organize();
566+
// Refesh the status
567+
self.flush().await?;
568568
Ok(nurse)
569569
}
570570

@@ -587,6 +587,7 @@ impl PluginManager for CoffeeManager {
587587
.get_mut(repo_name)
588588
.ok_or_else(|| error!("repository with name: {repo_name} not found"))?;
589589

590+
repo.change_root_path(&self.config.path());
590591
match repo.recover().await {
591592
Ok(_) => {
592593
log::info!("repository {} recovered", repo_name.clone());

coffee_core/src/config.rs

+17-18
Original file line numberDiff line numberDiff line change
@@ -1,37 +1,40 @@
11
//! Coffee configuration utils.
2-
use log::info;
3-
use serde::{Deserialize, Serialize};
42
use std::env;
53

6-
use crate::CoffeeOperation;
7-
use coffee_lib::utils::{check_dir_or_make_if_missing, copy_dir_if_exist};
4+
use serde::{Deserialize, Serialize};
5+
6+
use coffee_lib::utils::check_dir_or_make_if_missing;
87
use coffee_lib::{errors::CoffeeError, plugin::Plugin};
98

109
use crate::CoffeeArgs;
10+
use crate::CoffeeOperation;
11+
1112
/// Custom coffee configuration, given by a command line list of arguments
1213
/// or a coffee configuration file.
1314
#[derive(Clone, Debug, Serialize, Deserialize)]
1415
pub struct CoffeeConf {
1516
/// Network configuration related
1617
/// to core lightning network
1718
pub network: String,
19+
/// root path plugin manager
20+
pub root_path: String,
1821
/// path of core lightning configuration file
1922
/// managed by coffee
2023
pub config_path: String,
2124
/// path of the core lightning configuration file
2225
/// not managed by core lightning
23-
/// (this file included the file managed by coffee)
26+
///
27+
/// This file included the file managed by coffee
2428
pub cln_config_path: Option<String>,
2529
/// root cln directory path
2630
pub cln_root: Option<String>,
27-
/// root path plugin manager
28-
pub root_path: String,
2931
/// all plugins that are installed
3032
/// with the plugin manager.
3133
pub plugins: Vec<Plugin>,
3234
/// A flag that indicates if the
3335
/// user wants to skip the verification
3436
/// of nurse.
37+
#[serde(skip)]
3538
pub skip_verify: bool,
3639
}
3740

@@ -47,7 +50,7 @@ impl CoffeeConf {
4750
def_path = def_path.strip_suffix('/').unwrap_or(&def_path).to_string();
4851
def_path += "/.coffee";
4952
check_dir_or_make_if_missing(def_path.to_string()).await?;
50-
info!("creating coffee home at {def_path}");
53+
log::info!("creating coffee home at {def_path}");
5154

5255
let mut coffee = CoffeeConf {
5356
network: "bitcoin".to_owned(),
@@ -62,14 +65,8 @@ impl CoffeeConf {
6265
// check the command line arguments and bind them
6366
// inside the coffee conf
6467
coffee.bind_cmd_line_params(conf)?;
65-
6668
check_dir_or_make_if_missing(format!("{def_path}/{}", coffee.network)).await?;
6769
check_dir_or_make_if_missing(format!("{def_path}/{}/plugins", coffee.network)).await?;
68-
let repo_dir = format!("{def_path}/{}/repositories", coffee.network);
69-
// older version of coffee has a repository inside the directory
70-
copy_dir_if_exist(&format!("{def_path}/repositories"), &repo_dir).await?;
71-
// FIXME: nurse should clean up the `{def_path}/repositories`.
72-
check_dir_or_make_if_missing(repo_dir).await?;
7370
// after we know all the information regarding
7471
// the configuration we try to see if there is
7572
// something stored already to the disk.
@@ -105,10 +102,12 @@ impl CoffeeConf {
105102
}
106103
}
107104
}
108-
109-
// FIXME: be able to put the directory also in another place!
110-
// for now it is fixed in the Home/.coffee but another good place
111-
// will be, the .lightning dir
112105
Ok(())
113106
}
107+
108+
/// Return the root path of the coffee manager instance
109+
/// this include also the network path.
110+
pub fn path(&self) -> String {
111+
format!("{}/{}", self.root_path, self.network)
112+
}
114113
}

coffee_core/src/nurse/chain.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -53,8 +53,8 @@ impl RecoveryChainOfResponsibility {
5353
pub async fn new() -> Result<Self, CoffeeError> {
5454
Ok(Self {
5555
handlers: vec![
56-
Arc::new(GitRepositoryLocallyAbsentStrategy),
5756
Arc::new(CoffeeRepositoryDirCleanUp),
57+
Arc::new(GitRepositoryLocallyAbsentStrategy),
5858
],
5959
})
6060
}

coffee_core/src/nurse/strategy.rs

+5
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,11 @@ impl Handler for CoffeeRepositoryDirCleanUp {
9494
// Check whether there exists a network-specific repositories folder for each network.
9595
let mut directory_moving = vec![];
9696
for network in networks {
97+
let network_dir = format!("{}/{network}", coffee.config.root_path);
98+
if !Path::exists(Path::new(&network_dir)) {
99+
log::debug!("network dir `{network_dir}` not found");
100+
continue;
101+
}
97102
let subpath_repo = format!("{}/{network}/repositories", coffee.config.root_path);
98103
if !Path::exists(Path::new(&subpath_repo)) {
99104
directory_moving.push((network.to_string(), subpath_repo));

coffee_github/src/repository.rs

+4
Original file line numberDiff line numberDiff line change
@@ -233,6 +233,10 @@ impl Repository for Github {
233233
}
234234
}
235235

236+
fn change_root_path(&mut self, path: &str) {
237+
self.url.set_coffee_path(path);
238+
}
239+
236240
async fn upgrade(
237241
&mut self,
238242
plugins: &Vec<Plugin>,

coffee_lib/src/repository.rs

+5
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,11 @@ pub trait Repository: Any {
3434
/// recover the repository from the commit id.
3535
async fn recover(&mut self) -> Result<(), CoffeeError>;
3636

37+
/// While migrating there is a possibility that we should
38+
/// move an old repository into a new path. So this
39+
/// is semplyfing this process.
40+
fn change_root_path(&mut self, path: &str);
41+
3742
/// return the name of the repository.
3843
fn name(&self) -> String;
3944

coffee_lib/src/types/mod.rs

+3-32
Original file line numberDiff line numberDiff line change
@@ -166,37 +166,6 @@ pub mod response {
166166
}
167167
}
168168

169-
impl fmt::Display for ChainOfResponsibilityStatus {
170-
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
171-
if self.defects.is_empty() {
172-
write!(f, "Coffee is sane")
173-
} else {
174-
writeln!(f, "Coffee has the following defects:")?;
175-
for (i, defect) in self.defects.iter().enumerate() {
176-
match defect {
177-
Defect::RepositoryLocallyAbsent(repos) => {
178-
write!(f, "{}. Repository missing locally: ", i + 1)?;
179-
for repo in repos {
180-
write!(f, " {}", repo)?;
181-
}
182-
}
183-
Defect::CoffeeGlobalrepoCleanup(networks) => {
184-
writeln!(
185-
f,
186-
"Global repository migration completed for the networks: {}",
187-
networks
188-
.iter()
189-
.map(|(network, _)| network.to_owned())
190-
.collect::<String>()
191-
)?;
192-
}
193-
}
194-
}
195-
Ok(())
196-
}
197-
}
198-
}
199-
200169
/// This struct is used to represent the status of nurse,
201170
/// either sane or not.
202171
/// If not sane, return the action that nurse has taken.
@@ -231,7 +200,9 @@ pub mod response {
231200
NurseStatus::RepositoryLocallyRestored(repos) => {
232201
repositories_locally_restored.append(&mut repos.clone())
233202
}
234-
NurseStatus::MovingGlobalRepostoryTo(_) => {}
203+
NurseStatus::MovingGlobalRepostoryTo(status) => {
204+
new_status.push(NurseStatus::MovingGlobalRepostoryTo(status.to_owned()));
205+
}
235206
}
236207
}
237208
if !repositories_locally_removed.is_empty() {

coffee_lib/src/url.rs

+4
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,10 @@ impl URL {
5656
repo_name: get_repo_name_from_url(url),
5757
}
5858
}
59+
60+
pub fn set_coffee_path(&mut self, path: &str) {
61+
self.path_string = format!("{path}/{}", self.repo_name);
62+
}
5963
}
6064

6165
impl fmt::Display for URL {

0 commit comments

Comments
 (0)