depl 2.4.3

Toolkit for a bunch of local and remote CI/CD actions
Documentation
//! `Setup for project` menus.

use colored::Colorize;
use std::collections::{BTreeMap, BTreeSet};

use crate::actions::{Action, DefinedAction, UsedAction};
use crate::bmap;
use crate::entities::custom_command::CustomCommand;
use crate::entities::info::ShortName;
use crate::entities::variables::Variable;
use crate::project::DeployerProjectOptions;

impl UsedAction {
  /// Sets up the project from terminal.
  pub fn prompt_setup_for_project(
    &self,
    variables: &BTreeMap<ShortName, Variable>,
    definitions: &BTreeSet<DefinedAction>,
  ) -> anyhow::Result<Self> {
    let defined = self.definition(definitions)?;

    let used_action = match &defined.action {
      Action::Custom(cmd) => cmd.prompt_setup_for_project(self, variables)?,
      Action::Test(cmd) => cmd.prompt_setup_for_project(self, variables)?,
      Action::Staged(cmd) => cmd.prompt_setup_for_project(self, variables)?,
      Action::Observe(cmd) => cmd.prompt_setup_for_project(self, variables)?,
      Action::Interrupt
      | Action::Patch(_)
      | Action::UseFromStorage { .. }
      | Action::AddToStorage(_)
      | Action::SyncToRemote { .. }
      | Action::SyncFromRemote { .. } => self.clone(),
    };

    Ok(used_action)
  }
}

impl CustomCommand {
  /// Sets up custom command from terminal.
  pub fn prompt_setup_for_project(
    &self,
    used_action: &UsedAction,
    variables: &BTreeMap<ShortName, Variable>,
  ) -> anyhow::Result<UsedAction> {
    use inquire_reorder::Select;

    let mut configured_action = UsedAction {
      title: used_action.title.clone(),
      used: used_action.used.clone(),
      with: Default::default(),
    };

    let mut h = bmap!();
    let mut k = vec![];
    for short_name in variables.keys() {
      let item = format!("Variable `{}`", short_name.as_str());
      k.push(item.clone());
      h.insert(item, short_name);
    }

    for required_substituion in &self.placeholders {
      let selection = Select::new(
        &format!(
          "Select variable to replace `{}` in `{}` shell command (action `{}`{}):",
          required_substituion.green().italic(),
          self.cmd.green(),
          used_action.used.to_str().blue(),
          if let Some(title) = used_action.title.as_deref() {
            format!(" - {}", title.blue())
          } else {
            String::new()
          },
        ),
        k.clone(),
      )
      .prompt_skippable()?;

      if let Some(selection) = selection {
        let selected = h.get(&selection).unwrap();
        configured_action
          .with
          .insert(required_substituion.clone(), (*selected).clone());
      }
    }

    for required_env in &self.env {
      let selection = Select::new(
        &format!(
          "Select variable to pass as environmental `{}` to command `{}` (action `{}`{}):",
          required_env.green().italic(),
          self.cmd.green(),
          used_action.used.to_str().blue(),
          if let Some(title) = used_action.title.as_deref() {
            format!(" - {}", title.blue())
          } else {
            String::new()
          },
        ),
        k.clone(),
      )
      .prompt_skippable()?;

      if let Some(selection) = selection {
        let selected = h.get(&selection).unwrap();
        configured_action.with.insert(required_env.clone(), (*selected).clone());
      }
    }

    Ok(configured_action)
  }
}

/// Collects Pipeline's shortname from terminal.
pub fn specify_pipeline_short_name(config: &mut DeployerProjectOptions, short_name: &mut String) -> anyhow::Result<()> {
  while config.pipelines.iter().any(|p| p.title.as_str() == short_name)
    && !inquire_reorder::Confirm::new(&format!(
      "Do you want to overwrite an existing pipeline `{}` for this project? (y/n)",
      short_name.as_str()
    ))
    .prompt()?
  {
    *short_name = inquire_reorder::Text::new("Write the Pipeline's short name (only for this project) (or hit `esc`):")
      .prompt_skippable()?
      .ok_or_else(|| anyhow::anyhow!("Hitted Escape."))?;
  }

  Ok(())
}