Skip to main content

soldeer_commands/
lib.rs

1//! High-level commands for the Soldeer CLI
2#![cfg_attr(docsrs, feature(doc_cfg))]
3pub use crate::commands::{Args, Command};
4use clap::builder::PossibleValue;
5pub use clap_verbosity_flag::Verbosity;
6use clap_verbosity_flag::log::Level;
7use commands::CustomLevel;
8use derive_more::derive::FromStr;
9use soldeer_core::{Result, config::Paths};
10use std::{
11    env,
12    path::PathBuf,
13    sync::atomic::{AtomicBool, Ordering},
14};
15use utils::{get_config_location, intro, outro, outro_cancel, step};
16
17pub mod commands;
18pub mod utils;
19
20static TUI_ENABLED: AtomicBool = AtomicBool::new(true);
21
22/// The location where the Soldeer config should be stored.
23///
24/// This is a new type so we can implement the `ValueEnum` trait for it.
25#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, FromStr)]
26pub struct ConfigLocation(soldeer_core::config::ConfigLocation);
27
28impl clap::ValueEnum for ConfigLocation {
29    fn value_variants<'a>() -> &'a [Self] {
30        &[
31            Self(soldeer_core::config::ConfigLocation::Foundry),
32            Self(soldeer_core::config::ConfigLocation::Soldeer),
33        ]
34    }
35
36    fn to_possible_value(&self) -> Option<clap::builder::PossibleValue> {
37        Some(match self.0 {
38            soldeer_core::config::ConfigLocation::Foundry => PossibleValue::new("foundry"),
39            soldeer_core::config::ConfigLocation::Soldeer => PossibleValue::new("soldeer"),
40        })
41    }
42}
43
44impl From<ConfigLocation> for soldeer_core::config::ConfigLocation {
45    fn from(value: ConfigLocation) -> Self {
46        value.0
47    }
48}
49
50impl From<soldeer_core::config::ConfigLocation> for ConfigLocation {
51    fn from(value: soldeer_core::config::ConfigLocation) -> Self {
52        Self(value)
53    }
54}
55
56pub async fn run(command: Command, verbosity: Verbosity<CustomLevel>) -> Result<()> {
57    if env::var("RUST_LOG").is_ok() {
58        env_logger::builder().try_init().ok(); // init logger if possible (not already initialized)
59        TUI_ENABLED.store(false, Ordering::Relaxed);
60    } else {
61        match verbosity.log_level() {
62            Some(level) if level > Level::Error => {
63                // the user requested structure logging (-v[v*])
64                // init logger if possible (not already initialized)
65                env_logger::Builder::new()
66                    .filter_level(verbosity.log_level_filter())
67                    .try_init()
68                    .ok();
69                TUI_ENABLED.store(false, Ordering::Relaxed);
70            }
71            Some(_) => TUI_ENABLED.store(true, Ordering::Relaxed),
72            _ => TUI_ENABLED.store(false, Ordering::Relaxed),
73        }
74    }
75    match command {
76        Command::Init(cmd) => {
77            intro!("🦌 Soldeer Init 🦌");
78            step!("Initialize Foundry project to use Soldeer");
79            // for init, we always use the current dir as root, unless specified by env
80            let root = env::var("SOLDEER_PROJECT_ROOT")
81                .ok()
82                .filter(|p| !p.is_empty())
83                .map_or(env::current_dir()?, PathBuf::from);
84            let paths = Paths::with_root_and_config(
85                &root,
86                Some(get_config_location(&root, cmd.config_location)?),
87            )?;
88            commands::init::init_command(&paths, cmd).await.inspect_err(|_| {
89                outro_cancel!("An error occurred during initialization");
90            })?;
91            outro!("Done initializing!");
92        }
93        Command::Install(cmd) => {
94            intro!("🦌 Soldeer Install 🦌");
95            let root = Paths::get_root_path();
96            let paths = Paths::with_root_and_config(
97                &root,
98                Some(get_config_location(&root, cmd.config_location)?),
99            )?;
100            commands::install::install_command(&paths, cmd).await.inspect_err(|_| {
101                outro_cancel!("An error occurred during install");
102            })?;
103            outro!("Done installing!");
104        }
105        Command::Update(cmd) => {
106            intro!("🦌 Soldeer Update 🦌");
107            let root = Paths::get_root_path();
108            let paths = Paths::with_root_and_config(
109                &root,
110                Some(get_config_location(&root, cmd.config_location)?),
111            )?;
112            commands::update::update_command(&paths, cmd).await.inspect_err(|_| {
113                outro_cancel!("An error occurred during the update");
114            })?;
115            outro!("Done updating!");
116        }
117        Command::Uninstall(cmd) => {
118            intro!("🦌 Soldeer Uninstall 🦌");
119            let root = Paths::get_root_path();
120            let paths =
121                Paths::with_root_and_config(&root, Some(get_config_location(&root, None)?))?;
122            commands::uninstall::uninstall_command(&paths, &cmd).inspect_err(|_| {
123                outro_cancel!("An error occurred during uninstall");
124            })?;
125            outro!("Done uninstalling!");
126        }
127        Command::Clean(cmd) => {
128            intro!("🦌 Soldeer Clean 🦌");
129            let root = Paths::get_root_path();
130            let paths =
131                Paths::with_root_and_config(&root, Some(get_config_location(&root, None)?))?;
132            commands::clean::clean_command(&paths, &cmd).inspect_err(|_| {
133                outro_cancel!("An error occurred during clean");
134            })?;
135            outro!("Done cleaning!");
136        }
137        Command::Login(cmd) => {
138            intro!("🦌 Soldeer Login 🦌");
139            commands::login::login_command(cmd).await.inspect_err(|_| {
140                outro_cancel!("An error occurred during login");
141            })?;
142            outro!("Done logging in!");
143        }
144        Command::Push(cmd) => {
145            intro!("🦌 Soldeer Push 🦌");
146            commands::push::push_command(cmd).await.inspect_err(|_| {
147                outro_cancel!("An error occurred during push");
148            })?;
149            outro!("Done!");
150        }
151        Command::Version(_) => {
152            const VERSION: &str = env!("CARGO_PKG_VERSION");
153            println!("soldeer {VERSION}");
154        }
155    }
156    Ok(())
157}