xbp 10.28.0

XBP is a zero-config build pack that can also interact with proxies, kafka, sockets, synthetic monitors.
Documentation
use std::io::{self, Write};

use rpassword;
use tracing::info;

/// Ask the user for text input and return the trimmed result.
pub fn prompt_for_input(prompt: &str) -> Result<String, String> {
    info!("{}", prompt);
    io::stdout()
        .flush()
        .map_err(|e| format!("Failed to flush stdout: {}", e))?;

    let mut input = String::new();
    io::stdin()
        .read_line(&mut input)
        .map_err(|e| format!("Failed to read input: {}", e))?;

    Ok(input.trim().to_string())
}

/// Ask the user for a password without echoing.
pub fn prompt_for_password(prompt: &str) -> Result<String, String> {
    rpassword::prompt_password(prompt).map_err(|e| format!("Failed to read password: {}", e))
}

/// Resolve a string value from an explicit flag, stored config, or interactive prompt.
pub fn resolve_or_prompt(
    provided: Option<String>,
    stored: &mut Option<String>,
    prompt: &str,
    dirty: &mut bool,
) -> Result<String, String> {
    if let Some(value) = provided {
        if stored.as_ref() != Some(&value) {
            *stored = Some(value.clone());
            *dirty = true;
        }
        return Ok(value);
    }

    if let Some(value) = stored.clone() {
        return Ok(value);
    }

    let value = prompt_for_input(prompt)?;
    *stored = Some(value.clone());
    *dirty = true;
    Ok(value)
}

/// Resolve a password from an explicit flag, stored config, or hidden prompt.
pub fn resolve_or_prompt_password(
    provided: Option<String>,
    stored: &mut Option<String>,
    prompt: &str,
    dirty: &mut bool,
) -> Result<String, String> {
    if let Some(value) = provided {
        if stored.as_ref() != Some(&value) {
            *stored = Some(value.clone());
            *dirty = true;
        }
        return Ok(value);
    }

    if let Some(value) = stored.clone() {
        return Ok(value);
    }

    let value = prompt_for_password(prompt)?;
    *stored = Some(value.clone());
    *dirty = true;
    Ok(value)
}