diff options
author | Matthias Beyer <mail@beyermatthias.de> | 2020-11-03 17:13:10 +0100 |
---|---|---|
committer | Matthias Beyer <mail@beyermatthias.de> | 2020-11-03 17:46:51 +0100 |
commit | e56448f74a0bdc4ff703441d15ca5b7b06199fbe (patch) | |
tree | 6d2b0e75724623c6f9dc85b2c918a7bfce721cbb /src | |
parent | fa5b14fca13ca8b409677badd8d5a586a0885536 (diff) |
Add DB interface module for talking to the DB directly
Signed-off-by: Matthias Beyer <mail@beyermatthias.de>
Diffstat (limited to 'src')
-rw-r--r-- | src/db/interface.rs | 110 | ||||
-rw-r--r-- | src/db/mod.rs | 2 | ||||
-rw-r--r-- | src/main.rs | 3 |
3 files changed, 114 insertions, 1 deletions
diff --git a/src/db/interface.rs b/src/db/interface.rs new file mode 100644 index 0000000..65a46ad --- /dev/null +++ b/src/db/interface.rs @@ -0,0 +1,110 @@ +use std::path::PathBuf; + +use clap_v3 as clap; +use clap::ArgMatches; +use anyhow::anyhow; +use anyhow::Context; +use anyhow::Error; +use anyhow::Result; + +use crate::config::Configuration; +use crate::db::DbConnectionConfig; + +pub fn interface(db_connection_config: DbConnectionConfig, matches: &ArgMatches, config: &Configuration) -> Result<()> { + match matches.subcommand() { + ("cli", Some(matches)) => cli(db_connection_config, matches, config), + (other, _) => return Err(anyhow!("Unknown subcommand: {}", other)), + } +} + +fn cli(db_connection_config: DbConnectionConfig, matches: &ArgMatches, config: &Configuration) -> Result<()> { + use std::process::Command; + + trait PgCliCommand { + fn run_for_uri(&self, dbcc: DbConnectionConfig) -> Result<()>; + } + + struct Psql(PathBuf); + impl PgCliCommand for Psql { + fn run_for_uri(&self, dbcc: DbConnectionConfig) -> Result<()> { + Command::new(&self.0) + .arg(format!("--dbname={}", dbcc.database_name())) + .arg(format!("--host={}", dbcc.database_host())) + .arg(format!("--port={}", dbcc.database_port())) + .arg(format!("--username={}", dbcc.database_user())) + .stdin(std::process::Stdio::inherit()) + .stdout(std::process::Stdio::inherit()) + .stderr(std::process::Stdio::inherit()) + .output() + .map_err(Error::from) + .and_then(|out| { + if out.status.success() { + info!("pgcli exited successfully"); + Ok(()) + } else { + Err(anyhow!("gpcli did not exit successfully")) + .with_context(|| { + match String::from_utf8(out.stderr) { + Ok(log) => anyhow!("{}", log), + Err(e) => anyhow!("Cannot parse log into valid UTF-8: {}", e), + } + }) + .map_err(Error::from) + } + }) + } + } + + struct PgCli(PathBuf); + impl PgCliCommand for PgCli { + fn run_for_uri(&self, dbcc: DbConnectionConfig) -> Result<()> { + Command::new(&self.0) + .arg("--host") + .arg(dbcc.database_host()) + .arg("--port") + .arg(dbcc.database_port()) + .arg("--username") + .arg(dbcc.database_user()) + .arg(dbcc.database_name()) + .stdin(std::process::Stdio::inherit()) + .stdout(std::process::Stdio::inherit()) + .stderr(std::process::Stdio::inherit()) + .output() + .map_err(Error::from) + .and_then(|out| { + if out.status.success() { + info!("pgcli exited successfully"); + Ok(()) + } else { + Err(anyhow!("gpcli did not exit successfully")) + .with_context(|| { + match String::from_utf8(out.stderr) { + Ok(log) => anyhow!("{}", log), + Err(e) => anyhow!("Cannot parse log into valid UTF-8: {}", e), + } + }) + .map_err(Error::from) + } + }) + + } + } + + + matches.value_of("tool") + .map(|s| vec![s]) + .unwrap_or_else(|| vec!["psql", "pgcli"]) + .into_iter() + .filter_map(|s| which::which(&s).ok().map(|path| (path, s))) + .map(|(path, s)| { + match s { + "psql" => Ok(Box::new(Psql(path)) as Box<dyn PgCliCommand>), + "pgcli" => Ok(Box::new(PgCli(path)) as Box<dyn PgCliCommand>), + prog => Err(anyhow!("Unsupported pg CLI program: {}", prog)), + } + }) + .next() + .transpose()? + .ok_or_else(|| anyhow!("No Program found"))? + .run_for_uri(db_connection_config) +} diff --git a/src/db/mod.rs b/src/db/mod.rs index 95074cb..322d168 100644 --- a/src/db/mod.rs +++ b/src/db/mod.rs @@ -4,3 +4,5 @@ pub use connection::*; mod cli; pub use cli::*; +mod interface; +pub use interface::*; diff --git a/src/main.rs b/src/main.rs index 9e30044..8030a41 100644 --- a/src/main.rs +++ b/src/main.rs @@ -55,7 +55,6 @@ async fn main() -> Result<()> { let repo_path = PathBuf::from(config.repository()); let max_packages = count_pkg_files(&repo_path, ProgressBar::new_spinner()); let mut progressbars = ProgressBars::setup(); - let db = db::establish_connection(&config, &cli)?; let repo = { let bar = progressbars.repo_loading(); @@ -65,7 +64,9 @@ async fn main() -> Result<()> { repo }; + let db_connection_config = crate::db::parse_db_connection_config(&config, &cli); match cli.subcommand() { + ("db", Some(matches)) => db::interface(db_connection_config, matches, &config)?, ("build", Some(matches)) => { let bar_tree_building = progressbars.tree_building(); bar_tree_building.set_length(max_packages); |