summaryrefslogtreecommitdiff
path: root/src/workarea.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/workarea.rs')
-rw-r--r--src/workarea.rs74
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))
+ }
+}