use std::collections::BTreeSet;
use std::path::Path;
use crate::build::{BuiltSite, asset_count, plural};
use crate::manifest;
pub struct Written {
pub files: usize,
pub attachments: usize,
pub pruned: usize,
}
pub fn write_sites(sites: &[BuiltSite], dest: &Path, rooted: bool) -> Result<Written, String> {
let previous = manifest::read(dest)
.map_err(|e| format!("{}: {e}", dest.join(manifest::MANIFEST).display()))?
.unwrap_or_default();
let mut wrote: BTreeSet<String> = BTreeSet::new();
let mut files = 0usize;
let mut attachments = 0usize;
for built in sites {
let prefix = if rooted {
String::new()
} else {
format!("{}/", built.name)
};
for (rel, bytes) in &built.files {
let key = format!("{prefix}{rel}");
write_file(&dest.join(&key), bytes)?;
wrote.insert(key);
files += 1;
}
for (rel, source) in &built.attachments {
let key = format!("{prefix}{rel}");
let out = dest.join(&key);
if let Some(parent) = out.parent() {
std::fs::create_dir_all(parent)
.map_err(|e| format!("{}: {e}", parent.display()))?;
}
std::fs::copy(source, &out).map_err(|e| format!("{}: {e}", source.display()))?;
wrote.insert(key);
attachments += 1;
}
}
let stale: BTreeSet<String> = previous.difference(&wrote).cloned().collect();
let pruned = manifest::remove(dest, &stale).map_err(|e| format!("{}: {e}", dest.display()))?;
manifest::write(dest, &wrote)
.map_err(|e| format!("{}: {e}", dest.join(manifest::MANIFEST).display()))?;
Ok(Written {
files,
attachments,
pruned,
})
}
fn write_file(path: &Path, bytes: &[u8]) -> Result<(), String> {
if let Some(parent) = path.parent() {
std::fs::create_dir_all(parent).map_err(|e| format!("{}: {e}", parent.display()))?;
}
std::fs::write(path, bytes).map_err(|e| format!("{}: {e}", path.display()))
}
pub fn describe(built: &BuiltSite) -> String {
let withheld = match built.withheld.len() {
0 => String::new(),
n => format!(", {n} withheld"),
};
format!(
"{} — {} page{}, {} asset{}, {} attachment{}{withheld} ({})",
built.name,
built.pages,
plural(built.pages),
asset_count(built),
plural(asset_count(built)),
built.attachments.len(),
plural(built.attachments.len()),
built.audience,
)
}