use anyhow::Result;
use crate::models::common::Version;
use crate::services::git;
use crate::services::storage::changelog_storage::ChangelogStorage;
use crate::services::storage::config_storage::ConfigStorage;
use crate::services::storage::task_storage::ListStorage;
use crate::utils::project_paths::ProjectPaths;
pub fn cmd_semver(version_str: String, dry_run: bool, summary: bool, auto: bool) -> Result<()> {
let paths = ProjectPaths::get_paths()?;
let mut storage = ListStorage::new(&paths.todo_file)?;
let mut changelog = ChangelogStorage::new(&paths.changelog_file, storage.project_name())?;
let config_storage = ConfigStorage::new(&paths.config_file)?;
let config = config_storage.get_config();
let version = Version::parse(&version_str)?;
let unversioned_indices: Vec<usize> = storage
.tasks()
.iter()
.enumerate()
.filter(|(_, t)| t.completed && t.completed_at_version.is_none())
.map(|(idx, _)| idx)
.collect();
if unversioned_indices.is_empty() {
println!("Nothing to do: No completed tasks without a version.");
return Ok(());
}
if dry_run {
println!(
"Would assign version {} and move {} task(s) to CHANGELOG.md:",
version,
unversioned_indices.len()
);
for idx in &unversioned_indices {
println!(" [x] {}", storage.tasks()[*idx].description);
}
return Ok(());
}
for idx in &unversioned_indices {
if let Some(task) = storage.tasks_mut().get_mut(*idx) {
task.completed_at_version = Some(version.clone());
}
}
let mut versioned_tasks = Vec::new();
for idx in &unversioned_indices {
versioned_tasks.push(storage.tasks()[*idx].clone());
}
let changes = versioned_tasks
.iter()
.map(crate::models::changes::Change::from)
.collect();
let inserted = changelog.merge_changes_for_version(&version, changes);
let mut removal_indices = unversioned_indices;
removal_indices.sort_unstable_by(|a, b| b.cmp(a));
for idx in removal_indices {
storage.remove_task(idx)?;
}
changelog.save()?;
println!(
"Moved {} task(s) into CHANGELOG.md under version {}",
inserted, version
);
if summary {
println!();
println!("Tasks moved into {}:", version);
for task in versioned_tasks {
println!(" • {}", task.description);
}
}
if auto || config.preferences.auto_commit_todo {
git::commit_tally_files("update TODO/CHANGELOG: set semver")?;
}
Ok(())
}