diff options
| author | Micha White <botahamec@outlook.com> | 2025-09-27 08:37:13 -0400 |
|---|---|---|
| committer | Micha White <botahamec@outlook.com> | 2025-09-27 08:37:13 -0400 |
| commit | eb0a3f7a022fa6dce2a43a5427262d54b2001e71 (patch) | |
| tree | 8111c6e6e25660bcbf7910aa65f915495c806818 /src/workarea.rs | |
Working area
Diffstat (limited to 'src/workarea.rs')
| -rw-r--r-- | src/workarea.rs | 74 |
1 files changed, 74 insertions, 0 deletions
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<str>]>, +} + +pub struct WorkFileMetadata { + name: Arc<Path>, + last_modified: Instant, +} + +fn equal_to_path(a: impl AsRef<Path>, b: impl AsRef<Path>) -> bool { + a.as_ref() == b.as_ref() +} +pub fn included_files( + root: impl AsRef<Path>, + ignored_files: Option<&IgnoreFile>, + since: Option<SystemTime>, +) -> std::io::Result<Vec<PathBuf>> { + 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<Path>) -> std::io::Result<Self> { + 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)) + } +} |
