use std::cell::RefCell;
use std::collections::BTreeSet;
use std::fs;
use std::io::ErrorKind;
use std::path::{Path, PathBuf};
use super::construct::directory_error;
use super::error::StoreError;
pub fn drain_and_fence(set: &RefCell<BTreeSet<PathBuf>>) -> Result<(), StoreError> {
let dirs = std::mem::take(&mut *set.borrow_mut());
let mut remaining = dirs.into_iter();
while let Some(dir) = remaining.next() {
let synced = crate::fence::sync_dir_entry(&dir);
if let Err(error) = synced {
let mut pending = set.borrow_mut();
pending.insert(dir);
pending.extend(remaining);
return Err(StoreError::Io(error));
}
}
Ok(())
}
pub fn ensure_prefix_dir(prefix_dir: &Path) -> Result<bool, StoreError> {
match fs::metadata(prefix_dir) {
Ok(metadata) if metadata.is_dir() => Ok(false),
Ok(_metadata) => Err(StoreError::NotADirectory {
path: prefix_dir.to_path_buf(),
}),
Err(error) if error.kind() == ErrorKind::NotFound => {
#[cfg(test)]
let reservation = crate::fence::journal::reserve_create_dir(prefix_dir);
match fs::create_dir(prefix_dir) {
Ok(()) => {
#[cfg(test)]
reservation.commit();
Ok(true)
}
Err(error) if error.kind() == ErrorKind::AlreadyExists => {
#[cfg(test)]
reservation.cancel();
Ok(true)
}
Err(error) => {
#[cfg(test)]
reservation.cancel();
Err(directory_error(error, prefix_dir))
}
}
}
Err(error) => Err(directory_error(error, prefix_dir)),
}
}