use std::env;
use std::ffi::OsStr;
use std::fs::{create_dir, File};
use std::io::Write;
use std::path::{Path, PathBuf};
use regex::Regex;
#[test]
fn use_searcher() {
let workspace = tempfile::tempdir().unwrap();
setup_files(workspace.path());
let pattern = Regex::new("fo.").unwrap();
let mut builder = grox::Builder::new(&pattern, workspace.path());
builder.set_depth(1);
let searcher = builder.build();
assert!(searcher.is_ok());
let mut locations: Vec<grox::Location> = searcher.unwrap().collect();
assert_eq!(locations.len(), 2);
locations.sort_by_key(|loc| loc.file.file_name().unwrap().to_string_lossy().to_string());
println!("{:?}", locations);
assert_eq!(
&locations[0].file.file_name().unwrap().to_string_lossy(),
"baz.txt"
);
assert_eq!(locations[0].line, 1);
assert_eq!(
&locations[1].file.file_name().unwrap().to_string_lossy(),
"foo.txt"
);
assert_eq!(locations[1].line, 2);
}
#[test]
fn ignore_hidden_files_by_default() {
let workspace = tempfile::tempdir().unwrap();
setup_hidden_file(workspace.path());
let pattern = Regex::new("fo.").unwrap();
let searcher = grox::Builder::new(&pattern, workspace.path()).build();
assert!(searcher.is_ok());
let locations: Vec<grox::Location> = searcher.unwrap().collect();
assert_eq!(locations.len(), 0);
}
#[test]
fn search_hidden_files() {
let workspace = tempfile::tempdir().unwrap();
setup_hidden_file(workspace.path());
let pattern = Regex::new("fo.").unwrap();
let mut builder = grox::Builder::new(&pattern, workspace.path());
builder.set_flags(grox::SEARCH_HIDDEN);
let searcher = builder.build();
assert!(searcher.is_ok());
let locations: Vec<grox::Location> = searcher.unwrap().collect();
assert_eq!(locations.len(), 1);
}
#[test]
fn only_one_match_per_file() {
let workspace = tempfile::tempdir().unwrap();
let mut file = File::create(workspace.path().join("foo.txt")).unwrap();
file.write_all(b"foo\nfoz").unwrap();
let pattern = Regex::new("fo.").unwrap();
let mut builder = grox::Builder::new(&pattern, workspace.path());
builder.set_flags(grox::SINGLE_MATCH);
let searcher = builder.build();
assert!(searcher.is_ok());
let locations: Vec<grox::Location> = searcher.unwrap().collect();
assert_eq!(locations.len(), 1);
}
#[test]
fn only_scan_files_matching_a_pattern() {
let workspace = tempfile::tempdir().unwrap();
setup_files(workspace.path());
let pattern = Regex::new("fo.").unwrap();
let file_pattern = Regex::new("f.z").unwrap();
let mut builder = grox::Builder::new(&pattern, workspace.path());
builder.set_file_pattern(&file_pattern);
builder.set_flags(grox::SEARCH_HIDDEN);
let searcher = builder.build();
assert!(searcher.is_ok());
let locations: Vec<grox::Location> = searcher.unwrap().collect();
assert_eq!(locations.len(), 1);
}
#[test]
fn multiple_matches_per_line() {
let workspace = tempfile::tempdir().unwrap();
let mut file = File::create(workspace.path().join("foo.txt")).unwrap();
file.write_all(b"foo bar foz").unwrap();
let pattern = Regex::new("fo.").unwrap();
let searcher = grox::Builder::new(&pattern, workspace.path()).build().unwrap();
let locations: Vec<grox::Location> = searcher.collect();
assert_eq!(locations.len(), 2);
}
#[test]
fn exclude_dir() {
let workspace = tempfile::tempdir().unwrap();
let subsubdir = setup_files_for_exclusion(workspace.path());
let pattern = Regex::new("text").unwrap();
let mut builder = grox::Builder::new(&pattern, workspace.path());
builder.exclude_dir(subsubdir.to_str().unwrap());
let searcher = builder.build().unwrap();
let locations: Vec<grox::Location> = searcher.collect();
assert_eq!(locations.len(), 1);
let name = locations[0].file.file_name().and_then(OsStr::to_str).unwrap();
assert_eq!(name, "foo.txt");
}
#[test]
fn excluded_dir_can_be_relative() {
let workspace = tempfile::tempdir().unwrap();
let subsubdir = setup_files_for_exclusion(workspace.path());
let pattern = Regex::new("text").unwrap();
let mut builder = grox::Builder::new(&pattern, workspace.path());
let subsubdir = pathdiff::diff_paths(subsubdir, workspace.path()).unwrap();
builder.exclude_dir(subsubdir.to_str().unwrap());
let searcher = builder.build().unwrap();
let locations: Vec<grox::Location> = searcher.collect();
assert_eq!(locations.len(), 1);
}
#[test]
fn trailing_slash_allowed_for_excluded_dir() {
let workspace = tempfile::tempdir().unwrap();
let subsubdir = setup_files_for_exclusion(workspace.path());
let pattern = Regex::new("text").unwrap();
let mut builder = grox::Builder::new(&pattern, workspace.path());
let excluded_dir = format!("{}/", subsubdir.to_str().unwrap());
builder.exclude_dir(&excluded_dir);
let searcher = builder.build().unwrap();
let locations: Vec<grox::Location> = searcher.collect();
assert_eq!(locations.len(), 1);
let name = locations[0]
.file
.file_name()
.and_then(|name| name.to_str())
.unwrap();
assert_eq!(name, "foo.txt");
}
#[test]
fn relative_subdir_locations() {
let workspace = tempfile::tempdir().unwrap();
setup_files(workspace.path());
env::set_current_dir(workspace.path()).unwrap();
let pattern = Regex::new("forget").unwrap();
let directory = PathBuf::from(".");
let mut searcher = grox::Builder::new(&pattern, &directory).build().unwrap();
let location = searcher.next().unwrap();
assert_eq!(location.file.to_string_lossy(), "./subdir/baz.txt");
}
#[test]
fn can_exclude_nonexistent_dir() {
let pattern = Regex::new("foo").unwrap();
let directory = PathBuf::from(".");
let mut builder = grox::Builder::new(&pattern, &directory);
builder.exclude_dir("/doesnt/exist");
assert!(builder.build().is_ok());
}
fn setup_files(workspace: &Path) {
let mut file = File::create(workspace.join("foo.txt")).unwrap();
file.write_all(b"line 1\nsome foo text").unwrap();
let mut file = File::create(workspace.join("bar.txt")).unwrap();
file.write_all(b"bar text").unwrap();
let subdir = workspace.join("subdir");
create_dir(&subdir).unwrap();
let mut file = File::create(subdir.join("baz.txt")).unwrap();
file.write_all(b"forget what you know").unwrap();
let subsubdir = subdir.join("subdir");
create_dir(&subsubdir).unwrap();
let mut file = File::create(subsubdir.join("foz.txt")).unwrap();
file.write_all(b"I dream of you fondly").unwrap();
}
fn setup_hidden_file(workspace: &Path) {
let mut file = File::create(workspace.join(".foo")).unwrap();
file.write_all(b"foo").unwrap();
}
fn setup_files_for_exclusion(workspace: &Path) -> PathBuf {
let subdir = workspace.join("subdir");
create_dir(&subdir).unwrap();
let mut file = File::create(subdir.join("foo.txt")).unwrap();
file.write_all(b"some foo text").unwrap();
let subsubdir = subdir.join("subsubdir");
create_dir(&subsubdir).unwrap();
let mut file = File::create(subsubdir.join("bar.txt")).unwrap();
file.write_all(b"bar text").unwrap();
subsubdir
}