mirror of
https://github.com/watchexec/watchexec.git
synced 2024-11-13 07:41:11 +01:00
Ignore .git, .hg, etc while looking for ignore files
This commit is contained in:
parent
1c388d6b2d
commit
ed6df57aa0
2 changed files with 78 additions and 43 deletions
|
@ -115,34 +115,14 @@ pub async fn from_origin(path: impl AsRef<Path>) -> (Vec<IgnoreFile>, Vec<Error>
|
|||
)
|
||||
.await;
|
||||
|
||||
trace!("create IgnoreFilterer for visiting directories");
|
||||
let mut search_filter = IgnoreFilterer::new(&base, &files)
|
||||
.await
|
||||
.map_err(|err| errors.push(Error::new(ErrorKind::Other, err)))
|
||||
.ok();
|
||||
|
||||
trace!("visiting child directories for ignore files");
|
||||
match dunce::canonicalize(base) {
|
||||
Ok(base) => {
|
||||
let mut dirs = DirTourist::new(base.clone());
|
||||
match DirTourist::new(&base, &files).await {
|
||||
Ok(mut dirs) => {
|
||||
loop {
|
||||
match dirs.next().await {
|
||||
Visit::Done => break,
|
||||
Visit::Skip => continue,
|
||||
Visit::Find(dir) => {
|
||||
if dir == base {
|
||||
trace!(?dir, "dir is the base, continuing");
|
||||
continue;
|
||||
}
|
||||
|
||||
if let Some(sf) = &search_filter {
|
||||
if !sf.check_dir(&dir) {
|
||||
trace!(?dir, "dir is ignored, adding to skip list");
|
||||
dirs.skip(dir);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if discover_file(
|
||||
&mut files,
|
||||
&mut errors,
|
||||
|
@ -152,7 +132,7 @@ pub async fn from_origin(path: impl AsRef<Path>) -> (Vec<IgnoreFile>, Vec<Error>
|
|||
)
|
||||
.await
|
||||
{
|
||||
add_last_file_to_filter(&mut search_filter, &mut files, &mut errors)
|
||||
dirs.add_last_file_to_filter(&mut files, &mut errors)
|
||||
.await;
|
||||
}
|
||||
|
||||
|
@ -165,7 +145,7 @@ pub async fn from_origin(path: impl AsRef<Path>) -> (Vec<IgnoreFile>, Vec<Error>
|
|||
)
|
||||
.await
|
||||
{
|
||||
add_last_file_to_filter(&mut search_filter, &mut files, &mut errors)
|
||||
dirs.add_last_file_to_filter(&mut files, &mut errors)
|
||||
.await;
|
||||
}
|
||||
|
||||
|
@ -178,7 +158,7 @@ pub async fn from_origin(path: impl AsRef<Path>) -> (Vec<IgnoreFile>, Vec<Error>
|
|||
)
|
||||
.await
|
||||
{
|
||||
add_last_file_to_filter(&mut search_filter, &mut files, &mut errors)
|
||||
dirs.add_last_file_to_filter(&mut files, &mut errors)
|
||||
.await;
|
||||
}
|
||||
}
|
||||
|
@ -350,6 +330,7 @@ struct DirTourist {
|
|||
to_visit: Vec<PathBuf>,
|
||||
to_skip: HashSet<PathBuf>,
|
||||
pub errors: Vec<std::io::Error>,
|
||||
filter: IgnoreFilterer,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
|
@ -360,13 +341,23 @@ enum Visit {
|
|||
}
|
||||
|
||||
impl DirTourist {
|
||||
pub fn new(base: PathBuf) -> Self {
|
||||
Self {
|
||||
pub async fn new(base: &Path, files: &[IgnoreFile]) -> Result<Self, Error> {
|
||||
let base = dunce::canonicalize(base)?;
|
||||
trace!("create IgnoreFilterer for visiting directories");
|
||||
let mut filter = IgnoreFilterer::new(&base, files)
|
||||
.await
|
||||
.map_err(|err| Error::new(ErrorKind::Other, err))?;
|
||||
|
||||
filter.add_globs(&["/.git", "/.hg", "/.bzr", "/_darcs", "/.fossil-settings"], Some(base.clone())).await
|
||||
.map_err(|err| Error::new(ErrorKind::Other, err))?;
|
||||
|
||||
Ok(Self {
|
||||
to_visit: vec![base.clone()],
|
||||
base,
|
||||
to_skip: HashSet::new(),
|
||||
errors: Vec::new(),
|
||||
}
|
||||
filter,
|
||||
})
|
||||
}
|
||||
|
||||
pub async fn next(&mut self) -> Visit {
|
||||
|
@ -377,6 +368,12 @@ impl DirTourist {
|
|||
return Visit::Skip;
|
||||
}
|
||||
|
||||
if !self.filter.check_dir(&path) {
|
||||
trace!("path is ignored, adding to skip list");
|
||||
self.skip(path);
|
||||
return Visit::Skip;
|
||||
}
|
||||
|
||||
let mut dir = match read_dir(&path).await {
|
||||
Ok(dir) => dir,
|
||||
Err(err) => {
|
||||
|
@ -405,6 +402,12 @@ impl DirTourist {
|
|||
match entry.file_type().await {
|
||||
Ok(ft) => {
|
||||
if ft.is_dir() {
|
||||
if !self.filter.check_dir(&path) {
|
||||
trace!("path is ignored, adding to skip list");
|
||||
self.skip(path);
|
||||
continue;
|
||||
}
|
||||
|
||||
trace!("found a dir, adding to list");
|
||||
self.to_visit.push(path);
|
||||
} else {
|
||||
|
@ -438,6 +441,18 @@ impl DirTourist {
|
|||
self.to_skip.insert(path);
|
||||
}
|
||||
|
||||
pub(crate) async fn add_last_file_to_filter(
|
||||
&mut self,
|
||||
files: &mut Vec<IgnoreFile>,
|
||||
errors: &mut Vec<Error>,
|
||||
) {
|
||||
if let Some(ig) = files.last() {
|
||||
if let Err(err) = self.filter.add_file(ig).await {
|
||||
errors.push(Error::new(ErrorKind::Other, err));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn must_skip(&self, mut path: &Path) -> bool {
|
||||
if self.to_skip.contains(path) {
|
||||
return true;
|
||||
|
@ -455,17 +470,3 @@ impl DirTourist {
|
|||
false
|
||||
}
|
||||
}
|
||||
|
||||
async fn add_last_file_to_filter(
|
||||
filter: &mut Option<IgnoreFilterer>,
|
||||
files: &mut Vec<IgnoreFile>,
|
||||
errors: &mut Vec<Error>,
|
||||
) {
|
||||
if let Some(igf) = filter.as_mut() {
|
||||
if let Some(ig) = files.last() {
|
||||
if let Err(err) = igf.add_file(ig).await {
|
||||
errors.push(Error::new(ErrorKind::Other, err));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -145,6 +145,14 @@ impl IgnoreFilterer {
|
|||
})?;
|
||||
}
|
||||
|
||||
self.recompile(file.path.clone())?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn recompile(&mut self, file: PathBuf) -> Result<(), RuntimeError> {
|
||||
if let Some(builder) = &mut self.builder {
|
||||
let pre_ignores = self.compiled.num_ignores();
|
||||
let pre_allows = self.compiled.num_whitelists();
|
||||
|
||||
|
@ -152,7 +160,7 @@ impl IgnoreFilterer {
|
|||
let recompiled = builder
|
||||
.build()
|
||||
.map_err(|err| RuntimeError::IgnoreFileGlob {
|
||||
file: file.path.clone(),
|
||||
file,
|
||||
err,
|
||||
})?;
|
||||
|
||||
|
@ -167,6 +175,32 @@ impl IgnoreFilterer {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
/// Adds some globs manually, if the builder is available.
|
||||
///
|
||||
/// Does nothing silently otherwise.
|
||||
pub async fn add_globs(&mut self, globs: &[&str], applies_in: Option<PathBuf>) -> Result<(), RuntimeError> {
|
||||
if let Some(ref mut builder) = self.builder {
|
||||
let _span = trace_span!("loading ignore globs", ?globs).entered();
|
||||
for line in globs {
|
||||
if line.is_empty() || line.starts_with('#') {
|
||||
continue;
|
||||
}
|
||||
|
||||
trace!(?line, "adding ignore line");
|
||||
builder
|
||||
.add_line(applies_in.clone(), line)
|
||||
.map_err(|err| RuntimeError::IgnoreFileGlob {
|
||||
file: "manual glob".into(),
|
||||
err,
|
||||
})?;
|
||||
}
|
||||
|
||||
self.recompile("manual glob".into())?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Check a particular folder path against the ignore set.
|
||||
///
|
||||
/// Returns `false` if the folder should be ignored.
|
||||
|
|
Loading…
Reference in a new issue