use crate::release::change::ChangeFragmentFile;
#[derive(Debug, Clone, PartialEq, Eq)]
pub(crate) struct ArchiveSet {
pub(crate) sources: Vec<String>,
pub(crate) destination: String,
}
pub(crate) fn compute_archive_set(
fragments: &[ChangeFragmentFile],
transaction_id: &str,
) -> ArchiveSet {
let mut sources: Vec<String> = fragments
.iter()
.map(|f| format!("changes/{}", f.file_name))
.collect();
sources.sort();
ArchiveSet {
sources,
destination: format!("changes/archive/{transaction_id}"),
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::release::change::{ChangeEntry, ChangeKind};
fn fragment(name: &str, units: &[&str]) -> ChangeFragmentFile {
ChangeFragmentFile {
file_name: name.to_string(),
entries: units
.iter()
.map(|u| ChangeEntry {
unit: u.to_string(),
kind: ChangeKind::Compatible,
summary: "test".to_string(),
})
.collect(),
}
}
#[test]
fn computes_archive_set() {
let fragments = vec![
fragment("001-auth-fix.toml", &["arcature-auth"]),
fragment("002-db-break.toml", &["arcature-db"]),
];
let set = compute_archive_set(&fragments, "2026-08-15.01");
assert_eq!(set.destination, "changes/archive/2026-08-15.01");
assert_eq!(set.sources.len(), 2);
assert_eq!(set.sources[0], "changes/001-auth-fix.toml");
assert_eq!(set.sources[1], "changes/002-db-break.toml");
}
#[test]
fn empty_fragments_produce_empty_set() {
let set = compute_archive_set(&[], "2026-08-15.01");
assert_eq!(set.destination, "changes/archive/2026-08-15.01");
assert!(set.sources.is_empty());
}
#[test]
fn sources_are_sorted() {
let fragments = vec![fragment("zzz.toml", &["a"]), fragment("aaa.toml", &["b"])];
let set = compute_archive_set(&fragments, "2026-08-15.01");
assert_eq!(set.sources[0], "changes/aaa.toml");
assert_eq!(set.sources[1], "changes/zzz.toml");
}
}