use std::str::FromStr;
use clap::Args;
use crate::config::find_bmo_dir;
use crate::db::{Repository, open_db};
use crate::model::{IssueFilter, Status};
#[derive(Args)]
pub struct TruncateArgs {
#[arg(short, long, value_name = "STATUS")]
pub status: Vec<String>,
#[arg(long, conflicts_with = "status")]
pub all: bool,
#[arg(long)]
pub yes: bool,
}
impl TruncateArgs {
pub fn get_statuses(&self) -> anyhow::Result<Vec<Status>> {
if self.all {
Ok(Status::all().to_vec())
} else if !self.status.is_empty() {
self.status
.iter()
.map(|s| {
Status::from_str(s)
.map_err(|e| anyhow::anyhow!("invalid status {:?}: {}", s, e))
})
.collect()
} else {
Ok(vec![Status::Done])
}
}
}
pub fn run(args: &TruncateArgs, json: bool, db: Option<String>) -> anyhow::Result<()> {
let db_path = if let Some(path) = db {
std::path::PathBuf::from(path)
} else {
find_bmo_dir()?.join("issues.db")
};
let repo = open_db(&db_path)?;
let statuses: Vec<Status> = if args.all {
Status::all().to_vec()
} else if !args.status.is_empty() {
args.get_statuses()?
} else {
vec![Status::Done]
};
let count = if args.all {
repo.count_issues(IssueFilter::all())?
} else {
repo.count_issues(IssueFilter {
status: Some(statuses.clone()),
..Default::default()
})?
};
if count == 0 {
if json {
let envelope = serde_json::json!({
"ok": true,
"data": { "deleted": 0, "message": "Nothing to delete." },
});
println!("{}", serde_json::to_string_pretty(&envelope)?);
} else {
println!("Nothing to delete.");
}
return Ok(());
}
if !args.yes {
if args.all {
eprint!(
"Delete ALL {} issue(s) permanently? This cannot be undone. [y/N] ",
count
);
} else if statuses == [Status::Done] {
eprint!("Delete {} done issue(s) permanently? [y/N] ", count);
} else {
let labels: Vec<&str> = statuses.iter().map(|s| s.label()).collect();
eprint!(
"Delete {} issue(s) with status [{}]? [y/N] ",
count,
labels.join(", ")
);
}
let mut input = String::new();
std::io::stdin().read_line(&mut input)?;
if !input.trim().eq_ignore_ascii_case("y") {
eprintln!("Aborted.");
return Ok(());
}
}
let deleted = if args.all {
repo.truncate_all_issues()?
} else {
repo.truncate_issues(&statuses)?
};
let msg = format!("Deleted {} issue(s).", deleted);
if json {
let envelope = serde_json::json!({
"ok": true,
"data": { "deleted": deleted, "message": msg },
});
println!("{}", serde_json::to_string_pretty(&envelope)?);
} else {
println!("{}", msg);
}
Ok(())
}