use anyhow::{Result, bail};
use clap::Args;
use bob::db::Database;
use super::util::pkg_pattern;
use super::{Col, Formatter, OutputFormat, OutputOptions};
#[derive(Debug, Args)]
pub struct HistoryArgs {
#[arg(short = 'a', long)]
all: bool,
#[arg(short = 'H')]
no_header: bool,
#[arg(short = 'l', long)]
long: bool,
#[arg(short = 'r', long)]
raw: bool,
#[arg(short = 'f', long, value_enum, default_value_t = OutputFormat::Table)]
format: OutputFormat,
#[arg(short = 'o', long_help = bob::HistoryKind::columns_help(), value_delimiter = ',')]
columns: Option<Vec<String>>,
packages: Vec<String>,
}
pub fn run(db: &Database, args: HistoryArgs) -> Result<()> {
print_history(
db,
args.columns.as_deref(),
args.no_header,
args.long,
args.raw,
args.all,
args.format,
&args.packages,
)
}
#[allow(clippy::too_many_arguments)]
fn print_history(
db: &Database,
columns: Option<&[String]>,
no_header: bool,
long: bool,
raw: bool,
all: bool,
format: OutputFormat,
packages: &[String],
) -> Result<()> {
let all_cols = bob::HistoryKind::all_columns();
let default_cols = bob::HistoryKind::default_names();
let cols: Vec<&str> = if columns.is_some() {
columns
.map(|c| c.iter().map(|s| s.as_str()).collect())
.unwrap_or_default()
} else if long {
all_cols.iter().map(|(s, _)| s.as_str()).collect()
} else {
default_cols
};
for col in &cols {
if !all_cols.iter().any(|(c, _)| c == col) {
let names: Vec<&str> = all_cols.iter().map(|(n, _)| n.as_str()).collect();
bail!(
"Unknown column '{}'. Valid columns: {}",
col,
names.join(", ")
);
}
}
let patterns: Vec<regex::Regex> = packages
.iter()
.map(String::as_str)
.map(pkg_pattern)
.collect::<Result<Vec<_>>>()?;
let fmt_cols: Vec<Col> = cols
.iter()
.map(|&name| {
let (_, align) = all_cols.iter().find(|(n, _)| n == name).expect("validated");
Col::new(name.to_string(), *align)
})
.collect();
let mut fmt = Formatter::new(
std::io::stdout().lock(),
fmt_cols,
OutputOptions {
format,
no_header,
raw,
},
);
let mut rows = 0usize;
db.for_each_history(&cols, &patterns, all, |cells| {
rows += 1;
fmt.row(cells);
})?;
if rows == 0 {
if !patterns.is_empty() {
bail!("No history matches the pattern");
}
println!("No build history recorded");
return Ok(());
}
fmt.finish()?;
Ok(())
}