use anyhow::Result;
use chrono::Utc;
use fs_err as fs;
use std::path::PathBuf;
pub fn maybe_update(
cfg: &crate::config::Config,
tag: &str,
notes: &str,
disabled: bool,
) -> Result<()> {
if disabled {
return Ok(());
}
let path = cfg
.changelog_path
.clone()
.unwrap_or_else(|| "CHANGELOG.md".into());
let mut out = String::new();
let date = Utc::now().format("%Y-%m-%d").to_string();
out.push_str(&format!("## {} {}\n\n", tag, date));
let mut formatted_notes = String::new();
let mut lines = notes.lines().peekable();
while let Some(line) = lines.next() {
if line.trim().starts_with("### Authors") {
let author_count = notes.matches("\n- ").count();
formatted_notes.push_str("### ");
formatted_notes.push_str(if author_count > 1 {
"Authors\n"
} else {
"Author\n"
});
for l in lines.by_ref() {
if l.trim().is_empty() {
formatted_notes.push('\n');
break;
}
if let Some((name, count_part)) =
l.trim_start_matches("- ").split_once('(')
{
let count_str =
count_part.trim_end_matches(')').trim();
let number = count_str
.split_whitespace()
.next()
.unwrap_or("0")
.parse::<u32>()
.unwrap_or(0);
let plural = if number == 1 {
"commit"
} else {
"commits"
};
formatted_notes.push_str(&format!(
"- {} ({} {})\n",
name.trim(),
number,
plural
));
} else {
formatted_notes.push_str(l);
formatted_notes.push('\n');
}
}
} else {
formatted_notes.push_str(line);
formatted_notes.push('\n');
}
}
out.push_str(&formatted_notes);
out.push('\n');
let p = PathBuf::from(&path);
let existing = if p.exists() {
fs::read_to_string(&p).unwrap_or_default()
} else {
String::new()
};
let mut final_doc = String::new();
if let Some(h) = &cfg.changelog_header {
if !existing.starts_with(h) {
final_doc.push_str(h);
final_doc.push('\n');
final_doc.push('\n');
}
}
final_doc.push_str(&out);
final_doc.push_str(&existing);
fs::write(&p, final_doc)?;
eprintln!("[ok] updated changelog at {}", p.display());
Ok(())
}