diff --git a/CHANGELOG.md b/CHANGELOG.md index eb04c107dcd1..b27659572c25 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -37,6 +37,9 @@ - `fetch-params` - `snapshot fetch` - `snapshot validate` +- [#3355](https://github.com/ChainSafe/forest/pull/3355) Moved commands + - `forest-cli db stats` to `forest-tool db stats` + - `forest-cli db clean` to `forest-tool db destroy` ### Added diff --git a/scripts/db_params_hyperfine.sh b/scripts/db_params_hyperfine.sh index 536cf643c231..8fa5481ea21e 100755 --- a/scripts/db_params_hyperfine.sh +++ b/scripts/db_params_hyperfine.sh @@ -22,4 +22,4 @@ hyperfine \ ./target/release/forest \ --chain ${CHAIN} --config /tmp/forest.conf --rpc false --no-gc --encrypt-keystore false --halt-after-import \ --import-snapshot ${SNAPSHOT}; \ - ./target/release/forest-cli --chain ${CHAIN} db clean --force" + ./target/release/forest-tool db destroy --chain ${CHAIN} --force" diff --git a/scripts/gen_coverage_report.sh b/scripts/gen_coverage_report.sh index 088dcff91c23..787293902fad 100755 --- a/scripts/gen_coverage_report.sh +++ b/scripts/gen_coverage_report.sh @@ -41,7 +41,7 @@ cov forest --chain calibnet --encrypt-keystore false --import-snapshot "$SNAPSHO cov forest-cli sync wait cov forest-cli sync status cov forest-cli --chain calibnet db gc -cov forest-cli --chain calibnet db stats +cov forest-tool db stats --chain calibnet cov forest-cli snapshot export cov forest-cli snapshot export cov forest-cli attach --exec 'showPeers()' diff --git a/scripts/tests/forest_cli_check.sh b/scripts/tests/forest_cli_check.sh index 6bf0422469ca..e2f8f7cd8dde 100755 --- a/scripts/tests/forest_cli_check.sh +++ b/scripts/tests/forest_cli_check.sh @@ -21,9 +21,9 @@ function num-files-here() { "$FOREST_TOOL_PATH" fetch-params --keys -: "cleaning an empty database doesn't fail (see #2811)" -"$FOREST_CLI_PATH" --chain calibnet db clean --force -"$FOREST_CLI_PATH" --chain calibnet db clean --force +: "destroying an empty database doesn't fail (see #2811)" +"$FOREST_TOOL_PATH" db destroy --chain calibnet --force +"$FOREST_TOOL_PATH" db destroy --chain calibnet --force : fetch snapshot diff --git a/scripts/tests/harness.sh b/scripts/tests/harness.sh index 630467537162..fcdfc5e7c19a 100644 --- a/scripts/tests/harness.sh +++ b/scripts/tests/harness.sh @@ -20,7 +20,7 @@ function forest_download_and_import_snapshot { function forest_check_db_stats { echo "Checking DB stats" - $FOREST_CLI_PATH --chain calibnet db stats + $FOREST_TOOL_PATH db stats --chain calibnet } function forest_query_epoch { diff --git a/src/cli/main.rs b/src/cli/main.rs index e91dd3d7faf9..daaafc2e9776 100644 --- a/src/cli/main.rs +++ b/src/cli/main.rs @@ -24,6 +24,13 @@ macro_rules! bail_moved_cmd { $src ) }; + ($src:literal, $dst:literal) => { + anyhow::bail!( + "Invalid subcommand: {}. It has been moved to forest-tool {}.", + $src, + $dst + ) + }; } pub fn main(args: impl IntoIterator) -> anyhow::Result<()> diff --git a/src/cli/subcommands/db_cmd.rs b/src/cli/subcommands/db_cmd.rs index d0ada9d88f72..28423a449d20 100644 --- a/src/cli/subcommands/db_cmd.rs +++ b/src/cli/subcommands/db_cmd.rs @@ -3,16 +3,14 @@ use std::sync::Arc; -use crate::cli_shared::{chain_path, cli::Config}; -use crate::db::db_engine::db_root; +use crate::cli_shared::cli::Config; use crate::rpc_api::progress_api::GetProgressType; use crate::rpc_client::{db_ops::db_gc, progress_ops::get_progress}; use crate::utils::io::ProgressBar; use chrono::Utc; use clap::Subcommand; -use tracing::error; -use crate::cli::subcommands::{handle_rpc_err, prompt_confirm}; +use crate::cli::subcommands::handle_rpc_err; #[derive(Debug, Subcommand)] pub enum DBCommands { @@ -31,15 +29,7 @@ pub enum DBCommands { impl DBCommands { pub async fn run(&self, config: &Config) -> anyhow::Result<()> { match self { - Self::Stats => { - use human_repr::HumanCount; - - let dir = db_root(&chain_path(config)); - println!("Database path: {}", dir.display()); - let size = fs_extra::dir::get_size(dir).unwrap_or_default(); - println!("Database size: {}", size.human_count_bytes()); - Ok(()) - } + Self::Stats => crate::bail_moved_cmd!("db stats"), Self::GC => { let start = Utc::now(); @@ -81,31 +71,7 @@ impl DBCommands { Ok(()) } - Self::Clean { force } => { - let dir = chain_path(config); - if !dir.is_dir() { - println!( - "Aborted. Database path {} is not a valid directory", - dir.display() - ); - return Ok(()); - } - println!("Deleting {}", dir.display()); - if !force && !prompt_confirm() { - println!("Aborted."); - return Ok(()); - } - match fs_extra::dir::remove(&dir) { - Ok(_) => { - println!("Deleted {}", dir.display()); - Ok(()) - } - Err(err) => { - error!("{err}"); - Ok(()) - } - } - } + Self::Clean { force: _ } => crate::bail_moved_cmd!("db clean", "db destroy"), } } } diff --git a/src/cli/subcommands/mod.rs b/src/cli/subcommands/mod.rs index b1be9d5bdaf5..6ba2c55906ab 100644 --- a/src/cli/subcommands/mod.rs +++ b/src/cli/subcommands/mod.rs @@ -214,7 +214,7 @@ pub(super) fn print_stdout(out: String) { .unwrap(); } -fn prompt_confirm() -> bool { +pub fn prompt_confirm() -> bool { print!("Do you want to continue? [y/n] "); std::io::stdout().flush().unwrap(); let mut line = String::new(); diff --git a/src/tool/main.rs b/src/tool/main.rs index f47d3475d683..de5f102a8a7e 100644 --- a/src/tool/main.rs +++ b/src/tool/main.rs @@ -25,6 +25,7 @@ where Subcommand::Snapshot(cmd) => cmd.run().await, Subcommand::Fetch(cmd) => cmd.run().await, Subcommand::Archive(cmd) => cmd.run().await, + Subcommand::DB(cmd) => cmd.run().await, } }) } diff --git a/src/tool/subcommands/db_cmd.rs b/src/tool/subcommands/db_cmd.rs new file mode 100644 index 000000000000..2efecfea2e7e --- /dev/null +++ b/src/tool/subcommands/db_cmd.rs @@ -0,0 +1,84 @@ +// Copyright 2019-2023 ChainSafe Systems +// SPDX-License-Identifier: Apache-2.0, MIT + +use super::read_config; +use crate::cli::subcommands::prompt_confirm; +use crate::cli_shared::chain_path; +use crate::db::db_engine::db_root; +use crate::networks::NetworkChain; +use clap::Subcommand; +use tracing::error; + +#[derive(Debug, Subcommand)] +pub enum DBCommands { + /// Show DB stats + Stats { + /// Optional TOML file containing forest daemon configuration + #[arg(short, long)] + config: Option, + /// Optional chain, will override the chain section of configuration file if used + #[arg(long)] + chain: Option, + }, + /// DB destruction + Destroy { + /// Answer yes to all forest-cli yes/no questions without prompting + #[arg(long)] + force: bool, + /// Optional TOML file containing forest daemon configuration + #[arg(short, long)] + config: Option, + /// Optional chain, will override the chain section of configuration file if used + #[arg(long)] + chain: Option, + }, +} + +impl DBCommands { + pub async fn run(&self) -> anyhow::Result<()> { + match self { + Self::Stats { config, chain } => { + use human_repr::HumanCount; + + let config = read_config(config, chain)?; + + let dir = db_root(&chain_path(&config)); + println!("Database path: {}", dir.display()); + let size = fs_extra::dir::get_size(dir).unwrap_or_default(); + println!("Database size: {}", size.human_count_bytes()); + Ok(()) + } + Self::Destroy { + force, + config, + chain, + } => { + let config = read_config(config, chain)?; + + let dir = chain_path(&config); + if !dir.is_dir() { + println!( + "Aborted. Database path {} is not a valid directory", + dir.display() + ); + return Ok(()); + } + println!("Deleting {}", dir.display()); + if !force && !prompt_confirm() { + println!("Aborted."); + return Ok(()); + } + match fs_extra::dir::remove(&dir) { + Ok(_) => { + println!("Deleted {}", dir.display()); + Ok(()) + } + Err(err) => { + error!("{err}"); + Ok(()) + } + } + } + } + } +} diff --git a/src/tool/subcommands/fetch_params_cmd.rs b/src/tool/subcommands/fetch_params_cmd.rs index 6594455a1858..aee5c846ed5e 100644 --- a/src/tool/subcommands/fetch_params_cmd.rs +++ b/src/tool/subcommands/fetch_params_cmd.rs @@ -28,7 +28,7 @@ pub struct FetchCommands { impl FetchCommands { pub async fn run(&self) -> anyhow::Result<()> { - let config = read_config(&self.config)?; + let config = read_config(&self.config, &None)?; let sizes = if self.all { SectorSizeOpt::All diff --git a/src/tool/subcommands/mod.rs b/src/tool/subcommands/mod.rs index e5b3d901ed14..8ff837157bff 100644 --- a/src/tool/subcommands/mod.rs +++ b/src/tool/subcommands/mod.rs @@ -3,14 +3,17 @@ pub mod archive_cmd; pub mod benchmark_cmd; +pub mod db_cmd; pub mod fetch_params_cmd; pub mod snapshot_cmd; use crate::cli_shared::cli::HELP_MESSAGE; use crate::cli_shared::cli::*; +use crate::networks::{ChainConfig, NetworkChain}; use crate::utils::version::FOREST_VERSION_STRING; use crate::utils::{io::read_file_to_string, io::read_toml}; use clap::Parser; +use std::sync::Arc; /// Command-line options for the `forest-tool` binary #[derive(Parser)] @@ -39,10 +42,15 @@ pub enum Subcommand { /// Manage archives #[command(subcommand)] Archive(archive_cmd::ArchiveCommands), + + /// Database management + #[command(subcommand)] + DB(db_cmd::DBCommands), } -fn read_config(config: &Option) -> anyhow::Result { - Ok(match find_config_path(config) { +fn read_config(config: &Option, chain: &Option) -> anyhow::Result { + let path = find_config_path(config); + let mut cfg: Config = match &path { Some(path) => { // Read from config file let toml = read_file_to_string(path.to_path_buf())?; @@ -50,5 +58,15 @@ fn read_config(config: &Option) -> anyhow::Result { read_toml(&toml)? } None => Config::default(), - }) + }; + + // Override config with chain if some + match chain { + Some(NetworkChain::Mainnet) => cfg.chain = Arc::new(ChainConfig::mainnet()), + Some(NetworkChain::Calibnet) => cfg.chain = Arc::new(ChainConfig::calibnet()), + Some(NetworkChain::Devnet(_)) => cfg.chain = Arc::new(ChainConfig::devnet()), + None => (), + } + + Ok(cfg) }