use crate::private_storage::create_private_directory_all;
use crate::standards_review_entry::SHORT_SHA_LENGTH;
use std::io::Write;
use std::path::Path;
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum Delivery {
Appended,
AlreadyThere,
}
fn token(sha: &str) -> String {
return sha.chars().take(SHORT_SHA_LENGTH).collect();
}
pub fn names_commit(log: &Path, sha: &str) -> bool {
return std::fs::read_to_string(log).is_ok_and(|text| return text.contains(token(sha).as_str()));
}
fn append_whole(log: &Path, text: &str) -> std::io::Result<()> {
if let Some(directory) = log.parent() {
create_private_directory_all(directory)?;
}
let mut options: std::fs::OpenOptions = std::fs::OpenOptions::new();
options.append(true).create(true);
#[cfg(unix)]
{
use std::os::unix::fs::OpenOptionsExt;
options.mode(crate::private_storage::PRIVATE_FILE_MODE).custom_flags(libc::O_NOFOLLOW);
}
let mut file: std::fs::File = options.open(log)?;
return file.write_all(text.as_bytes());
}
pub fn deliver(log: &Path, sha: &str, text: &str) -> Result<Delivery, String> {
let current: String = match std::fs::read_to_string(log) {
Ok(found) => found,
Err(error) if error.kind() == std::io::ErrorKind::NotFound => String::new(),
Err(error) => return Err(format!("reading {} failed: {error}", log.display())),
};
if current.contains(token(sha).as_str()) {
return Ok(Delivery::AlreadyThere);
}
append_whole(log, text).map_err(|error| return format!("appending to {} failed: {error}", log.display()))?;
return Ok(Delivery::Appended);
}
#[cfg(test)]
#[path = "standards_review_append_tests.rs"]
mod tests;