diff --git a/Cargo.lock b/Cargo.lock index ec631353..cb1f0b97 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -75,7 +75,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e01ed3140b2f8d422c68afa1ed2e85d996ea619c988ac834d255db32138655cb" dependencies = [ "quote", - "syn 2.0.39", + "syn 2.0.48", ] [[package]] @@ -188,7 +188,7 @@ dependencies = [ "actix-router", "proc-macro2", "quote", - "syn 2.0.39", + "syn 2.0.48", ] [[package]] @@ -847,7 +847,7 @@ checksum = "16e62a023e7c117e27523144c5d2459f4397fcc3cab0085af8e2224f643a0193" dependencies = [ "proc-macro2", "quote", - "syn 2.0.39", + "syn 2.0.48", ] [[package]] @@ -858,7 +858,7 @@ checksum = "a66537f1bb974b254c98ed142ff995236e81b9d0fe4db0575f46612cb15eb0f9" dependencies = [ "proc-macro2", "quote", - "syn 2.0.39", + "syn 2.0.48", ] [[package]] @@ -1606,7 +1606,7 @@ dependencies = [ "heck", "proc-macro2", "quote", - "syn 2.0.39", + "syn 2.0.48", ] [[package]] @@ -2238,7 +2238,7 @@ checksum = "83fdaf97f4804dcebfa5862639bc9ce4121e82140bec2a987ac5140294865b5b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.39", + "syn 2.0.48", ] [[package]] @@ -2265,7 +2265,7 @@ dependencies = [ "proc-macro2", "quote", "scratch", - "syn 2.0.39", + "syn 2.0.48", ] [[package]] @@ -2282,7 +2282,7 @@ checksum = "2fa16a70dd58129e4dfffdff535fb1bce66673f7bbeec4a5a1765a504e1ccd84" dependencies = [ "proc-macro2", "quote", - "syn 2.0.39", + "syn 2.0.48", ] [[package]] @@ -2592,7 +2592,7 @@ checksum = "487585f4d0c6655fe74905e2504d8ad6908e4db67f744eb140876906c2f3175d" dependencies = [ "proc-macro2", "quote", - "syn 2.0.39", + "syn 2.0.48", ] [[package]] @@ -2633,7 +2633,7 @@ dependencies = [ "proc-macro2", "quote", "regex", - "syn 2.0.39", + "syn 2.0.48", "termcolor", "toml 0.7.8", "walkdir", @@ -3112,7 +3112,7 @@ dependencies = [ "heck", "proc-macro2", "quote", - "syn 2.0.39", + "syn 2.0.48", ] [[package]] @@ -3371,7 +3371,7 @@ dependencies = [ "fs-err", "proc-macro2", "quote", - "syn 2.0.39", + "syn 2.0.48", ] [[package]] @@ -3926,7 +3926,7 @@ dependencies = [ "proc-macro-warning", "proc-macro2", "quote", - "syn 2.0.39", + "syn 2.0.48", ] [[package]] @@ -3938,7 +3938,7 @@ dependencies = [ "proc-macro-crate", "proc-macro2", "quote", - "syn 2.0.39", + "syn 2.0.48", ] [[package]] @@ -3948,7 +3948,7 @@ source = "git+https://github.com/subspace/polkadot-sdk?rev=c63a8b28a9fd26d42116b dependencies = [ "proc-macro2", "quote", - "syn 2.0.39", + "syn 2.0.48", ] [[package]] @@ -4124,7 +4124,7 @@ checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac" dependencies = [ "proc-macro2", "quote", - "syn 2.0.39", + "syn 2.0.48", ] [[package]] @@ -6099,7 +6099,7 @@ dependencies = [ "heck", "proc-macro2", "quote", - "syn 2.0.39", + "syn 2.0.48", ] [[package]] @@ -6493,7 +6493,7 @@ dependencies = [ "macro_magic_core", "macro_magic_macros", "quote", - "syn 2.0.39", + "syn 2.0.48", ] [[package]] @@ -6507,7 +6507,7 @@ dependencies = [ "macro_magic_core_macros", "proc-macro2", "quote", - "syn 2.0.39", + "syn 2.0.48", ] [[package]] @@ -6518,7 +6518,7 @@ checksum = "c12469fc165526520dff2807c2975310ab47cf7190a45b99b49a7dc8befab17b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.39", + "syn 2.0.48", ] [[package]] @@ -6529,7 +6529,7 @@ checksum = "b8fb85ec1620619edf2984a7693497d4ec88a9665d8b87e942856884c92dbf2a" dependencies = [ "macro_magic_core", "quote", - "syn 2.0.39", + "syn 2.0.48", ] [[package]] @@ -7186,7 +7186,7 @@ dependencies = [ "proc-macro-crate", "proc-macro2", "quote", - "syn 2.0.39", + "syn 2.0.48", ] [[package]] @@ -7197,7 +7197,7 @@ checksum = "681030a937600a36906c185595136d26abfebb4aa9c65701cefcaf8578bb982b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.39", + "syn 2.0.48", ] [[package]] @@ -7921,7 +7921,7 @@ checksum = "4359fd9c9171ec6e8c62926d6faaf553a8dc3f64e1507e76da7911b4f6a04405" dependencies = [ "proc-macro2", "quote", - "syn 2.0.39", + "syn 2.0.48", ] [[package]] @@ -8137,14 +8137,14 @@ checksum = "3d1eaa7fa0aa1929ffdf7eeb6eac234dde6268914a14ad44d23521ab6a9b258e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.39", + "syn 2.0.48", ] [[package]] name = "proc-macro2" -version = "1.0.69" +version = "1.0.78" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "134c189feb4956b20f6f547d2cf727d4c0fe06722b20a0eec87ed445a97f92da" +checksum = "e2422ad645d89c99f8f3e6b88a9fdeca7fabeac836b1002371c4367c8f984aae" dependencies = [ "unicode-ident", ] @@ -8195,7 +8195,7 @@ checksum = "440f724eba9f6996b75d63681b0a92b06947f1457076d503a4d2e2c8f56442b8" dependencies = [ "proc-macro2", "quote", - "syn 2.0.39", + "syn 2.0.48", ] [[package]] @@ -8287,6 +8287,7 @@ dependencies = [ "rand 0.8.5", "serde", "serde_derive", + "serde_json", "single-instance", "sp-core", "strum", @@ -8423,9 +8424,9 @@ dependencies = [ [[package]] name = "quote" -version = "1.0.33" +version = "1.0.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae" +checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef" dependencies = [ "proc-macro2", ] @@ -8625,7 +8626,7 @@ checksum = "7f7473c2cfcf90008193dd0e3e16599455cb601a9fce322b5bb55de799664925" dependencies = [ "proc-macro2", "quote", - "syn 2.0.39", + "syn 2.0.48", ] [[package]] @@ -9177,7 +9178,7 @@ dependencies = [ "proc-macro-crate", "proc-macro2", "quote", - "syn 2.0.39", + "syn 2.0.48", ] [[package]] @@ -10000,7 +10001,7 @@ dependencies = [ "proc-macro-crate", "proc-macro2", "quote", - "syn 2.0.39", + "syn 2.0.48", ] [[package]] @@ -10482,9 +10483,9 @@ checksum = "a3f0bf26fd526d2a95683cd0f87bf103b8539e2ca1ef48ce002d67aad59aa0b4" [[package]] name = "serde" -version = "1.0.188" +version = "1.0.196" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf9e0fcba69a370eed61bcf2b728575f726b50b55cba78064753d708ddc7549e" +checksum = "870026e60fa08c69f064aa766c10f10b1d62db9ccd4d0abb206472bee0ce3b32" dependencies = [ "serde_derive", ] @@ -10500,20 +10501,20 @@ dependencies = [ [[package]] name = "serde_derive" -version = "1.0.188" +version = "1.0.196" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4eca7ac642d82aa35b60049a6eccb4be6be75e599bd2e9adb5f875a737654af2" +checksum = "33c85360c95e7d137454dc81d9a4ed2b8efd8fbe19cee57357b32b9771fccb67" dependencies = [ "proc-macro2", "quote", - "syn 2.0.39", + "syn 2.0.48", ] [[package]] name = "serde_json" -version = "1.0.106" +version = "1.0.113" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2cc66a619ed80bf7a0f6b17dd063a84b88f6dea1813737cf469aef1d081142c2" +checksum = "69801b70b1c3dac963ecb03a364ba0ceda9cf60c71cfe475e99864759c8b8a79" dependencies = [ "itoa", "ryu", @@ -10815,7 +10816,7 @@ dependencies = [ "proc-macro-crate", "proc-macro2", "quote", - "syn 2.0.39", + "syn 2.0.48", ] [[package]] @@ -11029,7 +11030,7 @@ source = "git+https://github.com/subspace/polkadot-sdk?rev=c63a8b28a9fd26d42116b dependencies = [ "quote", "sp-core-hashing", - "syn 2.0.39", + "syn 2.0.48", ] [[package]] @@ -11048,7 +11049,7 @@ source = "git+https://github.com/subspace/polkadot-sdk?rev=c63a8b28a9fd26d42116b dependencies = [ "proc-macro2", "quote", - "syn 2.0.39", + "syn 2.0.48", ] [[package]] @@ -11335,7 +11336,7 @@ dependencies = [ "proc-macro-crate", "proc-macro2", "quote", - "syn 2.0.39", + "syn 2.0.48", ] [[package]] @@ -11527,7 +11528,7 @@ dependencies = [ "parity-scale-codec", "proc-macro2", "quote", - "syn 2.0.39", + "syn 2.0.48", ] [[package]] @@ -11686,7 +11687,7 @@ dependencies = [ "proc-macro2", "quote", "rustversion", - "syn 2.0.39", + "syn 2.0.48", ] [[package]] @@ -12210,9 +12211,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.39" +version = "2.0.48" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23e78b90f2fcf45d3e842032ce32e3f2d1545ba6636271dcbf24fa306d87be7a" +checksum = "0f3531638e407dfc0814761abb7c00a5b54992b849452a0646b7f65c9f770f3f" dependencies = [ "proc-macro2", "quote", @@ -12326,7 +12327,7 @@ checksum = "266b2e40bc00e5a6c09c3584011e08b06f123c00362c92b975ba9843aaaa14b8" dependencies = [ "proc-macro2", "quote", - "syn 2.0.39", + "syn 2.0.48", ] [[package]] @@ -12467,7 +12468,7 @@ checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.39", + "syn 2.0.48", ] [[package]] @@ -12657,7 +12658,7 @@ source = "git+https://github.com/tokio-rs/tracing?branch=v0.1.x#c6bedbe2725830c1 dependencies = [ "proc-macro2", "quote", - "syn 2.0.39", + "syn 2.0.48", ] [[package]] @@ -13130,7 +13131,7 @@ dependencies = [ "once_cell", "proc-macro2", "quote", - "syn 2.0.39", + "syn 2.0.48", "wasm-bindgen-shared", ] @@ -13164,7 +13165,7 @@ checksum = "54681b18a46765f095758388f2d0cf16eb8d4169b639ab575a8f5693af210c7b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.39", + "syn 2.0.48", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -14191,7 +14192,7 @@ checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" dependencies = [ "proc-macro2", "quote", - "syn 2.0.39", + "syn 2.0.48", ] [[package]] diff --git a/pulsar/Cargo.toml b/pulsar/Cargo.toml index 57f8f70e..fe53f167 100644 --- a/pulsar/Cargo.toml +++ b/pulsar/Cargo.toml @@ -26,6 +26,7 @@ owo-colors = "3.5.0" rand = "0.8.5" serde = "1" serde_derive = "1" +serde_json = "1.0.113" single-instance = "0.3.3" sp-core = { version = "21.0.0", git = "https://github.com/subspace/polkadot-sdk", rev = "c63a8b28a9fd26d42116b0dcef1f2a5cefb9cd1c", features = ["full_crypto"] } strum = "0.24.1" diff --git a/pulsar/src/commands.rs b/pulsar/src/commands.rs index 42411cf4..5a57d902 100644 --- a/pulsar/src/commands.rs +++ b/pulsar/src/commands.rs @@ -1,3 +1,4 @@ +pub(crate) mod config; pub(crate) mod farm; pub(crate) mod info; pub(crate) mod init; diff --git a/pulsar/src/commands/config.rs b/pulsar/src/commands/config.rs new file mode 100644 index 00000000..2bce00c8 --- /dev/null +++ b/pulsar/src/commands/config.rs @@ -0,0 +1,170 @@ +//! Config CLI command of pulsar is about setting either or all of the +//! parameters: +//! - chain +//! - farm size +//! - reward address +//! - node directory +//! - farm directory +//! +//! and showing the set config details. +//! +//! ## Usage +//! +//! ### Show +//! ```bash +//! $ pulsar config +//! Current Config set as: +//! { +//! "chain": "Gemini3g", +//! "farmer": { +//! "reward_address": "06fef8efdd808a95500e5baee2bcde4cf8d5e1191b2b3f93065f10f0e4648c09", +//! "farm_directory": "/Users/abhi3700/Library/Application Support/pulsar/farms", +//! "farm_size": "3.0 GB" +//! }, +//! "node": { +//! "directory": "/Users/abhi3700/Library/Application Support/pulsar/node", +//! "name": "abhi3700" +//! } +//! } +//! in file: "/Users/abhi3700/Library/Application Support/pulsar/settings.toml" +//! ``` +//! +//! ### Chain +//! ```bash +//! $ pulsar config -c devnet +//! ``` +//! +//! ### Farm size +//! ```bash +//! $ pulsar config -f 3GB +//! ``` +//! +//! ### Reward address +//! +//! ```bash +//! $ pulsar config -r 5CDstQSbxPrPAaRTuVR2n9PHuhGYnnQvXdbJSQmodD5i16x2 +//! ``` +//! +//! ### Node directory +//! ```bash +//! $ pulsar config -n "/Users/abhi3700/test/pulsar1/node" +//! ``` +//! +//! ### Farm directory +//! ```bash +//! $ pulsar config -d "/Users/abhi3700/test/pulsar1/farms" +//! ``` +//! +//! ### All params +//! ```bash +//! $ pulsar config \ +//! --chain devnet \ +//! --farm-size 5GB \ +//! --reward-address 5DXRtoHJePQBEk44onMy5yG4T8CjpPaK4qKNmrwpxqxZALGY \ +//! --node-dir "/Users/abhi3700/test/pulsar1/node" \ +//! --farm-dir "/Users/abhi3700/test/pulsar1/farms" +//! ``` + +use std::fs; +use std::path::PathBuf; +use std::str::FromStr; + +use color_eyre::eyre::{self, bail}; + +use crate::commands::wipe::wipe; +use crate::config::{parse_config, parse_config_path, ChainConfig, Config}; +use crate::utils::{create_or_move_data, reward_address_parser, size_parser}; + +// function for config cli command +pub(crate) async fn config( + chain: Option, + farm_size: Option, + reward_address: Option, + node_dir: Option, + farm_dir: Option, +) -> eyre::Result<()> { + // Define the path to your settings.toml file + let config_path = parse_config_path()?; + + // if config file doesn't exist, then throw error + if !config_path.exists() { + bail!("Config file: \"settings.toml\" not found.\nPlease use `pulsar init` command first."); + } + + // Load the current configuration + let mut config: Config = parse_config()?; + + if chain.is_some() + || farm_size.is_some() + || reward_address.is_some() + || node_dir.is_some() + || farm_dir.is_some() + { + // no options provided + if chain.is_none() + && farm_size.is_none() + && reward_address.is_none() + && node_dir.is_none() + && farm_dir.is_none() + { + println!("At least one option has to be provided.\nTry `pulsar config -h`"); + return Ok(()); + } + + // update (optional) the chain + if let Some(c) = chain { + let new_chain = ChainConfig::from_str(&c)?; + if config.chain == new_chain.clone() { + bail!("Chain already set"); + } + + config.chain = new_chain.clone(); + + // if chain is changed, then wipe everything (farmer, node, summary) except + // config file + if parse_config()?.chain == new_chain { + wipe(true, true, true, false).await.expect("Error while wiping."); + } + } + + // update (optional) the farm size + if let Some(f) = farm_size { + let farm_size = size_parser(&f)?; + config.farmer.farm_size = farm_size; + } + + // update (optional) the reward address + if let Some(r) = reward_address { + let reward_address = reward_address_parser(&r)?; + config.farmer.reward_address = reward_address; + } + + // update (optional) the node directory + if let Some(n) = node_dir { + let node_dir = PathBuf::from_str(&n).expect("Invalid node directory"); + create_or_move_data(&config.node.directory, &node_dir)?; + config.node.directory = node_dir; + } + + // update (optional) the farm directory + if let Some(fd) = farm_dir { + let farm_dir = PathBuf::from_str(&fd).expect("Invalid farm directory"); + create_or_move_data(&config.farmer.farm_directory, &farm_dir)?; + config.farmer.farm_directory = farm_dir; + } + + // Save the updated configuration back to the file + fs::write(config_path, toml::to_string(&config)?)?; + } else { + // Display the current configuration as JSON + // Serialize `config` to a pretty-printed JSON string + let serialized = serde_json::to_string_pretty(&config)?; + println!( + "Current Config already set as: \n{}\nin file: {:?}", + serialized, + config_path.to_str().expect("Expected stringified config path") + ); + } + + Ok(()) +} diff --git a/pulsar/src/commands/farm.rs b/pulsar/src/commands/farm.rs index 16e77d79..bb6354e3 100644 --- a/pulsar/src/commands/farm.rs +++ b/pulsar/src/commands/farm.rs @@ -2,7 +2,7 @@ use std::io::Write; use std::sync::atomic::{AtomicBool, Ordering}; use std::sync::Arc; -use color_eyre::eyre::{eyre, Context, Error, Result}; +use color_eyre::eyre::{bail, eyre, Context, Error, Result}; use color_eyre::Report; use futures::prelude::*; use indicatif::{ProgressBar, ProgressStyle}; @@ -42,9 +42,7 @@ pub(crate) async fn farm(is_verbose: bool, enable_domains: bool, no_rotation: bo let instance = SingleInstance::new(SINGLE_INSTANCE) .context("Cannot take the instance lock from the OS! Aborting...")?; if !instance.is_single() { - return Err(eyre!( - "It seems like there is already a farming instance running. Aborting...", - )); + bail!("It seems like there is already a farming instance running. Aborting...",) } // raise file limit raise_fd_limit(); diff --git a/pulsar/src/commands/init.rs b/pulsar/src/commands/init.rs index 3004a226..704835c9 100644 --- a/pulsar/src/commands/init.rs +++ b/pulsar/src/commands/init.rs @@ -1,7 +1,7 @@ use std::io::{BufRead, Write}; use std::str::FromStr; -use color_eyre::eyre::{eyre, Context, Error, Result}; +use color_eyre::eyre::{bail, Context, Error, Result}; use crossterm::terminal::{Clear, ClearType}; use crossterm::{cursor, execute}; use rand::prelude::IteratorRandom; @@ -137,7 +137,7 @@ fn generate_or_get_reward_address(reward_address_exist: bool) -> Result Result<()> { /// implementation of the `wipe` command /// /// can wipe farmer, node, summary and farm -async fn wipe( +pub(crate) async fn wipe( wipe_farmer: bool, wipe_node: bool, wipe_summary: bool, diff --git a/pulsar/src/config.rs b/pulsar/src/config.rs index 173399ef..abbf5025 100644 --- a/pulsar/src/config.rs +++ b/pulsar/src/config.rs @@ -2,7 +2,7 @@ use std::fs::{create_dir_all, remove_file, File}; use std::num::NonZeroU8; use std::path::PathBuf; -use color_eyre::eyre::{eyre, Report, Result, WrapErr}; +use color_eyre::eyre::{bail, eyre, Report, Result, WrapErr}; use derivative::Derivative; use serde::{Deserialize, Serialize}; use strum_macros::EnumIter; @@ -150,7 +150,7 @@ impl FarmerConfig { } /// Enum for Chain -#[derive(Deserialize, Serialize, Default, Clone, Debug, EnumIter)] +#[derive(Deserialize, Serialize, Default, Clone, Debug, EnumIter, PartialEq)] pub(crate) enum ChainConfig { #[default] Gemini3g, @@ -189,13 +189,19 @@ pub(crate) fn create_config() -> Result<(File, PathBuf)> { Ok((file, config_path)) } -/// parses the config, and returns [`Config`] +/// parses the config path, and returns `ConfigPath` #[instrument] -pub(crate) fn parse_config() -> Result { +pub(crate) fn parse_config_path() -> Result { let config_path = dirs::config_dir().expect("couldn't get the default config directory!"); let config_path = config_path.join("pulsar").join("settings.toml"); - let config: Config = toml::from_str(&std::fs::read_to_string(config_path)?)?; + Ok(config_path) +} + +/// parses the config, and returns [`Config`] +#[instrument] +pub(crate) fn parse_config() -> Result { + let config: Config = toml::from_str(&std::fs::read_to_string(parse_config_path()?)?)?; Ok(config) } @@ -206,7 +212,7 @@ pub(crate) fn validate_config() -> Result { // validity checks if config.farmer.farm_size < MIN_FARM_SIZE { - return Err(eyre!("farm size should be bigger than {MIN_FARM_SIZE}!")); + bail!("farm size should be bigger than {MIN_FARM_SIZE}!"); } Ok(config) diff --git a/pulsar/src/main.rs b/pulsar/src/main.rs index 924b30a1..7ee9a211 100644 --- a/pulsar/src/main.rs +++ b/pulsar/src/main.rs @@ -25,6 +25,7 @@ use strum::IntoEnumIterator; use strum_macros::EnumIter; use tracing::instrument; +use crate::commands::config::config; use crate::commands::farm::farm; use crate::commands::info::info; use crate::commands::init::init; @@ -68,6 +69,21 @@ enum Commands { #[command(about = "displays info about the farmer instance (i.e. total amount of rewards, \ and status of initial plotting)")] Info, + #[command( + about = "set the config params: chain, farm-size, reward-address, node-dir, farm-dir" + )] + Config { + #[arg(short, long, action)] + chain: Option, + #[arg(short, long, action)] + farm_size: Option, + #[arg(short, long, action)] + reward_address: Option, + #[arg(short, long, action)] + node_dir: Option, + #[arg(short = 'd', long, action)] + farm_dir: Option, + }, OpenLogs, } @@ -88,6 +104,11 @@ async fn main() -> Result<(), Report> { Some(Commands::Wipe { farmer, node }) => { wipe_config(farmer, node).await.suggestion(support_message())?; } + Some(Commands::Config { chain, farm_size, reward_address, node_dir, farm_dir }) => { + config(chain, farm_size, reward_address, node_dir, farm_dir) + .await + .suggestion(support_message())?; + } Some(Commands::OpenLogs) => { open_log_dir().suggestion(support_message())?; } @@ -177,10 +198,13 @@ async fn arrow_key_mode() -> Result<(), Report> { info().await.suggestion(support_message())?; } 4 => { + config(None, None, None, None, None).await.suggestion(support_message())?; + } + 5 => { open_log_dir().suggestion(support_message())?; } _ => { - unreachable!("this number must stay in [0-4]") + unreachable!("this number must stay in [0-5]") } } @@ -222,6 +246,13 @@ impl std::fmt::Display for Commands { Commands::Wipe { farmer: _, node: _ } => write!(f, "wipe"), Commands::Info => write!(f, "info"), Commands::Init => write!(f, "init"), + Commands::Config { + chain: _, + farm_size: _, + reward_address: _, + node_dir: _, + farm_dir: _, + } => write!(f, "config"), Commands::OpenLogs => write!(f, "open logs directory"), } } diff --git a/pulsar/src/tests.rs b/pulsar/src/tests.rs index b18e34c2..4cbbaf5d 100644 --- a/pulsar/src/tests.rs +++ b/pulsar/src/tests.rs @@ -1,3 +1,4 @@ +use std::path::PathBuf; use std::str::FromStr; use rand::rngs::SmallRng; @@ -7,8 +8,9 @@ use subspace_sdk::ByteSize; use crate::config::ChainConfig; use crate::summary::*; use crate::utils::{ - apply_extra_options, custom_log_dir, directory_parser, farm_directory_getter, - node_directory_getter, node_name_parser, reward_address_parser, size_parser, yes_or_no_parser, + apply_extra_options, create_or_move_data, custom_log_dir, directory_parser, + farm_directory_getter, node_directory_getter, node_name_parser, reward_address_parser, + size_parser, yes_or_no_parser, }; async fn update_summary_file_randomly(summary_file: SummaryFile) { @@ -175,3 +177,48 @@ fn custom_log_dir_test() { #[cfg(target_os = "windows")] assert!(log_path.ends_with("AppData/Local/pulsar/logs")); } + +#[cfg(test)] +mod create_or_move_data_tests { + + use std::fs; + + use super::*; + use crate::utils::data_dir_getter; + + /// Ensuring the function correctly handles the case where the old and new + /// directories are the same. + #[test] + fn test_fails_when_old_new_dirs_same() { + let old_dir = node_directory_getter(); + let new_dir = node_directory_getter(); + + assert!(create_or_move_data(&old_dir, &new_dir).is_err()); + } + + /// Verifying the function fails when the new directory path does not start + /// with "/". + #[test] + #[cfg(any(target_os = "macos", target_os = "linux"))] + fn test_fails_new_dir_wo_slash() { + let old_dir = node_directory_getter(); + let new_dir = PathBuf::from("pulsar/node"); + + assert!(create_or_move_data(&old_dir, &new_dir).is_err()); + } + + /// test as expected by parsing valid old & new dirs + #[test] + fn test_create_or_move_data_success() { + let old_dir = node_directory_getter(); + let new_dir = data_dir_getter().join("node2"); + + assert!(create_or_move_data(&old_dir, &new_dir).is_ok()); + + // old dir shouldn't exist + assert!(!old_dir.exists()); + + // delete the newly created dir to reset + fs::remove_dir_all(new_dir).unwrap(); + } +} diff --git a/pulsar/src/utils.rs b/pulsar/src/utils.rs index 6cef31bc..9ed9bf59 100644 --- a/pulsar/src/utils.rs +++ b/pulsar/src/utils.rs @@ -1,9 +1,9 @@ use std::env; -use std::fs::create_dir_all; +use std::fs::{self, create_dir_all}; use std::path::{Path, PathBuf}; use std::str::FromStr; -use color_eyre::eyre::{eyre, Context, Result}; +use color_eyre::eyre::{bail, eyre, Context, Result}; use futures::prelude::*; use owo_colors::OwoColorize; use serde::{Deserialize, Deserializer, Serialize, Serializer}; @@ -121,9 +121,7 @@ pub(crate) fn directory_parser(location: &str) -> Result { /// utilize `ByteSize` crate for the validation pub(crate) fn size_parser(size: &str) -> Result { - let Ok(size) = size.parse::() else { - return Err(eyre!("could not parse the value!")); - }; + let Ok(size) = size.parse::() else { bail!("could not parse the value!") }; if size < MIN_FARM_SIZE { Err(eyre!(format!("farm size cannot be smaller than {}", MIN_FARM_SIZE))) } else { @@ -153,7 +151,7 @@ pub(crate) fn provider_storage_dir_getter() -> PathBuf { node_directory_getter().join("provider-storage") } -fn data_dir_getter() -> PathBuf { +pub(crate) fn data_dir_getter() -> PathBuf { dirs::data_dir().expect("data folder must be present in every major OS").join("pulsar") } @@ -388,3 +386,38 @@ impl<'de> Deserialize<'de> for Rewards { Ok(Rewards(value)) } } + +/// move data from old directory (if any) to new directory, or else just create +/// the new directory. +pub(crate) fn create_or_move_data(old_dir: &PathBuf, new_dir: &PathBuf) -> Result<()> { + if old_dir == new_dir { + bail!("This directory is already set"); + } + + #[cfg(any(target_os = "macos", target_os = "linux"))] + if !new_dir.starts_with("/") { + bail!("New directory path must start with /"); + } + + // Create the new directory if it doesn't exist + if !new_dir.exists() { + fs::create_dir_all(new_dir)?; + } + + // Move contents if the old directory exists + if old_dir.exists() { + let entries = fs::read_dir(old_dir)?; + for entry in entries { + let entry = entry?; + let file_name = entry.file_name(); + fs::rename(entry.path(), new_dir.join(file_name))?; + } + + // Check if the old directory is empty now and remove it + if fs::read_dir(old_dir)?.next().is_none() { + fs::remove_dir(old_dir)?; + } + } + + Ok(()) +}