From eb0a3f7a022fa6dce2a43a5427262d54b2001e71 Mon Sep 17 00:00:00 2001 From: Micha White Date: Sat, 27 Sep 2025 08:37:13 -0400 Subject: Working area --- src/workarea.rs | 74 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 74 insertions(+) create mode 100644 src/workarea.rs (limited to 'src/workarea.rs') diff --git a/src/workarea.rs b/src/workarea.rs new file mode 100644 index 0000000..d5d2e13 --- /dev/null +++ b/src/workarea.rs @@ -0,0 +1,74 @@ +use std::fs::File; +use std::io::{BufRead, BufReader}; +use std::ops::Deref; +use std::path::{Path, PathBuf}; +use std::sync::Arc; +use std::time::{Instant, SystemTime}; + +use walkdir::WalkDir; + +pub struct IgnoreFile { + globs: Arc<[Arc]>, +} + +pub struct WorkFileMetadata { + name: Arc, + last_modified: Instant, +} + +fn equal_to_path(a: impl AsRef, b: impl AsRef) -> bool { + a.as_ref() == b.as_ref() +} +pub fn included_files( + root: impl AsRef, + ignored_files: Option<&IgnoreFile>, + since: Option, +) -> std::io::Result> { + let mut files = Vec::new(); + + let walker = WalkDir::new(root).into_iter().filter_entry(|entry| { + !equal_to_path(entry.path(), ".pj") + && !equal_to_path(entry.path(), ".ignore") + && entry + .metadata() + .ok() + .is_some_and(|metadata| metadata.is_file()) + && ignored_files + .is_none_or(|file| !file.should_ignore(entry.path().to_string_lossy().deref())) + && since + .zip(entry.metadata().ok()) + .and_then(|(since, metadata)| { + metadata.modified().ok().map(|modified| (since, modified)) + }) + .is_none_or(|(since, modified)| since < modified) + }); + + for entry in walker { + files.push(entry?.into_path()); + } + + Ok(files) +} + +impl IgnoreFile { + fn open(root: impl AsRef) -> std::io::Result { + let mut globs = Vec::new(); + globs.push(String::from(".pj/")); + + let ignore_file = Path::join(root.as_ref(), ".ignore"); + let ignore_file = BufReader::new(File::open(ignore_file)?); + for line in ignore_file.lines() { + globs.push(line?); + } + + Ok(Self { + globs: globs.iter().map(|s| s.deref().into()).collect(), + }) + } + + fn should_ignore(&self, path: &str) -> bool { + self.globs + .iter() + .any(|glob| fast_glob::glob_match(&**glob, path)) + } +} -- cgit v1.2.3