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.
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -1 +1,2 @@
|
|||||||
|
# comment
|
||||||
/target
|
/target
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ pub struct Config {
|
|||||||
pub pattern: String,
|
pub pattern: String,
|
||||||
pub ignore_case: bool,
|
pub ignore_case: bool,
|
||||||
pub path: String,
|
pub path: String,
|
||||||
|
pub use_gitignore: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Config {
|
impl Config {
|
||||||
@@ -28,7 +29,12 @@ impl Config {
|
|||||||
Arg::with_name("path")
|
Arg::with_name("path")
|
||||||
.help("Path to search in")
|
.help("Path to search in")
|
||||||
.index(2)
|
.index(2)
|
||||||
.default_value("."),
|
.default_value(""),
|
||||||
|
)
|
||||||
|
.arg(
|
||||||
|
Arg::with_name("gitignore")
|
||||||
|
.long("no-gitignore")
|
||||||
|
.help("Include results that are specified in .gitignore"),
|
||||||
)
|
)
|
||||||
.get_matches();
|
.get_matches();
|
||||||
|
|
||||||
@@ -36,6 +42,7 @@ impl Config {
|
|||||||
pattern: String::from(matches.value_of("pattern").unwrap()),
|
pattern: String::from(matches.value_of("pattern").unwrap()),
|
||||||
ignore_case: matches.is_present("ignore case"),
|
ignore_case: matches.is_present("ignore case"),
|
||||||
path: String::from(matches.value_of("path").unwrap()),
|
path: String::from(matches.value_of("path").unwrap()),
|
||||||
|
use_gitignore: !matches.is_present("gitignore"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
52
src/main.rs
52
src/main.rs
@@ -1,6 +1,6 @@
|
|||||||
use rack::config::Config;
|
use rack::config::Config;
|
||||||
use rack::filematch::*;
|
use rack::filematch::*;
|
||||||
use std::fs::{self, File};
|
use std::fs::{self, DirEntry, File};
|
||||||
use std::io;
|
use std::io;
|
||||||
use std::io::prelude::*;
|
use std::io::prelude::*;
|
||||||
use std::path::Path;
|
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 {
|
match results {
|
||||||
Result::Ok(matches) if matches.len() == 0 => println!("No matches :("),
|
Result::Ok(matches) if matches.len() == 0 => println!("No matches :("),
|
||||||
Result::Ok(matches) => print_report(&config, &matches),
|
Result::Ok(matches) => print_report(&config, &matches),
|
||||||
@@ -30,15 +32,46 @@ fn main() {
|
|||||||
fn traverse_dir(
|
fn traverse_dir(
|
||||||
config: &Config,
|
config: &Config,
|
||||||
dir: &Path,
|
dir: &Path,
|
||||||
|
gitignore_entries: Option<Vec<String>>,
|
||||||
operation: fn(&Config, &Path) -> io::Result<FileMatch>,
|
operation: fn(&Config, &Path) -> io::Result<FileMatch>,
|
||||||
) -> io::Result<Vec<FileMatch>> {
|
) -> io::Result<Vec<FileMatch>> {
|
||||||
let mut matches: Vec<FileMatch> = Vec::new();
|
let mut matches: Vec<FileMatch> = Vec::new();
|
||||||
for entry in fs::read_dir(dir)? {
|
let entries = fs::read_dir(dir)?.collect::<Vec<io::Result<DirEntry>>>();
|
||||||
|
|
||||||
|
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::<Vec<String>>()
|
||||||
|
}
|
||||||
|
None => gitignore_entries.unwrap_or(Vec::new()),
|
||||||
|
};
|
||||||
|
|
||||||
|
for entry in entries {
|
||||||
let entry = entry?;
|
let entry = entry?;
|
||||||
let file_type = entry.file_type()?;
|
let file_type = entry.file_type()?;
|
||||||
|
let path = entry.path().to_str().unwrap().to_owned();
|
||||||
if file_type.is_dir() {
|
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
|
let has_results = results
|
||||||
.iter()
|
.iter()
|
||||||
.filter({ |mat| mat.matches.len() > 0 })
|
.filter({ |mat| mat.matches.len() > 0 })
|
||||||
@@ -49,6 +82,15 @@ fn traverse_dir(
|
|||||||
matches.append(&mut results);
|
matches.append(&mut results);
|
||||||
}
|
}
|
||||||
} else {
|
} 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());
|
let result = operation(&config, &entry.path());
|
||||||
match result {
|
match result {
|
||||||
Result::Ok(result) if result.matches.len() > 0 => matches.push(result),
|
Result::Ok(result) if result.matches.len() > 0 => matches.push(result),
|
||||||
|
|||||||
@@ -12,9 +12,9 @@ pub struct ColorPrinter<'a> {
|
|||||||
pub file_match: &'a FileMatch,
|
pub file_match: &'a FileMatch,
|
||||||
}
|
}
|
||||||
|
|
||||||
struct SimplePrinter<'a> {
|
pub struct SimplePrinter<'a> {
|
||||||
config: &'a Config,
|
pub config: &'a Config,
|
||||||
file_match: &'a FileMatch,
|
pub file_match: &'a FileMatch,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> Printer for SimplePrinter<'a> {
|
impl<'a> Printer for SimplePrinter<'a> {
|
||||||
@@ -71,6 +71,7 @@ impl<'a> Printer for ColorPrinter<'a> {
|
|||||||
};
|
};
|
||||||
|
|
||||||
let mut term = term::stdout().unwrap();
|
let mut term = term::stdout().unwrap();
|
||||||
|
|
||||||
term.fg(term::color::YELLOW).unwrap();
|
term.fg(term::color::YELLOW).unwrap();
|
||||||
term.attr(term::Attr::Bold).unwrap();
|
term.attr(term::Attr::Bold).unwrap();
|
||||||
simple_printer.print_file_name();
|
simple_printer.print_file_name();
|
||||||
|
|||||||
Reference in New Issue
Block a user