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))
}
}
|