diff options
author | Canop <cano.petrole@gmail.com> | 2018-12-30 18:57:08 +0100 |
---|---|---|
committer | Canop <cano.petrole@gmail.com> | 2018-12-30 18:57:08 +0100 |
commit | 79cc0ce33a4f0600cf9607d5e3a615b1a227ce12 (patch) | |
tree | d427ef712cb7a209c7163bdf1bda36b9e1a46717 /src/git_ignore.rs | |
parent | a37b04b914a09051c621c391a1d46e6979c2c95e (diff) |
gitignore respect togglable and available as cli arg
Diffstat (limited to 'src/git_ignore.rs')
-rw-r--r-- | src/git_ignore.rs | 33 |
1 files changed, 23 insertions, 10 deletions
diff --git a/src/git_ignore.rs b/src/git_ignore.rs index 76173c3..33aa4c8 100644 --- a/src/git_ignore.rs +++ b/src/git_ignore.rs @@ -1,3 +1,7 @@ +// implements parsing and applying .gitignore files +// Also manages a stack of such files, because more than one +// can apply for a dir (i.e when entering a directory we +// may add a gitignore file to the stack use glob; use regex::Regex; use std::fs::File; @@ -7,15 +11,15 @@ use std::path::{Path, PathBuf}; // a simple rule of a gitignore file #[derive(Clone)] struct GitIgnoreRule { - ok: bool, // does this rule when matched means the file is good? (usually false) + ok: bool, // does this rule when matched means the file is good? (usually false) + directory: bool, // whether this rule only applies to directories + filename: bool, // does this rule apply to just the filename pattern: glob::Pattern, - directory: bool, - filename: bool, pattern_options: glob::MatchOptions, } impl GitIgnoreRule { - fn from(line: &str) -> Option<GitIgnoreRule> { + fn from(line: &str, dir: &Path) -> Option<GitIgnoreRule> { lazy_static! { static ref RE: Regex = Regex::new( r"(?x) @@ -33,9 +37,12 @@ impl GitIgnoreRule { } if let Some(c) = RE.captures(line) { if let Some(p) = c.get(2) { - let p = p.as_str(); + let mut p = p.as_str().to_string(); let has_separator = p.contains('/'); - if let Ok(pattern) = glob::Pattern::new(p) { + if has_separator && p.starts_with('/') { + p = dir.to_string_lossy().to_string() + &p; + } + if let Ok(pattern) = glob::Pattern::new(&p) { let pattern_options = glob::MatchOptions { case_sensitive: true, // not really sure about this one require_literal_leading_dot: false, @@ -63,20 +70,26 @@ pub struct GitIgnoreFile { impl GitIgnoreFile { pub fn new(path: &Path) -> Result<GitIgnoreFile> { let f = File::open(path)?; + let parent = path.parent().unwrap(); let mut rules: Vec<GitIgnoreRule> = Vec::new(); for line in BufReader::new(f).lines() { - if let Some(rule) = GitIgnoreRule::from(&line?) { + if let Some(rule) = GitIgnoreRule::from(&line?, &parent) { rules.push(rule); } } // the last rule applicable to a path is the right one. So // we reverse the list to easily iterate from the last one to the first one rules.reverse(); - debug!("loaded gif {:?} with {} rules", path, rules.len()); + debug!( + "loaded .gitignore file {:?} with {} rules", + path, + rules.len() + ); Ok(GitIgnoreFile { rules }) } } +// a stack of the gitignore files applying to a directory pub struct GitIgnoreFilter { pub files: Vec<GitIgnoreFile>, } @@ -111,12 +124,12 @@ impl GitIgnoreFilter { } if rule.filename { if rule.pattern.matches_with(filename, &rule.pattern_options) { - debug!("rule matches filename {:?} -> ok={}", path, rule.ok); + //debug!("rule matches filename {:?} -> ok={}", path, rule.ok); return rule.ok; } } else { if rule.pattern.matches_path_with(path, &rule.pattern_options) { - debug!("rule matches path {:?} -> ok={}", path, rule.ok); + //debug!("rule matches path {:?} -> ok={}", path, rule.ok); return rule.ok; } } |