use std::collections::HashSet;
use std::path::PathBuf;
use crate::error::Result;
use crate::project::Project;
use super::{g_i64, g_str, Store};
#[derive(Debug, Default)]
pub struct FlushPlan {
pub deletes: Vec<PathBuf>,
pub renames: Vec<(PathBuf, PathBuf)>,
pub writes: Vec<(PathBuf, String)>,
pub retired_write: Option<(PathBuf, String)>,
pub legacy_remove: Option<PathBuf>,
}
impl Store {
pub fn flush_plan(mut self, prj: &Project) -> Result<FlushPlan> {
let rows = self.full_rows()?;
let mut plan = FlushPlan::default();
let surviving: HashSet<i64> = rows.iter().map(|r| r.dkey).collect();
for (dkey, load_path) in &self.loaded {
if !surviving.contains(dkey) {
plan.deletes.push(load_path.clone());
}
}
for r in &rows {
if let Some(orig) = &r.orig_relpath {
if *orig != r.relpath {
plan.renames
.push((self.abspath(orig), self.abspath(&r.relpath)));
}
}
}
for r in &rows {
let text = r.doc.to_text();
let write = match &r.orig_text {
None => true,
Some(orig) => *orig != text,
};
if write {
plan.writes.push((self.abspath(&r.relpath), text));
}
}
let (_, retired) = self.select(
"SELECT rkey, id, num, title FROM retired ORDER BY rkey",
vec![],
)?;
let grew = retired.len() > self.retired_loaded;
if grew || self.retired_legacy {
let mut entries: Vec<(u64, (String, String))> = retired
.iter()
.map(|r| {
let num = g_i64(&r[2]).map(|n| n as u64).unwrap_or(u64::MAX);
let id = g_str(&r[1]).unwrap_or_default();
let title = g_str(&r[3]).unwrap_or_default();
(num, (id, title))
})
.collect();
entries.sort_by_key(|e| e.0); let pairs: Vec<(String, String)> = entries.into_iter().map(|e| e.1).collect();
if !pairs.is_empty() {
plan.retired_write = Some((
crate::retired::path(&prj.base),
crate::retired::serialize(&pairs),
));
}
if self.retired_legacy {
plan.legacy_remove = Some(crate::retired::legacy_path(&prj.base));
}
}
Ok(plan)
}
}