+
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
103 changes: 93 additions & 10 deletions src/find/matchers/logical_matchers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,9 +35,16 @@ impl Matcher for AndMatcher {
/// place. If the nth sub-matcher returns false, then we immediately return
/// and don't make any further calls.
fn matches(&self, dir_entry: &DirEntry, matcher_io: &mut MatcherIO) -> bool {
self.submatchers
.iter()
.all(|x| x.matches(dir_entry, matcher_io))
for matcher in &self.submatchers {
if !matcher.matches(dir_entry, matcher_io) {
return false;
}
if matcher_io.should_quit() {
break;
}
}

true
}

fn has_side_effects(&self) -> bool {
Expand Down Expand Up @@ -79,9 +86,7 @@ impl AndMatcherBuilder {
// safe to unwrap: we've just checked the size
return self.submatchers.pop().unwrap();
}
let matcher = Box::new(AndMatcher::new(self.submatchers));
self.submatchers = Vec::new();
matcher
AndMatcher::new(self.submatchers).into_box()
}
}

Expand All @@ -104,9 +109,16 @@ impl Matcher for OrMatcher {
/// place. If the nth sub-matcher returns true, then we immediately return
/// and don't make any further calls.
fn matches(&self, dir_entry: &DirEntry, matcher_io: &mut MatcherIO) -> bool {
self.submatchers
.iter()
.any(|x| x.matches(dir_entry, matcher_io))
for matcher in &self.submatchers {
if matcher.matches(dir_entry, matcher_io) {
return true;
}
if matcher_io.should_quit() {
break;
}
}

false
}

fn has_side_effects(&self) -> bool {
Expand Down Expand Up @@ -170,7 +182,7 @@ impl OrMatcherBuilder {
for x in self.submatchers {
submatchers.push(x.build());
}
Box::new(OrMatcher::new(submatchers))
OrMatcher::new(submatchers).into_box()
}
}

Expand All @@ -196,6 +208,9 @@ impl Matcher for ListMatcher {
let mut rc = false;
for matcher in &self.submatchers {
rc = matcher.matches(dir_entry, matcher_io);
if matcher_io.should_quit() {
break;
}
}
rc
}
Expand Down Expand Up @@ -341,9 +356,12 @@ impl Matcher for NotMatcher {

mod tests {
use super::*;
use crate::find::matchers::quit::QuitMatcher;
use crate::find::matchers::tests::get_dir_entry_for;
use crate::find::matchers::{Matcher, MatcherIO};
use crate::find::tests::FakeDependencies;
use std::cell::RefCell;
use std::rc::Rc;
use walkdir::DirEntry;

/// Simple Matcher impl that has side effects
Expand All @@ -359,6 +377,16 @@ mod tests {
}
}

/// Matcher that counts its invocations
struct Counter(Rc<RefCell<u32>>);

impl Matcher for Counter {
fn matches(&self, _: &DirEntry, _: &mut MatcherIO) -> bool {
*self.0.borrow_mut() += 1;
true
}
}

#[test]
fn and_matches_works() {
let abbbc = get_dir_entry_for("test_data/simple", "abbbc");
Expand Down Expand Up @@ -506,4 +534,59 @@ mod tests {
assert!(has_fx.has_side_effects());
assert!(!hasnt_fx.has_side_effects());
}

#[test]
fn and_quit_works() {
let abbbc = get_dir_entry_for("test_data/simple", "abbbc");
let mut builder = AndMatcherBuilder::new();
let deps = FakeDependencies::new();

let before = Rc::new(RefCell::new(0));
let after = Rc::new(RefCell::new(0));
builder.new_and_condition(Counter(before.clone()));
builder.new_and_condition(QuitMatcher);
builder.new_and_condition(Counter(after.clone()));
builder.build().matches(&abbbc, &mut deps.new_matcher_io());

assert_eq!(*before.borrow(), 1);
assert_eq!(*after.borrow(), 0);
}

#[test]
fn or_quit_works() {
let abbbc = get_dir_entry_for("test_data/simple", "abbbc");
let mut builder = OrMatcherBuilder::new();
let deps = FakeDependencies::new();

let before = Rc::new(RefCell::new(0));
let after = Rc::new(RefCell::new(0));
builder.new_and_condition(Counter(before.clone()));
builder.new_or_condition("-o").unwrap();
builder.new_and_condition(QuitMatcher);
builder.new_or_condition("-o").unwrap();
builder.new_and_condition(Counter(after.clone()));
builder.build().matches(&abbbc, &mut deps.new_matcher_io());

assert_eq!(*before.borrow(), 1);
assert_eq!(*after.borrow(), 0);
}

#[test]
fn list_quit_works() {
let abbbc = get_dir_entry_for("test_data/simple", "abbbc");
let mut builder = ListMatcherBuilder::new();
let deps = FakeDependencies::new();

let before = Rc::new(RefCell::new(0));
let after = Rc::new(RefCell::new(0));
builder.new_and_condition(Counter(before.clone()));
builder.new_list_condition().unwrap();
builder.new_and_condition(QuitMatcher);
builder.new_list_condition().unwrap();
builder.new_and_condition(Counter(after.clone()));
builder.build().matches(&abbbc, &mut deps.new_matcher_io());

assert_eq!(*before.borrow(), 1);
assert_eq!(*after.borrow(), 0);
}
}
13 changes: 13 additions & 0 deletions src/find/matchers/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ mod perm;
mod printer;
mod printf;
mod prune;
mod quit;
mod regex;
mod size;
mod time;
Expand All @@ -35,6 +36,7 @@ use self::perm::PermMatcher;
use self::printer::{PrintDelimiter, Printer};
use self::printf::Printf;
use self::prune::PruneMatcher;
use self::quit::QuitMatcher;
use self::regex::RegexMatcher;
use self::size::SizeMatcher;
use self::time::{FileTimeMatcher, FileTimeType, NewerMatcher};
Expand All @@ -46,6 +48,7 @@ use super::{Config, Dependencies};
/// from the file/directory info.
pub struct MatcherIO<'a> {
should_skip_dir: bool,
quit: bool,
deps: &'a dyn Dependencies<'a>,
}

Expand All @@ -54,6 +57,7 @@ impl<'a> MatcherIO<'a> {
MatcherIO {
deps,
should_skip_dir: false,
quit: false,
}
}

Expand All @@ -65,6 +69,14 @@ impl<'a> MatcherIO<'a> {
self.should_skip_dir
}

pub fn quit(&mut self) {
self.quit = true;
}

pub fn should_quit(&self) -> bool {
self.quit
}

pub fn now(&self) -> SystemTime {
self.deps.now()
}
Expand Down Expand Up @@ -382,6 +394,7 @@ fn build_matcher_tree(
Some(PermMatcher::new(args[i])?.into_box())
}
"-prune" => Some(PruneMatcher::new().into_box()),
"-quit" => Some(QuitMatcher.into_box()),
"-not" | "!" => {
if !are_more_expressions(args, i) {
return Err(From::from(format!(
Expand Down
39 changes: 39 additions & 0 deletions src/find/matchers/quit.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
// Copyright 2017 Tavian Barnes
//
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file or at
// https://opensource.org/licenses/MIT.

use walkdir::DirEntry;

use super::{Matcher, MatcherIO};

/// This matcher quits the search immediately.
pub struct QuitMatcher;

impl Matcher for QuitMatcher {
fn matches(&self, _: &DirEntry, matcher_io: &mut MatcherIO) -> bool {
matcher_io.quit();
true
}
}

#[cfg(test)]
mod tests {
use super::*;
use crate::find::matchers::tests::get_dir_entry_for;
use crate::find::matchers::Matcher;
use crate::find::tests::FakeDependencies;

#[test]
fn quits_when_matched() {
let dir = get_dir_entry_for("test_data", "simple");
let deps = FakeDependencies::new();

let mut matcher_io = deps.new_matcher_io();
assert!(!matcher_io.should_quit());
let matcher = QuitMatcher;
assert!(matcher.matches(&dir, &mut matcher_io));
assert!(matcher_io.should_quit());
}
}
41 changes: 36 additions & 5 deletions src/find/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,7 @@ fn process_dir<'a>(
config: &Config,
deps: &'a dyn Dependencies<'a>,
matcher: &dyn matchers::Matcher,
quit: &mut bool,
) -> u64 {
let mut found_count: u64 = 0;
let mut walkdir = WalkDir::new(dir)
Expand All @@ -138,15 +139,18 @@ fn process_dir<'a>(
// Slightly yucky loop handling here :-(. See docs for
// WalkDirIterator::skip_current_dir for explanation.
let mut it = walkdir.into_iter();
loop {
match it.next() {
None => break,
Some(Err(err)) => writeln!(&mut stderr(), "Error: {}: {}", dir, err).unwrap(),
Some(Ok(entry)) => {
while let Some(result) = it.next() {
match result {
Err(err) => writeln!(&mut stderr(), "Error: {}: {}", dir, err).unwrap(),
Ok(entry) => {
let mut matcher_io = matchers::MatcherIO::new(deps);
if matcher.matches(&entry, &mut matcher_io) {
found_count += 1;
}
if matcher_io.should_quit() {
*quit = true;
break;
}
if matcher_io.should_skip_current_dir() {
it.skip_current_dir();
}
Expand All @@ -168,13 +172,18 @@ fn do_find<'a>(args: &[&str], deps: &'a dyn Dependencies<'a>) -> Result<u64, Box
}

let mut found_count: u64 = 0;
let mut quit = false;
for path in paths_and_matcher.paths {
found_count += process_dir(
&path,
&paths_and_matcher.config,
deps,
&*paths_and_matcher.matcher,
&mut quit,
);
if quit {
break;
}
}
Ok(found_count)
}
Expand Down Expand Up @@ -796,4 +805,26 @@ mod tests {
fix_up_slashes("./test_data/links/link-f\n")
);
}

#[test]
fn find_print_then_quit() {
let deps = FakeDependencies::new();

let rc = find_main(
&[
"find",
&fix_up_slashes("./test_data/simple"),
&fix_up_slashes("./test_data/simple"),
"-print",
"-quit",
],
&deps,
);

assert_eq!(rc, 0);
assert_eq!(
deps.get_output_as_string(),
fix_up_slashes("./test_data/simple\n"),
);
}
}
点击 这是indexloc提供的php浏览器服务,不要输入任何密码和下载