use std::{collections::HashSet, fs, path::Path};
use crate::{
object::ChangeId,
store::{Result, atomic::write_file_atomic},
};
pub struct ShallowInfo {
path: std::path::PathBuf,
shallow_states: HashSet<ChangeId>,
}
impl ShallowInfo {
pub fn load(heddle_dir: &Path) -> Result<Self> {
let path = heddle_dir.join("shallow");
let shallow_states = if path.exists() {
let contents = fs::read_to_string(&path)?;
contents
.lines()
.filter_map(|line| {
let line = line.trim();
if line.is_empty() || line.starts_with('#') {
None
} else {
ChangeId::parse(line).ok()
}
})
.collect()
} else {
HashSet::new()
};
Ok(Self {
path,
shallow_states,
})
}
pub fn is_shallow(&self, id: &ChangeId) -> bool {
self.shallow_states.contains(id)
}
pub fn shallow_states(&self) -> &HashSet<ChangeId> {
&self.shallow_states
}
pub fn add_shallow(&mut self, id: ChangeId) -> Result<()> {
if self.shallow_states.insert(id) {
self.save()?;
}
Ok(())
}
pub fn remove_shallow(&mut self, id: &ChangeId) -> Result<()> {
if self.shallow_states.remove(id) {
self.save()?;
}
Ok(())
}
fn save(&self) -> Result<()> {
let contents: String = self
.shallow_states
.iter()
.map(|id| format!("{}\n", id.to_string_full()))
.collect();
write_file_atomic(&self.path, contents.as_bytes())?;
Ok(())
}
}
#[cfg(test)]
mod tests {
use tempfile::TempDir;
use super::*;
#[test]
fn test_shallow_save_rewrites_file_without_temp_residue() {
let temp_dir = TempDir::new().unwrap();
let heddle_dir = temp_dir.path().join(".heddle");
fs::create_dir_all(&heddle_dir).unwrap();
let mut shallow = ShallowInfo::load(&heddle_dir).unwrap();
let id = ChangeId::generate();
shallow.add_shallow(id).unwrap();
let reloaded = ShallowInfo::load(&heddle_dir).unwrap();
assert!(reloaded.is_shallow(&id));
let temp_entries = fs::read_dir(&heddle_dir)
.unwrap()
.filter_map(|entry| entry.ok())
.filter(|entry| entry.file_name().to_string_lossy().contains(".tmp-"))
.count();
assert_eq!(temp_entries, 0);
}
}