summaryrefslogtreecommitdiffstats
path: root/src/git_ignore.rs
diff options
context:
space:
mode:
authorCanop <cano.petrole@gmail.com>2018-12-30 18:57:08 +0100
committerCanop <cano.petrole@gmail.com>2018-12-30 18:57:08 +0100
commit79cc0ce33a4f0600cf9607d5e3a615b1a227ce12 (patch)
treed427ef712cb7a209c7163bdf1bda36b9e1a46717 /src/git_ignore.rs
parenta37b04b914a09051c621c391a1d46e6979c2c95e (diff)
gitignore respect togglable and available as cli arg
Diffstat (limited to 'src/git_ignore.rs')
-rw-r--r--src/git_ignore.rs33
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;
}
}