use std::{fs, path::PathBuf};
use anyhow::Result;
use clap::Args;
use dcbor::prelude::*;
use provenance_mark::{
ProvenanceMarkGenerator, ProvenanceMarkInfo, util::parse_date,
};
use super::{info::InfoArgs, print::OutputFormat};
use crate::utils::read_existing_directory_path;
#[derive(Debug, Args)]
#[group(skip)]
pub struct CommandArgs {
path: PathBuf,
#[arg(short, long, default_value = "Blank.")]
comment: String,
#[arg(short, long, value_parser = parse_date)]
date: Option<Date>,
#[arg(short, long)]
quiet: bool,
#[arg(long, value_enum, default_value_t = OutputFormat::Markdown)]
format: OutputFormat,
#[command(flatten)]
info: InfoArgs,
}
impl crate::exec::Exec for CommandArgs {
fn exec(&self) -> Result<String> {
let path = read_existing_directory_path(&self.path)?;
let generator_path = path.join("generator.json");
let generator_json = fs::read_to_string(&generator_path)?;
let mut generator: ProvenanceMarkGenerator =
serde_json::from_str(&generator_json)?;
let date = self.date.unwrap_or_else(Date::now);
let info = self.info.to_cbor()?;
let mark = match info {
Some(info_cbor) => generator.next(date, Some(info_cbor)),
None => generator.next(date, None::<CBOR>),
};
let mark_info =
ProvenanceMarkInfo::new(mark.clone(), self.comment.clone());
let marks_path = path.join("marks");
let mark_json = serde_json::to_string_pretty(&mark_info)?;
let mark_path = marks_path.join(format!("mark-{}.json", mark.seq()));
fs::write(&mark_path, mark_json)?;
let generator_json = serde_json::to_string_pretty(&generator)?;
fs::write(generator_path, generator_json)?;
let status_line =
format!("Mark {} written to: {}", mark.seq(), mark_path.display());
match self.format {
OutputFormat::Markdown => {
let mut paragraphs: Vec<String> = Vec::new();
if !self.quiet {
paragraphs.push(status_line);
}
paragraphs.push(mark_info.markdown_summary());
Ok(paragraphs.join("\n\n"))
}
OutputFormat::Ur => {
if !self.quiet {
eprintln!("{}", status_line);
}
Ok(mark_info.ur().to_string())
}
OutputFormat::Json => {
if !self.quiet {
eprintln!("{}", status_line);
}
serde_json::to_string_pretty(&mark_info).map_err(Into::into)
}
}
}
}