From 1229c05d8ded7287ac4ec4d4d5c443b677cf12e6 Mon Sep 17 00:00:00 2001 From: Cameron Cordes Date: Wed, 20 May 2020 15:38:26 -0400 Subject: [PATCH] Add basic gitignore functionality No support for wildcards and exact matches might screw up nested directories. The Globbing functionality seems like its going to be a pain to properly match up. --- .gitignore | 1 + src/config.rs | 9 ++++++++- src/main.rs | 52 +++++++++++++++++++++++++++++++++++++++++++++----- src/printer.rs | 7 ++++--- 4 files changed, 60 insertions(+), 9 deletions(-) diff --git a/.gitignore b/.gitignore index ea8c4bf..1276c08 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,2 @@ +# comment /target diff --git a/src/config.rs b/src/config.rs index a70f261..ec68fae 100644 --- a/src/config.rs +++ b/src/config.rs @@ -6,6 +6,7 @@ pub struct Config { pub pattern: String, pub ignore_case: bool, pub path: String, + pub use_gitignore: bool, } impl Config { @@ -28,7 +29,12 @@ impl Config { Arg::with_name("path") .help("Path to search in") .index(2) - .default_value("."), + .default_value(""), + ) + .arg( + Arg::with_name("gitignore") + .long("no-gitignore") + .help("Include results that are specified in .gitignore"), ) .get_matches(); @@ -36,6 +42,7 @@ impl Config { pattern: String::from(matches.value_of("pattern").unwrap()), ignore_case: matches.is_present("ignore case"), path: String::from(matches.value_of("path").unwrap()), + use_gitignore: !matches.is_present("gitignore"), } } } diff --git a/src/main.rs b/src/main.rs index 7d87308..40f3bb7 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,6 +1,6 @@ use rack::config::Config; use rack::filematch::*; -use std::fs::{self, File}; +use std::fs::{self, DirEntry, File}; use std::io; use std::io::prelude::*; use std::path::Path; @@ -19,7 +19,9 @@ fn main() { } }; - let results = traverse_dir(&config, path, |config, path| check_file(config, path)); + let results = traverse_dir(&config, path, Option::None, |config, path| { + check_file(config, path) + }); match results { Result::Ok(matches) if matches.len() == 0 => println!("No matches :("), Result::Ok(matches) => print_report(&config, &matches), @@ -30,15 +32,46 @@ fn main() { fn traverse_dir( config: &Config, dir: &Path, + gitignore_entries: Option>, operation: fn(&Config, &Path) -> io::Result, ) -> io::Result> { let mut matches: Vec = Vec::new(); - for entry in fs::read_dir(dir)? { + let entries = fs::read_dir(dir)?.collect::>>(); + + let gitignore: Option<&DirEntry> = entries + .iter() + .filter_map(|entry| entry.as_ref().ok()) + .find(|entry| entry.path().file_name().unwrap() == ".gitignore"); + + let gitignore = match gitignore { + Some(g) => { + let file = io::BufReader::new(File::open(g.path())?); + file.lines() + .map(|line| line.unwrap().trim().to_owned()) + .filter(|line| line.len() > 0 && !line.starts_with('#')) + .collect::>() + } + None => gitignore_entries.unwrap_or(Vec::new()), + }; + + for entry in entries { let entry = entry?; let file_type = entry.file_type()?; - + let path = entry.path().to_str().unwrap().to_owned(); if file_type.is_dir() { - let mut results = traverse_dir(&config, &entry.path(), operation)?; + if config.use_gitignore { + let should_ignore = gitignore.iter().find(|&line| path.contains(&line.clone())); + + if should_ignore.unwrap_or(&String::from("")).len() > 0 + || entry.path().to_str().unwrap().contains("/.git") + { + continue; + } + } + + // TODO: Should borrow gitignore instead of cloning.. + let mut results = + traverse_dir(&config, &entry.path(), Some(gitignore.clone()), operation)?; let has_results = results .iter() .filter({ |mat| mat.matches.len() > 0 }) @@ -49,6 +82,15 @@ fn traverse_dir( matches.append(&mut results); } } else { + if config.use_gitignore { + let should_ignore = gitignore.iter().find(|&line| path.contains(&line.clone())); + + if should_ignore.unwrap_or(&String::from("")).len() > 0 + || entry.path().to_str().unwrap().contains("/.git") + { + continue; + } + } let result = operation(&config, &entry.path()); match result { Result::Ok(result) if result.matches.len() > 0 => matches.push(result), diff --git a/src/printer.rs b/src/printer.rs index 1314e77..a855c9f 100644 --- a/src/printer.rs +++ b/src/printer.rs @@ -12,9 +12,9 @@ pub struct ColorPrinter<'a> { pub file_match: &'a FileMatch, } -struct SimplePrinter<'a> { - config: &'a Config, - file_match: &'a FileMatch, +pub struct SimplePrinter<'a> { + pub config: &'a Config, + pub file_match: &'a FileMatch, } impl<'a> Printer for SimplePrinter<'a> { @@ -71,6 +71,7 @@ impl<'a> Printer for ColorPrinter<'a> { }; let mut term = term::stdout().unwrap(); + term.fg(term::color::YELLOW).unwrap(); term.attr(term::Attr::Bold).unwrap(); simple_printer.print_file_name();