use std::path::Path;
pub fn read_working_file(repo_path: &Path, rel_path: &str) -> std::io::Result<Option<String>> {
match std::fs::read(repo_path.join(rel_path)) {
Ok(bytes) => Ok(Some(String::from_utf8_lossy(&bytes).into_owned())),
Err(e) if e.kind() == std::io::ErrorKind::NotFound => Ok(None),
Err(e) => Err(e),
}
}
pub fn read_working_file_bytes(
repo_path: &Path,
rel_path: &str,
) -> std::io::Result<Option<Vec<u8>>> {
match std::fs::read(repo_path.join(rel_path)) {
Ok(bytes) => Ok(Some(bytes)),
Err(e) if e.kind() == std::io::ErrorKind::NotFound => Ok(None),
Err(e) => Err(e),
}
}
pub fn working_file_is_binary(repo_path: &Path, rel_path: &str) -> bool {
use std::io::Read;
let Ok(f) = std::fs::File::open(repo_path.join(rel_path)) else {
return false;
};
let mut buf = Vec::with_capacity(8192);
if f.take(8192).read_to_end(&mut buf).is_err() {
return false;
}
buf.contains(&0)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn reads_present_file_and_none_for_absent() {
let dir = tempfile::tempdir().unwrap();
std::fs::write(dir.path().join("a.txt"), "hello\n").unwrap();
assert_eq!(
read_working_file(dir.path(), "a.txt").unwrap().as_deref(),
Some("hello\n")
);
assert_eq!(read_working_file(dir.path(), "missing.txt").unwrap(), None);
}
#[test]
fn bytes_variant_round_trips_and_none_for_absent() {
let dir = tempfile::tempdir().unwrap();
std::fs::write(dir.path().join("b.bin"), [0u8, 1, 2, 255]).unwrap();
assert_eq!(
read_working_file_bytes(dir.path(), "b.bin").unwrap(),
Some(vec![0, 1, 2, 255])
);
assert_eq!(read_working_file_bytes(dir.path(), "nope").unwrap(), None);
}
#[test]
fn binary_detection_flags_nul_and_clears_text() {
let dir = tempfile::tempdir().unwrap();
std::fs::write(dir.path().join("t.txt"), "plain text\n").unwrap();
std::fs::write(dir.path().join("b.bin"), [b'x', 0, b'y']).unwrap();
assert!(!working_file_is_binary(dir.path(), "t.txt"));
assert!(working_file_is_binary(dir.path(), "b.bin"));
assert!(!working_file_is_binary(dir.path(), "absent"));
}
#[test]
fn binary_detection_scans_the_full_8kib_window() {
let dir = tempfile::tempdir().unwrap();
let mut data = vec![b'a'; 8000];
data.push(0);
std::fs::write(dir.path().join("mid.bin"), &data).unwrap();
assert!(working_file_is_binary(dir.path(), "mid.bin"));
}
#[test]
fn binary_detection_stops_at_8kib() {
let dir = tempfile::tempdir().unwrap();
let mut data = vec![b'a'; 8192];
data.push(0);
std::fs::write(dir.path().join("late.bin"), &data).unwrap();
assert!(!working_file_is_binary(dir.path(), "late.bin"));
}
}