use std::path::Path;
use anyhow::Result;
use crate::index::{count_unit_formats, ArchiveIndex, Index};
pub struct SyncResult {
pub unit_count: usize,
pub archive_count: usize,
pub md_count: usize,
pub yaml_count: usize,
pub mixed_formats: bool,
}
pub fn sync(mana_dir: &Path) -> Result<SyncResult> {
let (md_count, yaml_count) = count_unit_formats(mana_dir)?;
let index = Index::build(mana_dir)?;
let unit_count = index.units.len();
index.save(mana_dir)?;
let archive_index = ArchiveIndex::build(mana_dir)?;
let archive_count = archive_index.units.len();
if archive_count > 0 || mana_dir.join("archive.yaml").exists() {
archive_index.save(mana_dir)?;
}
Ok(SyncResult {
unit_count,
archive_count,
md_count,
yaml_count,
mixed_formats: md_count > 0 && yaml_count > 0,
})
}
#[cfg(test)]
mod tests {
use super::*;
use crate::unit::{Status, Unit};
use crate::util::title_to_slug;
use std::fs;
use tempfile::TempDir;
#[test]
fn sync_rebuilds_index() {
let dir = TempDir::new().unwrap();
let mana_dir = dir.path().join(".mana");
fs::create_dir(&mana_dir).unwrap();
let unit1 = Unit::new("1", "Task one");
let unit2 = Unit::new("2", "Task two");
let slug1 = title_to_slug(&unit1.title);
let slug2 = title_to_slug(&unit2.title);
unit1
.to_file(mana_dir.join(format!("1-{}.md", slug1)))
.unwrap();
unit2
.to_file(mana_dir.join(format!("2-{}.md", slug2)))
.unwrap();
let result = sync(&mana_dir).unwrap();
assert_eq!(result.unit_count, 2);
assert!(!result.mixed_formats);
}
#[test]
fn sync_empty_project() {
let dir = TempDir::new().unwrap();
let mana_dir = dir.path().join(".mana");
fs::create_dir(&mana_dir).unwrap();
let result = sync(&mana_dir).unwrap();
assert_eq!(result.unit_count, 0);
assert_eq!(result.archive_count, 0);
}
#[test]
fn sync_rebuilds_archive() {
let dir = TempDir::new().unwrap();
let mana_dir = dir.path().join(".mana");
fs::create_dir(&mana_dir).unwrap();
let archive_dir = mana_dir.join("archive").join("2026").join("03");
fs::create_dir_all(&archive_dir).unwrap();
let mut unit = Unit::new("10", "Archived ten");
unit.status = Status::Closed;
unit.is_archived = true;
let slug = title_to_slug(&unit.title);
unit.to_file(archive_dir.join(format!("10-{}.md", slug)))
.unwrap();
let result = sync(&mana_dir).unwrap();
assert_eq!(result.archive_count, 1);
assert!(mana_dir.join("archive.yaml").exists());
}
}