added interactive mode (#44)

Co-authored-by: kjuulh <contact@kjuulh.io>
Reviewed-on: #44
This commit is contained in:
Kasper Juul Hermansen 2022-12-01 08:51:52 +00:00
parent c00b3a97d2
commit 0dedf9268d
8 changed files with 117 additions and 5 deletions

View File

@ -66,6 +66,15 @@ pub fn execute_cmd() -> Command {
.default_value("true")
.required(false),
)
.arg(
Arg::new("interactive")
.long("interactive")
.short('i')
.action(ArgAction::Set)
.env("OCTOPUSH_INTERACTIVE")
.default_value("false")
.required(false),
)
}
pub async fn execute_subcommand(args: &ArgMatches) -> eyre::Result<()> {
@ -84,6 +93,11 @@ pub async fn execute_subcommand(args: &ArgMatches) -> eyre::Result<()> {
.ok_or(eyre::anyhow!("--dry-run is required"))?
.parse()?;
let interactive: bool = args
.get_one::<String>("interactive")
.ok_or(eyre::anyhow!("--interactive is required"))?
.parse()?;
if dryrun {
tracing::info!("running in dry-run mode");
}
@ -123,21 +137,21 @@ pub async fn execute_subcommand(args: &ArgMatches) -> eyre::Result<()> {
if let Some(git) = &select.git {
service_register
.git_selector
.run(git, &action_path, &action, dryrun)
.run(git, &action_path, &action, dryrun, interactive)
.await?;
}
if let Some(gitea) = &select.gitea {
service_register
.gitea_selector
.run(gitea, &action_path, &action, dryrun)
.run(gitea, &action_path, &action, dryrun, interactive)
.await?;
}
if let Some(github) = &select.github {
service_register
.github_selector
.run(github, &action_path, &action, dryrun)
.run(github, &action_path, &action, dryrun, interactive)
.await?;
}
}

View File

@ -5,3 +5,4 @@ pub mod schema;
pub mod selectors;
mod shell;
pub mod storage;
pub mod ui;

View File

@ -6,18 +6,21 @@ use crate::{
executor::executor::DynExecutor,
git::DynGitProvider,
schema::models::{Action, Git},
ui::DynUI,
};
pub struct GitSelector {
git_provider: DynGitProvider,
executor: DynExecutor,
ui: DynUI,
}
impl GitSelector {
pub fn new(git_provider: DynGitProvider, executor: DynExecutor) -> Self {
pub fn new(git_provider: DynGitProvider, executor: DynExecutor, ui: DynUI) -> Self {
Self {
git_provider,
executor,
ui,
}
}
@ -27,6 +30,7 @@ impl GitSelector {
action_path: &PathBuf,
action: &Action,
dryrun: bool,
interactive: bool,
) -> eyre::Result<()> {
tracing::info!("fetching repos");
for repo in &git.repositories {
@ -46,6 +50,10 @@ impl GitSelector {
continue;
}
if interactive {
self.ui.confirm().await?;
}
if let Some(push) = &git.push {
self.git_provider
.push_branch(repo, &push.branch.name)

View File

@ -6,12 +6,14 @@ use crate::{
executor::executor::DynExecutor,
git::{gitea::DynGiteaProvider, DynGitProvider},
schema::models::{Action, Gitea},
ui::DynUI,
};
pub struct GiteaSelector {
gitea_provider: DynGiteaProvider,
git_provider: DynGitProvider,
executor: DynExecutor,
ui: DynUI,
}
impl GiteaSelector {
@ -19,11 +21,13 @@ impl GiteaSelector {
gitea_provider: DynGiteaProvider,
git_provider: DynGitProvider,
executor: DynExecutor,
ui: DynUI,
) -> Self {
Self {
gitea_provider,
git_provider,
executor,
ui,
}
}
@ -33,6 +37,7 @@ impl GiteaSelector {
action_path: &PathBuf,
action: &Action,
dryrun: bool,
interactive: bool,
) -> eyre::Result<()> {
tracing::info!("fetching repos");
for repo in &git.repositories {
@ -52,6 +57,10 @@ impl GiteaSelector {
continue;
}
if interactive {
self.ui.confirm().await?;
}
if let Some(push) = &git.push {
self.git_provider
.push_branch(repo, &push.pull_request.name)

View File

@ -6,12 +6,14 @@ use crate::{
executor::executor::DynExecutor,
git::{github::DynGitHubProvider, DynGitProvider},
schema::models::{Action, GitHub},
ui::DynUI,
};
pub struct GitHubSelector {
github_provider: DynGitHubProvider,
git_provider: DynGitProvider,
executor: DynExecutor,
ui: DynUI,
}
impl GitHubSelector {
@ -19,11 +21,13 @@ impl GitHubSelector {
github_provider: DynGitHubProvider,
git_provider: DynGitProvider,
executor: DynExecutor,
ui: DynUI,
) -> Self {
Self {
github_provider,
git_provider,
executor,
ui,
}
}
@ -33,6 +37,7 @@ impl GitHubSelector {
action_path: &PathBuf,
action: &Action,
dryrun: bool,
interactive: bool,
) -> eyre::Result<()> {
tracing::info!("fetching repos");
for repo in &git.repositories {
@ -52,6 +57,10 @@ impl GitHubSelector {
continue;
}
if interactive {
self.ui.confirm().await?;
}
if let Some(push) = &git.push {
self.git_provider
.push_branch(repo, &push.pull_request.name)

View File

@ -0,0 +1,12 @@
pub mod terminal_ui;
use std::sync::Arc;
use async_trait::async_trait;
#[async_trait]
pub trait UI {
async fn confirm(&self) -> eyre::Result<()>;
}
pub type DynUI = Arc<dyn UI + Send + Sync>;

View File

@ -0,0 +1,47 @@
use std::{
io::{self, Write},
process::exit,
};
use async_trait::async_trait;
use super::UI;
pub struct TerminalUI {}
impl TerminalUI {
pub fn new() -> Self {
Self {}
}
pub async fn query_console(&self) -> eyre::Result<()> {
print!("Continue? ([Y]es/[N]o): ");
std::io::stdout().lock().flush()?;
let mut input = String::new();
let _ = io::stdin().read_line(&mut input)?;
if input.to_lowercase().starts_with("y") {
return Ok(());
} else if input.to_lowercase().starts_with("n") {
exit(0)
} else {
Err(eyre::anyhow!("input not valid"))
}
}
}
#[async_trait]
impl UI for TerminalUI {
async fn confirm(&self) -> eyre::Result<()> {
match self.query_console().await {
Ok(_) => Ok(()),
Err(e) => {
if e.to_string().starts_with("input not valid") {
self.query_console().await
} else {
Err(e)
}
}
}
}
}

View File

@ -22,6 +22,7 @@ use octopush_core::{
git_selector::GitSelector, gitea_selector::GiteaSelector, github_selector::GitHubSelector,
},
storage::{local::LocalStorageEngine, DynStorageEngine},
ui::{terminal_ui::TerminalUI, DynUI},
};
pub struct ServiceRegister {
@ -35,6 +36,7 @@ pub struct ServiceRegister {
pub gitea_selector: Arc<GiteaSelector>,
pub github_provider: DynGitHubProvider,
pub github_selector: Arc<GitHubSelector>,
pub ui: DynUI,
}
impl ServiceRegister {
@ -57,11 +59,19 @@ impl ServiceRegister {
storage_engine.clone(),
gitea_client.clone(),
));
let git_selector = Arc::new(GitSelector::new(git_provider.clone(), executor.clone()));
let ui = Arc::new(TerminalUI::new());
let git_selector = Arc::new(GitSelector::new(
git_provider.clone(),
executor.clone(),
ui.clone(),
));
let gitea_selector = Arc::new(GiteaSelector::new(
gitea_provider.clone(),
git_provider.clone(),
executor.clone(),
ui.clone(),
));
let github_client = Arc::new(DefaultGitHubClient::new(&github_client_options)?);
let github_provider = Arc::new(DefaultGitHubProvider::new(
@ -73,6 +83,7 @@ impl ServiceRegister {
github_provider.clone(),
git_provider.clone(),
executor.clone(),
ui.clone(),
));
Ok(Self {
@ -86,6 +97,7 @@ impl ServiceRegister {
gitea_selector,
github_provider,
github_selector,
ui,
})
}