Skip to main content

ohlcv_ctl/cli/command/
mod.rs

1//! Command line interface for the collector.
2
3mod drop;
4use std::fmt;
5
6pub use drop::drop;
7
8mod fetch;
9pub use fetch::fetch;
10
11mod init;
12pub use init::init;
13
14use clap::ArgMatches;
15use inquire::{Password, PasswordDisplayMode};
16use ohlcv::{
17    database::{Credentials, DbType},
18    Database,
19};
20use tracing::instrument;
21
22use crate::Error;
23
24/// Execute the command specified by the command line arguments.
25///
26/// # Errors
27///
28/// Returns an error if the command is not recognized or if an error occurs
29/// while executing the command.
30#[instrument(skip(command))]
31pub async fn execute(command: Option<(&str, &ArgMatches)>) -> Result<(), Error> {
32    match command {
33        Some(("drop", args)) => {
34            let config = args.get_one::<std::path::PathBuf>("config");
35            let all = args.get_flag("all");
36
37            drop(all, config).await
38        }
39        Some(("init", args)) => {
40            let config = args.get_one::<std::path::PathBuf>("config");
41
42            init(config).await
43        }
44        Some(("fetch", args)) => {
45            let config = args.get_one::<std::path::PathBuf>("config");
46
47            fetch(config).await
48        }
49        Some((command, _)) => Err(Error::CommandName(command.into())),
50        None => fetch(None).await,
51    }
52}
53
54#[instrument]
55fn ask_password(username: impl AsRef<str> + fmt::Debug) -> Result<String, Error> {
56    let username = username.as_ref();
57
58    Password::new(&format!(
59        "Enter password for the database user `{username}`:"
60    ))
61    .with_display_toggle_enabled()
62    .with_display_mode(PasswordDisplayMode::Hidden)
63    .without_confirmation()
64    .with_help_message("Output is hidden.")
65    .prompt()
66    .map_err(|err| Error::AskPassword(username.into(), Box::new(err)))
67}
68
69fn root_credentials(db: &DbType) -> Result<Option<Credentials>, Error> {
70    if let Some(username) = db.root_username() {
71        let creds = Credentials::new(username);
72
73        if creds.has_password() {
74            return Ok(Some(creds));
75        }
76
77        let password = ask_password(username)?;
78        return Ok(Some(creds.with_password(password)));
79    }
80    Ok(None)
81}