diff --git a/Cargo.lock b/Cargo.lock index 5819f88..44de7f1 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -312,7 +312,7 @@ dependencies = [ "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", "mio 0.6.19 (registry+https://github.com/rust-lang/crates.io-index)", "mio-extras 2.0.5 (registry+https://github.com/rust-lang/crates.io-index)", - "walkdir 2.2.9 (registry+https://github.com/rust-lang/crates.io-index)", + "walkdir 2.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -425,7 +425,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "walkdir" -version = "2.2.9" +version = "2.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "same-file 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", @@ -446,6 +446,7 @@ dependencies = [ "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "nix 0.15.0 (registry+https://github.com/rust-lang/crates.io-index)", "notify 4.0.14 (registry+https://github.com/rust-lang/crates.io-index)", + "walkdir 2.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -547,7 +548,7 @@ dependencies = [ "checksum unicode-width 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "7007dbd421b92cc6e28410fe7362e2e0a2503394908f417b68ec8d1c364c4e20" "checksum unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "826e7639553986605ec5979c7dd957c7895e93eabed50ab2ffa7f6128a75097c" "checksum void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d" -"checksum walkdir 2.2.9 (registry+https://github.com/rust-lang/crates.io-index)" = "9658c94fa8b940eab2250bd5a457f9c48b748420d71293b165c8cdbe2f55f71e" +"checksum walkdir 2.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "777182bc735b6424e1a57516d35ed72cb8019d85c8c9bf536dccb3445c1a2f7d" "checksum winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a" "checksum winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)" = "8093091eeb260906a183e6ae1abdba2ef5ef2257a21801128899c3fc699229c6" "checksum winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc" diff --git a/Cargo.toml b/Cargo.toml index 09009f8..53eb2a9 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -31,6 +31,7 @@ lazy_static = "1.1.0" log = "0.4.4" notify = "4.0.13" derive_builder = "0.9.0" +walkdir = "2.3.1" [dependencies.clap] version = "2.32.0" diff --git a/src/gitignore.rs b/src/gitignore.rs index 11c636d..6bc733c 100644 --- a/src/gitignore.rs +++ b/src/gitignore.rs @@ -1,11 +1,13 @@ extern crate globset; +extern crate walkdir; use globset::{GlobBuilder, GlobSet, GlobSetBuilder}; -use std::collections::HashSet; + use std::fs; use std::io; use std::io::Read; use std::path::{Path, PathBuf}; +use walkdir::WalkDir; pub struct Gitignore { files: Vec, @@ -43,39 +45,43 @@ enum MatchResult { pub fn load(paths: &[PathBuf]) -> Gitignore { let mut files = vec![]; - let mut checked_dirs = HashSet::new(); for path in paths { let mut p = path.to_owned(); - loop { - if !checked_dirs.contains(&p) { - checked_dirs.insert(p.clone()); - - let gitignore_path = p.join(".gitignore"); - if gitignore_path.exists() { - if let Ok(f) = GitignoreFile::new(&gitignore_path) { - debug!("Loaded {:?}", gitignore_path); - files.push(f); - } else { - debug!("Unable to load {:?}", gitignore_path); - } - } - } - + // scan parent directories up to a root .git folder + let top_level_git_dir = loop { // Stop if we see a .git directory if let Ok(metadata) = p.join(".git").metadata() { if metadata.is_dir() { - break; + break Some(path); } } if p.parent().is_none() { - break; + break None; } + }; - p.pop(); + if let Some(root) = top_level_git_dir { + // scan in subdirectories + for entry in WalkDir::new(root) + .into_iter() + .filter_map(Result::ok) + .filter(|e| e.file_type().is_file()) + .filter(|e| e.file_name() == ".gitignore") + { + let gitignore_path = entry.path(); + if let Ok(f) = GitignoreFile::new(&gitignore_path) { + debug!("Loaded {:?}", gitignore_path); + files.push(f); + } else { + debug!("Unable to load {:?}", gitignore_path); + } + } } + + p.pop(); } Gitignore::new(files)