use eyre::Result;
use super::{display_arg, local_time};
use crate::system::history::store::Trigger;
use crate::ui::table::MiseTable;
#[derive(Debug, usage_rs::Args)]
#[usage(visible_alias = "list", verbatim_doc_comment)]
pub(crate) struct HistoryLs {
#[usage(long, short = 'J')]
json: bool,
#[usage(long, short = 'n', default_value_t = 20, default = "20")]
limit: usize,
#[usage(long, value_name = "PATH")]
path: Option<String>,
#[usage(long, value_name = "TRIGGER")]
trigger: Option<String>,
#[usage(long, value_name = "LABEL")]
label: Option<String>,
#[usage(long)]
pending: bool,
}
impl HistoryLs {
pub(crate) async fn run(self) -> Result<()> {
let (store, _tracked, mut entries) = super::open().await?;
if self.pending {
entries = crate::system::history::store::peek_pending_in(store.state_dir())?
.into_iter()
.map(|(_, pending)| crate::system::history::store::Entry {
id: pending.id,
commit: String::new(),
checkpoint: pending.checkpoint,
})
.collect();
}
entries.reverse();
if let Some(label) = &self.label {
entries.retain(|entry| entry.checkpoint.labels.contains(label));
}
if let Some(path) = &self.path {
let path = display_arg(path);
entries.retain(|entry| entry.checkpoint.changes.touches(&path));
}
if let Some(trigger) = &self.trigger {
let Some(trigger) = Trigger::parse(trigger) else {
eyre::bail!("unknown trigger {trigger:?}");
};
entries.retain(|entry| entry.checkpoint.trigger == trigger);
}
if self.limit > 0 {
entries.truncate(self.limit);
}
if self.json {
miseprintln!("{}", serde_json::to_string_pretty(&entries)?);
return Ok(());
}
if entries.is_empty() {
info!("no history checkpoints recorded");
return Ok(());
}
let mut table = MiseTable::new(false, &["ID", "When", "Trigger", "Description", "Files"]);
for entry in &entries {
let checkpoint = &entry.checkpoint;
let files = if checkpoint.tree.available {
let changed = checkpoint.changes.len();
if changed == 0 {
"-".to_string()
} else {
changed.to_string()
}
} else {
"unavailable".to_string()
};
let status = match checkpoint.status() {
Some(status)
if status != crate::system::history::store::OperationStatus::Completed =>
{
format!(" ({})", status.as_str())
}
_ => String::new(),
};
table.add_row(vec![
entry.id.to_string(),
local_time(&checkpoint.created_at),
format!("{}{status}", checkpoint.kind_label()),
checkpoint.description.clone(),
files,
]);
}
table.print()
}
}