mirror of
https://github.com/uutils/findutils.git
synced 2026-06-10 15:48:30 -07:00
Format using rustfmt
This commit is contained in:
+1
-1
@@ -4,8 +4,8 @@
|
||||
// license that can be found in the LICENSE file or at
|
||||
// https://opensource.org/licenses/MIT.
|
||||
|
||||
extern crate glob;
|
||||
extern crate findutils;
|
||||
extern crate glob;
|
||||
|
||||
fn main() {
|
||||
let args = std::env::args().collect::<Vec<String>>();
|
||||
|
||||
+18
-14
@@ -6,7 +6,7 @@
|
||||
|
||||
use std::error::Error;
|
||||
use std::ffi::OsString;
|
||||
use std::io::{Write, stderr};
|
||||
use std::io::{stderr, Write};
|
||||
use std::path::Path;
|
||||
use std::process::Command;
|
||||
use walkdir::DirEntry;
|
||||
@@ -25,12 +25,13 @@ pub struct SingleExecMatcher {
|
||||
}
|
||||
|
||||
impl SingleExecMatcher {
|
||||
pub fn new(executable: &str,
|
||||
args: &[&str],
|
||||
exec_in_parent_dir: bool)
|
||||
-> Result<SingleExecMatcher, Box<Error>> {
|
||||
|
||||
let transformed_args = args.iter()
|
||||
pub fn new(
|
||||
executable: &str,
|
||||
args: &[&str],
|
||||
exec_in_parent_dir: bool,
|
||||
) -> Result<SingleExecMatcher, Box<Error>> {
|
||||
let transformed_args = args
|
||||
.iter()
|
||||
.map(|&a| match a {
|
||||
"{}" => Arg::Filename,
|
||||
_ => Arg::LiteralArg(OsString::from(a)),
|
||||
@@ -44,11 +45,16 @@ impl SingleExecMatcher {
|
||||
})
|
||||
}
|
||||
|
||||
pub fn new_box(executable: &str,
|
||||
args: &[&str],
|
||||
exec_in_parent_dir: bool)
|
||||
-> Result<Box<Matcher>, Box<Error>> {
|
||||
Ok(Box::new(SingleExecMatcher::new(executable, args, exec_in_parent_dir)?))
|
||||
pub fn new_box(
|
||||
executable: &str,
|
||||
args: &[&str],
|
||||
exec_in_parent_dir: bool,
|
||||
) -> Result<Box<Matcher>, Box<Error>> {
|
||||
Ok(Box::new(SingleExecMatcher::new(
|
||||
executable,
|
||||
args,
|
||||
exec_in_parent_dir,
|
||||
)?))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -72,7 +78,6 @@ impl Matcher for SingleExecMatcher {
|
||||
});
|
||||
}
|
||||
if self.exec_in_parent_dir {
|
||||
|
||||
if file_info.path() == Path::new(".") {
|
||||
command.current_dir(file_info.path());
|
||||
} else if let Some(parent) = file_info.path().parent() {
|
||||
@@ -93,7 +98,6 @@ impl Matcher for SingleExecMatcher {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#[cfg(test)]
|
||||
/// No tests here, because we need to call out to an external executable. See
|
||||
/// tests/exec_unit_tests.rs instead.
|
||||
|
||||
@@ -26,17 +26,20 @@ pub struct AndMatcher {
|
||||
|
||||
impl AndMatcher {
|
||||
pub fn new(submatchers: Vec<Box<Matcher>>) -> AndMatcher {
|
||||
AndMatcher { submatchers: submatchers }
|
||||
AndMatcher {
|
||||
submatchers: submatchers,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
impl Matcher for AndMatcher {
|
||||
/// Returns true if all sub-matchers return true. Short-circuiting does take
|
||||
/// 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))
|
||||
self.submatchers
|
||||
.iter()
|
||||
.all(|x| x.matches(dir_entry, matcher_io))
|
||||
}
|
||||
|
||||
fn has_side_effects(&self) -> bool {
|
||||
@@ -62,7 +65,9 @@ pub struct AndMatcherBuilder {
|
||||
|
||||
impl AndMatcherBuilder {
|
||||
pub fn new() -> AndMatcherBuilder {
|
||||
AndMatcherBuilder { submatchers: Vec::new() }
|
||||
AndMatcherBuilder {
|
||||
submatchers: Vec::new(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn new_and_condition(&mut self, matcher: Box<Matcher>) {
|
||||
@@ -82,8 +87,6 @@ impl AndMatcherBuilder {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// This matcher contains a collection of other matchers. A file matches
|
||||
/// if it matches any of the contained sub-matchers. For sub-matchers that have
|
||||
/// side effects, the side effects occur in the same order as the sub-matchers
|
||||
@@ -94,17 +97,20 @@ pub struct OrMatcher {
|
||||
|
||||
impl OrMatcher {
|
||||
pub fn new(submatchers: Vec<Box<Matcher>>) -> OrMatcher {
|
||||
OrMatcher { submatchers: submatchers }
|
||||
OrMatcher {
|
||||
submatchers: submatchers,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
impl Matcher for OrMatcher {
|
||||
/// Returns true if any sub-matcher returns true. Short-circuiting does take
|
||||
/// 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))
|
||||
self.submatchers
|
||||
.iter()
|
||||
.any(|x| x.matches(dir_entry, matcher_io))
|
||||
}
|
||||
|
||||
fn has_side_effects(&self) -> bool {
|
||||
@@ -131,21 +137,28 @@ pub struct OrMatcherBuilder {
|
||||
impl OrMatcherBuilder {
|
||||
pub fn new_and_condition(&mut self, matcher: Box<Matcher>) {
|
||||
// safe to unwrap. submatchers always has at least one member
|
||||
self.submatchers.last_mut().unwrap().new_and_condition(matcher);
|
||||
self.submatchers
|
||||
.last_mut()
|
||||
.unwrap()
|
||||
.new_and_condition(matcher);
|
||||
}
|
||||
|
||||
pub fn new_or_condition(&mut self, arg: &str) -> Result<(), Box<Error>> {
|
||||
if self.submatchers.last().unwrap().submatchers.is_empty() {
|
||||
return Err(From::from(format!("invalid expression; you have used a binary operator \
|
||||
'{}' with nothing before it.",
|
||||
arg)));
|
||||
return Err(From::from(format!(
|
||||
"invalid expression; you have used a binary operator \
|
||||
'{}' with nothing before it.",
|
||||
arg
|
||||
)));
|
||||
}
|
||||
self.submatchers.push(AndMatcherBuilder::new());
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn new() -> OrMatcherBuilder {
|
||||
let mut o = OrMatcherBuilder { submatchers: Vec::new() };
|
||||
let mut o = OrMatcherBuilder {
|
||||
submatchers: Vec::new(),
|
||||
};
|
||||
o.submatchers.push(AndMatcherBuilder::new());
|
||||
o
|
||||
}
|
||||
@@ -165,7 +178,6 @@ impl OrMatcherBuilder {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// This matcher contains a collection of other matchers. In contrast to
|
||||
/// `OrMatcher` and `AndMatcher`, all the submatcher objects are called
|
||||
/// regardless of the results of previous submatchers. This is primarily used
|
||||
@@ -177,11 +189,12 @@ pub struct ListMatcher {
|
||||
|
||||
impl ListMatcher {
|
||||
pub fn new(submatchers: Vec<Box<Matcher>>) -> ListMatcher {
|
||||
ListMatcher { submatchers: submatchers }
|
||||
ListMatcher {
|
||||
submatchers: submatchers,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
impl Matcher for ListMatcher {
|
||||
/// Calls matches on all submatcher objects, with no short-circuiting.
|
||||
/// Returns the result of the call to the final submatcher
|
||||
@@ -217,7 +230,10 @@ pub struct ListMatcherBuilder {
|
||||
impl ListMatcherBuilder {
|
||||
pub fn new_and_condition(&mut self, matcher: Box<Matcher>) {
|
||||
// safe to unwrap. submatchers always has at least one member
|
||||
self.submatchers.last_mut().unwrap().new_and_condition(matcher);
|
||||
self.submatchers
|
||||
.last_mut()
|
||||
.unwrap()
|
||||
.new_and_condition(matcher);
|
||||
}
|
||||
|
||||
pub fn new_or_condition(&mut self, arg: &str) -> Result<(), Box<Error>> {
|
||||
@@ -230,8 +246,10 @@ impl ListMatcherBuilder {
|
||||
let grandchild_and_matcher = &child_or_matcher.submatchers.last().unwrap();
|
||||
|
||||
if grandchild_and_matcher.submatchers.is_empty() {
|
||||
return Err(From::from("invalid expression; you have used a binary operator '-a' \
|
||||
with nothing before it."));
|
||||
return Err(From::from(
|
||||
"invalid expression; you have used a binary operator '-a' \
|
||||
with nothing before it.",
|
||||
));
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
@@ -243,8 +261,10 @@ impl ListMatcherBuilder {
|
||||
let grandchild_and_matcher = &child_or_matcher.submatchers.last().unwrap();
|
||||
|
||||
if grandchild_and_matcher.submatchers.is_empty() {
|
||||
return Err(From::from("invalid expression; you have used a binary operator ',' \
|
||||
with nothing before it."));
|
||||
return Err(From::from(
|
||||
"invalid expression; you have used a binary operator ',' \
|
||||
with nothing before it.",
|
||||
));
|
||||
}
|
||||
}
|
||||
self.submatchers.push(OrMatcherBuilder::new());
|
||||
@@ -252,7 +272,9 @@ impl ListMatcherBuilder {
|
||||
}
|
||||
|
||||
pub fn new() -> ListMatcherBuilder {
|
||||
let mut o = ListMatcherBuilder { submatchers: Vec::new() };
|
||||
let mut o = ListMatcherBuilder {
|
||||
submatchers: Vec::new(),
|
||||
};
|
||||
o.submatchers.push(OrMatcherBuilder::new());
|
||||
o
|
||||
}
|
||||
@@ -272,7 +294,6 @@ impl ListMatcherBuilder {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// A simple matcher that always matches.
|
||||
pub struct TrueMatcher;
|
||||
|
||||
@@ -303,7 +324,6 @@ impl FalseMatcher {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// Matcher that wraps another matcher and inverts matching criteria.
|
||||
pub struct NotMatcher {
|
||||
submatcher: Box<Matcher>,
|
||||
@@ -311,7 +331,9 @@ pub struct NotMatcher {
|
||||
|
||||
impl NotMatcher {
|
||||
pub fn new(submatcher: Box<Matcher>) -> NotMatcher {
|
||||
NotMatcher { submatcher: submatcher }
|
||||
NotMatcher {
|
||||
submatcher: submatcher,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn new_box(submatcher: Box<Matcher>) -> Box<NotMatcher> {
|
||||
@@ -340,11 +362,11 @@ impl Matcher for NotMatcher {
|
||||
#[cfg(test)]
|
||||
|
||||
mod tests {
|
||||
use walkdir::DirEntry;
|
||||
use crate::find::matchers::tests::get_dir_entry_for;
|
||||
use super::*;
|
||||
use crate::find::matchers::tests::get_dir_entry_for;
|
||||
use crate::find::matchers::{Matcher, MatcherIO};
|
||||
use crate::find::tests::FakeDependencies;
|
||||
use walkdir::DirEntry;
|
||||
|
||||
/// Simple Matcher impl that has side effects
|
||||
pub struct HasSideEffects {}
|
||||
@@ -365,8 +387,6 @@ mod tests {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
#[test]
|
||||
fn and_matches_works() {
|
||||
let abbbc = get_dir_entry_for("test_data/simple", "abbbc");
|
||||
|
||||
+259
-156
File diff suppressed because it is too large
Load Diff
@@ -30,7 +30,8 @@ impl NameMatcher {
|
||||
|
||||
impl Matcher for NameMatcher {
|
||||
fn matches(&self, file_info: &DirEntry, _: &mut MatcherIO) -> bool {
|
||||
self.pattern.matches(file_info.file_name().to_string_lossy().as_ref())
|
||||
self.pattern
|
||||
.matches(file_info.file_name().to_string_lossy().as_ref())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -54,20 +55,23 @@ impl CaselessNameMatcher {
|
||||
|
||||
impl super::Matcher for CaselessNameMatcher {
|
||||
fn matches(&self, file_info: &DirEntry, _: &mut MatcherIO) -> bool {
|
||||
self.pattern
|
||||
.matches(file_info.file_name().to_string_lossy().to_lowercase().as_ref())
|
||||
self.pattern.matches(
|
||||
file_info
|
||||
.file_name()
|
||||
.to_string_lossy()
|
||||
.to_lowercase()
|
||||
.as_ref(),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#[cfg(test)]
|
||||
|
||||
mod tests {
|
||||
use crate::find::matchers::Matcher;
|
||||
use crate::find::matchers::tests::get_dir_entry_for;
|
||||
use crate::find::tests::FakeDependencies;
|
||||
use super::*;
|
||||
|
||||
use crate::find::matchers::tests::get_dir_entry_for;
|
||||
use crate::find::matchers::Matcher;
|
||||
use crate::find::tests::FakeDependencies;
|
||||
|
||||
#[test]
|
||||
fn matching_with_wrong_case_returns_false() {
|
||||
|
||||
+275
-158
File diff suppressed because it is too large
Load Diff
@@ -23,10 +23,12 @@ impl Printer {
|
||||
|
||||
impl Matcher for Printer {
|
||||
fn matches(&self, file_info: &DirEntry, matcher_io: &mut MatcherIO) -> bool {
|
||||
writeln!(matcher_io.deps.get_output().borrow_mut(),
|
||||
"{}",
|
||||
file_info.path().to_string_lossy())
|
||||
.unwrap();
|
||||
writeln!(
|
||||
matcher_io.deps.get_output().borrow_mut(),
|
||||
"{}",
|
||||
file_info.path().to_string_lossy()
|
||||
)
|
||||
.unwrap();
|
||||
true
|
||||
}
|
||||
|
||||
@@ -38,11 +40,11 @@ impl Matcher for Printer {
|
||||
#[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;
|
||||
use crate::find::tests::fix_up_slashes;
|
||||
use super::*;
|
||||
use crate::find::tests::FakeDependencies;
|
||||
|
||||
#[test]
|
||||
fn prints() {
|
||||
@@ -51,7 +53,9 @@ mod tests {
|
||||
let matcher = Printer::new();
|
||||
let deps = FakeDependencies::new();
|
||||
assert!(matcher.matches(&abbbc, &mut deps.new_matcher_io()));
|
||||
assert_eq!(fix_up_slashes("./test_data/simple/abbbc\n"),
|
||||
deps.get_output_as_string());
|
||||
assert_eq!(
|
||||
fix_up_slashes("./test_data/simple/abbbc\n"),
|
||||
deps.get_output_as_string()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -30,10 +30,10 @@ impl Matcher for PruneMatcher {
|
||||
#[cfg(test)]
|
||||
|
||||
mod tests {
|
||||
use crate::find::matchers::Matcher;
|
||||
use crate::find::matchers::tests::get_dir_entry_for;
|
||||
use crate::find::tests::FakeDependencies;
|
||||
use super::*;
|
||||
use crate::find::matchers::tests::get_dir_entry_for;
|
||||
use crate::find::matchers::Matcher;
|
||||
use crate::find::tests::FakeDependencies;
|
||||
|
||||
#[test]
|
||||
fn file_type_matcher() {
|
||||
|
||||
+51
-34
@@ -32,9 +32,11 @@ impl FromStr for Unit {
|
||||
"M" => Unit::MebiByte,
|
||||
"G" => Unit::GibiByte,
|
||||
_ => {
|
||||
return Err(From::from(format!("Invalid suffix {} for -size. Only allowed \
|
||||
values are <nothing>, b, c, w, k, M or G",
|
||||
s)));
|
||||
return Err(From::from(format!(
|
||||
"Invalid suffix {} for -size. Only allowed \
|
||||
values are <nothing>, b, c, w, k, M or G",
|
||||
s
|
||||
)));
|
||||
}
|
||||
})
|
||||
}
|
||||
@@ -70,18 +72,20 @@ pub struct SizeMatcher {
|
||||
}
|
||||
|
||||
impl SizeMatcher {
|
||||
pub fn new(value_to_match: ComparableValue,
|
||||
suffix_string: &str)
|
||||
-> Result<SizeMatcher, Box<Error>> {
|
||||
pub fn new(
|
||||
value_to_match: ComparableValue,
|
||||
suffix_string: &str,
|
||||
) -> Result<SizeMatcher, Box<Error>> {
|
||||
Ok(SizeMatcher {
|
||||
unit: suffix_string.parse()?,
|
||||
value_to_match: value_to_match,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn new_box(value_to_match: ComparableValue,
|
||||
suffix_string: &str)
|
||||
-> Result<Box<Matcher>, Box<Error>> {
|
||||
pub fn new_box(
|
||||
value_to_match: ComparableValue,
|
||||
suffix_string: &str,
|
||||
) -> Result<Box<Matcher>, Box<Error>> {
|
||||
Ok(Box::new(SizeMatcher::new(value_to_match, suffix_string)?))
|
||||
}
|
||||
}
|
||||
@@ -89,16 +93,17 @@ impl SizeMatcher {
|
||||
impl Matcher for SizeMatcher {
|
||||
fn matches(&self, file_info: &DirEntry, _: &mut MatcherIO) -> bool {
|
||||
match file_info.metadata() {
|
||||
Ok(metadata) => {
|
||||
self.value_to_match
|
||||
.matches(byte_size_to_unit_size(self.unit, metadata.len()))
|
||||
}
|
||||
Ok(metadata) => self
|
||||
.value_to_match
|
||||
.matches(byte_size_to_unit_size(self.unit, metadata.len())),
|
||||
Err(e) => {
|
||||
writeln!(&mut stderr(),
|
||||
"Error getting file size for {}: {}",
|
||||
file_info.path().to_string_lossy(),
|
||||
e)
|
||||
.unwrap();
|
||||
writeln!(
|
||||
&mut stderr(),
|
||||
"Error getting file size for {}: {}",
|
||||
file_info.path().to_string_lossy(),
|
||||
e
|
||||
)
|
||||
.unwrap();
|
||||
false
|
||||
}
|
||||
}
|
||||
@@ -107,10 +112,10 @@ impl Matcher for SizeMatcher {
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::find::matchers::{ComparableValue, Matcher};
|
||||
use crate::find::matchers::tests::get_dir_entry_for;
|
||||
use crate::find::tests::FakeDependencies;
|
||||
use super::*;
|
||||
use crate::find::matchers::tests::get_dir_entry_for;
|
||||
use crate::find::matchers::{ComparableValue, Matcher};
|
||||
use crate::find::tests::FakeDependencies;
|
||||
// need to explicitly use non-pub members
|
||||
use super::{byte_size_to_unit_size, Unit};
|
||||
|
||||
@@ -125,8 +130,10 @@ mod tests {
|
||||
assert_eq!(byte_size_to_unit_size(Unit::Block, 1025), 3);
|
||||
assert_eq!(byte_size_to_unit_size(Unit::KibiByte, 1025), 2);
|
||||
assert_eq!(byte_size_to_unit_size(Unit::MebiByte, 1024 * 1024 + 1), 2);
|
||||
assert_eq!(byte_size_to_unit_size(Unit::GibiByte, 1024 * 1024 * 1024 + 1),
|
||||
2);
|
||||
assert_eq!(
|
||||
byte_size_to_unit_size(Unit::GibiByte, 1024 * 1024 * 1024 + 1),
|
||||
2
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -136,18 +143,24 @@ mod tests {
|
||||
assert_eq!(byte_size_to_unit_size("b".parse().unwrap(), 513), 2);
|
||||
assert_eq!(byte_size_to_unit_size("".parse().unwrap(), 513), 2);
|
||||
assert_eq!(byte_size_to_unit_size("k".parse().unwrap(), 1025), 2);
|
||||
assert_eq!(byte_size_to_unit_size("M".parse().unwrap(), 1024 * 1024 + 1),
|
||||
2);
|
||||
assert_eq!(byte_size_to_unit_size("G".parse().unwrap(), 2024 * 1024 * 1024 + 1),
|
||||
2);
|
||||
assert_eq!(
|
||||
byte_size_to_unit_size("M".parse().unwrap(), 1024 * 1024 + 1),
|
||||
2
|
||||
);
|
||||
assert_eq!(
|
||||
byte_size_to_unit_size("G".parse().unwrap(), 2024 * 1024 * 1024 + 1),
|
||||
2
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn size_matcher_bad_unit() {
|
||||
if let Err(e) = SizeMatcher::new(ComparableValue::EqualTo(2), "xyz") {
|
||||
assert!(e.description().contains("Invalid suffix") && e.description().contains("xyz"),
|
||||
"bad description: {}",
|
||||
e);
|
||||
assert!(
|
||||
e.description().contains("Invalid suffix") && e.description().contains("xyz"),
|
||||
"bad description: {}",
|
||||
e
|
||||
);
|
||||
} else {
|
||||
panic!("parsing a unit string should fail");
|
||||
}
|
||||
@@ -161,9 +174,13 @@ mod tests {
|
||||
let equal_to_1_blocks = SizeMatcher::new(ComparableValue::EqualTo(1), "b").unwrap();
|
||||
let deps = FakeDependencies::new();
|
||||
|
||||
assert!(!equal_to_2_blocks.matches(&file_info, &mut deps.new_matcher_io()),
|
||||
"512-byte file should not match size of 2 blocks");
|
||||
assert!(equal_to_1_blocks.matches(&file_info, &mut deps.new_matcher_io()),
|
||||
"512-byte file should match size of 1 block");
|
||||
assert!(
|
||||
!equal_to_2_blocks.matches(&file_info, &mut deps.new_matcher_io()),
|
||||
"512-byte file should not match size of 2 blocks"
|
||||
);
|
||||
assert!(
|
||||
equal_to_1_blocks.matches(&file_info, &mut deps.new_matcher_io()),
|
||||
"512-byte file should match size of 1 block"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
+129
-79
@@ -23,7 +23,9 @@ pub struct NewerMatcher {
|
||||
impl NewerMatcher {
|
||||
pub fn new(path_to_file: &str) -> Result<NewerMatcher, Box<Error>> {
|
||||
let metadata = fs::metadata(path_to_file)?;
|
||||
Ok(NewerMatcher { given_modification_time: metadata.modified()? })
|
||||
Ok(NewerMatcher {
|
||||
given_modification_time: metadata.modified()?,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn new_box(path_to_file: &str) -> Result<Box<Matcher>, Box<Error>> {
|
||||
@@ -38,7 +40,10 @@ impl NewerMatcher {
|
||||
// and returns an Err (with a duration) otherwise. So if this_time >
|
||||
// given_modification_time (in which case we want to return true) then
|
||||
// duration_since will return an error.
|
||||
Ok(self.given_modification_time.duration_since(this_time).is_err())
|
||||
Ok(self
|
||||
.given_modification_time
|
||||
.duration_since(this_time)
|
||||
.is_err())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -46,11 +51,13 @@ impl Matcher for NewerMatcher {
|
||||
fn matches(&self, file_info: &DirEntry, _: &mut MatcherIO) -> bool {
|
||||
match self.matches_impl(file_info) {
|
||||
Err(e) => {
|
||||
writeln!(&mut stderr(),
|
||||
"Error getting modification time for {}: {}",
|
||||
file_info.path().to_string_lossy(),
|
||||
e)
|
||||
.unwrap();
|
||||
writeln!(
|
||||
&mut stderr(),
|
||||
"Error getting modification time for {}: {}",
|
||||
file_info.path().to_string_lossy(),
|
||||
e
|
||||
)
|
||||
.unwrap();
|
||||
false
|
||||
}
|
||||
Ok(t) => t,
|
||||
@@ -86,12 +93,14 @@ impl Matcher for FileTimeMatcher {
|
||||
fn matches(&self, file_info: &DirEntry, matcher_io: &mut MatcherIO) -> bool {
|
||||
match self.matches_impl(file_info, matcher_io.now()) {
|
||||
Err(e) => {
|
||||
writeln!(&mut stderr(),
|
||||
"Error getting {:?} time for {}: {}",
|
||||
self.file_time_type,
|
||||
file_info.path().to_string_lossy(),
|
||||
e)
|
||||
.unwrap();
|
||||
writeln!(
|
||||
&mut stderr(),
|
||||
"Error getting {:?} time for {}: {}",
|
||||
self.file_time_type,
|
||||
file_info.path().to_string_lossy(),
|
||||
e
|
||||
)
|
||||
.unwrap();
|
||||
false
|
||||
}
|
||||
Ok(t) => t,
|
||||
@@ -99,8 +108,6 @@ impl Matcher for FileTimeMatcher {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
impl FileTimeMatcher {
|
||||
/// Impementation of matches that returns a result, allowing use to use try!
|
||||
/// to deal with the errors.
|
||||
@@ -147,10 +154,10 @@ mod tests {
|
||||
use tempdir::TempDir;
|
||||
use walkdir::DirEntry;
|
||||
|
||||
use crate::find::matchers::{ComparableValue, Matcher};
|
||||
use crate::find::matchers::tests::get_dir_entry_for;
|
||||
use crate::find::tests::FakeDependencies;
|
||||
use super::*;
|
||||
use crate::find::matchers::tests::get_dir_entry_for;
|
||||
use crate::find::matchers::{ComparableValue, Matcher};
|
||||
use crate::find::tests::FakeDependencies;
|
||||
|
||||
#[test]
|
||||
fn newer_matcher() {
|
||||
@@ -170,12 +177,18 @@ mod tests {
|
||||
let matcher_for_old = NewerMatcher::new(&old_file.path().to_string_lossy()).unwrap();
|
||||
let deps = FakeDependencies::new();
|
||||
|
||||
assert!(!matcher_for_new.matches(&old_file, &mut deps.new_matcher_io()),
|
||||
"old_file shouldn't be newer than new_dir");
|
||||
assert!(matcher_for_old.matches(&new_file, &mut deps.new_matcher_io()),
|
||||
"new_file should be newer than old_dir");
|
||||
assert!(!matcher_for_old.matches(&old_file, &mut deps.new_matcher_io()),
|
||||
"old_file shouldn't be newer than itself");
|
||||
assert!(
|
||||
!matcher_for_new.matches(&old_file, &mut deps.new_matcher_io()),
|
||||
"old_file shouldn't be newer than new_dir"
|
||||
);
|
||||
assert!(
|
||||
matcher_for_old.matches(&new_file, &mut deps.new_matcher_io()),
|
||||
"new_file should be newer than old_dir"
|
||||
);
|
||||
assert!(
|
||||
!matcher_for_old.matches(&old_file, &mut deps.new_matcher_io()),
|
||||
"old_file shouldn't be newer than itself"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -185,67 +198,96 @@ mod tests {
|
||||
|
||||
let files_mtime = file.metadata().unwrap().modified().unwrap();
|
||||
|
||||
let exactly_one_day_matcher = FileTimeMatcher::new(FileTimeType::Modified,
|
||||
ComparableValue::EqualTo(1));
|
||||
let more_than_one_day_matcher = FileTimeMatcher::new(FileTimeType::Modified,
|
||||
ComparableValue::MoreThan(1));
|
||||
let less_than_one_day_matcher = FileTimeMatcher::new(FileTimeType::Modified,
|
||||
ComparableValue::LessThan(1));
|
||||
let zero_day_matcher = FileTimeMatcher::new(FileTimeType::Modified,
|
||||
ComparableValue::EqualTo(0));
|
||||
let exactly_one_day_matcher =
|
||||
FileTimeMatcher::new(FileTimeType::Modified, ComparableValue::EqualTo(1));
|
||||
let more_than_one_day_matcher =
|
||||
FileTimeMatcher::new(FileTimeType::Modified, ComparableValue::MoreThan(1));
|
||||
let less_than_one_day_matcher =
|
||||
FileTimeMatcher::new(FileTimeType::Modified, ComparableValue::LessThan(1));
|
||||
let zero_day_matcher =
|
||||
FileTimeMatcher::new(FileTimeType::Modified, ComparableValue::EqualTo(0));
|
||||
|
||||
// set "now" to 2 days after the file was modified.
|
||||
let mut deps = FakeDependencies::new();
|
||||
deps.set_time(files_mtime + Duration::new(2 * super::SECONDS_PER_DAY as u64, 0));
|
||||
assert!(!exactly_one_day_matcher.matches(&file, &mut deps.new_matcher_io()),
|
||||
"2 day old file shouldn't match exactly 1 day old");
|
||||
assert!(more_than_one_day_matcher.matches(&file, &mut deps.new_matcher_io()),
|
||||
"2 day old file should match more than 1 day old");
|
||||
assert!(!less_than_one_day_matcher.matches(&file, &mut deps.new_matcher_io()),
|
||||
"2 day old file shouldn't match less than 1 day old");
|
||||
assert!(!zero_day_matcher.matches(&file, &mut deps.new_matcher_io()),
|
||||
"2 day old file shouldn't match exactly 0 days old");
|
||||
assert!(
|
||||
!exactly_one_day_matcher.matches(&file, &mut deps.new_matcher_io()),
|
||||
"2 day old file shouldn't match exactly 1 day old"
|
||||
);
|
||||
assert!(
|
||||
more_than_one_day_matcher.matches(&file, &mut deps.new_matcher_io()),
|
||||
"2 day old file should match more than 1 day old"
|
||||
);
|
||||
assert!(
|
||||
!less_than_one_day_matcher.matches(&file, &mut deps.new_matcher_io()),
|
||||
"2 day old file shouldn't match less than 1 day old"
|
||||
);
|
||||
assert!(
|
||||
!zero_day_matcher.matches(&file, &mut deps.new_matcher_io()),
|
||||
"2 day old file shouldn't match exactly 0 days old"
|
||||
);
|
||||
|
||||
// set "now" to 1 day after the file was modified.
|
||||
deps.set_time(files_mtime + Duration::new((3 * super::SECONDS_PER_DAY / 2) as u64, 0));
|
||||
assert!(exactly_one_day_matcher.matches(&file, &mut deps.new_matcher_io()),
|
||||
"1 day old file should match exactly 1 day old");
|
||||
assert!(!more_than_one_day_matcher.matches(&file, &mut deps.new_matcher_io()),
|
||||
"1 day old file shouldn't match more than 1 day old");
|
||||
assert!(!less_than_one_day_matcher.matches(&file, &mut deps.new_matcher_io()),
|
||||
"1 day old file shouldn't match less than 1 day old");
|
||||
assert!(!zero_day_matcher.matches(&file, &mut deps.new_matcher_io()),
|
||||
"1 day old file shouldn't match exactly 0 days old");
|
||||
assert!(
|
||||
exactly_one_day_matcher.matches(&file, &mut deps.new_matcher_io()),
|
||||
"1 day old file should match exactly 1 day old"
|
||||
);
|
||||
assert!(
|
||||
!more_than_one_day_matcher.matches(&file, &mut deps.new_matcher_io()),
|
||||
"1 day old file shouldn't match more than 1 day old"
|
||||
);
|
||||
assert!(
|
||||
!less_than_one_day_matcher.matches(&file, &mut deps.new_matcher_io()),
|
||||
"1 day old file shouldn't match less than 1 day old"
|
||||
);
|
||||
assert!(
|
||||
!zero_day_matcher.matches(&file, &mut deps.new_matcher_io()),
|
||||
"1 day old file shouldn't match exactly 0 days old"
|
||||
);
|
||||
|
||||
// set "now" to exactly the same time file was modified.
|
||||
deps.set_time(files_mtime);
|
||||
assert!(!exactly_one_day_matcher.matches(&file, &mut deps.new_matcher_io()),
|
||||
"0 day old file shouldn't match exactly 1 day old");
|
||||
assert!(!more_than_one_day_matcher.matches(&file, &mut deps.new_matcher_io()),
|
||||
"0 day old file shouldn't match more than 1 day old");
|
||||
assert!(less_than_one_day_matcher.matches(&file, &mut deps.new_matcher_io()),
|
||||
"0 day old file should match less than 1 day old");
|
||||
assert!(zero_day_matcher.matches(&file, &mut deps.new_matcher_io()),
|
||||
"0 day old file should match exactly 0 days old");
|
||||
|
||||
assert!(
|
||||
!exactly_one_day_matcher.matches(&file, &mut deps.new_matcher_io()),
|
||||
"0 day old file shouldn't match exactly 1 day old"
|
||||
);
|
||||
assert!(
|
||||
!more_than_one_day_matcher.matches(&file, &mut deps.new_matcher_io()),
|
||||
"0 day old file shouldn't match more than 1 day old"
|
||||
);
|
||||
assert!(
|
||||
less_than_one_day_matcher.matches(&file, &mut deps.new_matcher_io()),
|
||||
"0 day old file should match less than 1 day old"
|
||||
);
|
||||
assert!(
|
||||
zero_day_matcher.matches(&file, &mut deps.new_matcher_io()),
|
||||
"0 day old file should match exactly 0 days old"
|
||||
);
|
||||
|
||||
// set "now" to a second before the file was modified (e.g. the file was
|
||||
// modified after find started running
|
||||
deps.set_time(files_mtime - Duration::new(1 as u64, 0));
|
||||
assert!(!exactly_one_day_matcher.matches(&file, &mut deps.new_matcher_io()),
|
||||
"future-modified file shouldn'1 match exactly 1 day old");
|
||||
assert!(!more_than_one_day_matcher.matches(&file, &mut deps.new_matcher_io()),
|
||||
"future-modified file shouldn't match more than 1 day old");
|
||||
assert!(less_than_one_day_matcher.matches(&file, &mut deps.new_matcher_io()),
|
||||
"future-modified file should match less than 1 day old");
|
||||
assert!(!zero_day_matcher.matches(&file, &mut deps.new_matcher_io()),
|
||||
"future-modified file shouldn't match exactly 0 days old");
|
||||
|
||||
assert!(
|
||||
!exactly_one_day_matcher.matches(&file, &mut deps.new_matcher_io()),
|
||||
"future-modified file shouldn'1 match exactly 1 day old"
|
||||
);
|
||||
assert!(
|
||||
!more_than_one_day_matcher.matches(&file, &mut deps.new_matcher_io()),
|
||||
"future-modified file shouldn't match more than 1 day old"
|
||||
);
|
||||
assert!(
|
||||
less_than_one_day_matcher.matches(&file, &mut deps.new_matcher_io()),
|
||||
"future-modified file should match less than 1 day old"
|
||||
);
|
||||
assert!(
|
||||
!zero_day_matcher.matches(&file, &mut deps.new_matcher_io()),
|
||||
"future-modified file shouldn't match exactly 0 days old"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn file_time_matcher_modified_created_accessed() {
|
||||
|
||||
let temp_dir = TempDir::new("file_time_matcher_modified_created_accessed").unwrap();
|
||||
|
||||
// No easy way to independently set file times. So create it - setting creation time
|
||||
@@ -266,12 +308,14 @@ mod tests {
|
||||
// write to the file - changing the modifiation and potentially the accessed time
|
||||
let mut buffer = [0; 10];
|
||||
{
|
||||
let mut f =
|
||||
OpenOptions::new().read(true).write(true).open(&foo_path).expect("open temp file");
|
||||
let mut f = OpenOptions::new()
|
||||
.read(true)
|
||||
.write(true)
|
||||
.open(&foo_path)
|
||||
.expect("open temp file");
|
||||
let _ = f.write(&mut buffer);
|
||||
}
|
||||
|
||||
|
||||
thread::sleep(Duration::from_secs(2));
|
||||
// read the file agaion - potentially changing accessed time
|
||||
{
|
||||
@@ -302,22 +346,28 @@ mod tests {
|
||||
}
|
||||
|
||||
/// helper function for file_time_matcher_modified_created_accessed
|
||||
fn test_matcher_for_file_time_type(file_info: &DirEntry,
|
||||
file_time: SystemTime,
|
||||
file_time_type: FileTimeType) {
|
||||
fn test_matcher_for_file_time_type(
|
||||
file_info: &DirEntry,
|
||||
file_time: SystemTime,
|
||||
file_time_type: FileTimeType,
|
||||
) {
|
||||
{
|
||||
let matcher = FileTimeMatcher::new(file_time_type, ComparableValue::EqualTo(0));
|
||||
|
||||
let mut deps = FakeDependencies::new();
|
||||
deps.set_time(file_time);
|
||||
assert!(matcher.matches(&file_info, &mut deps.new_matcher_io()),
|
||||
"{:?} time matcher should match",
|
||||
file_time_type);
|
||||
assert!(
|
||||
matcher.matches(&file_info, &mut deps.new_matcher_io()),
|
||||
"{:?} time matcher should match",
|
||||
file_time_type
|
||||
);
|
||||
|
||||
deps.set_time(file_time - Duration::from_secs(1));
|
||||
assert!(!matcher.matches(&file_info, &mut deps.new_matcher_io()),
|
||||
"{:?} time matcher shouldn't match a second before",
|
||||
file_time_type);
|
||||
assert!(
|
||||
!matcher.matches(&file_info, &mut deps.new_matcher_io()),
|
||||
"{:?} time matcher shouldn't match a second before",
|
||||
file_time_type
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,11 +21,21 @@ impl TypeMatcher {
|
||||
"f" => FileType::is_file,
|
||||
"d" => FileType::is_dir,
|
||||
"b" | "c" | "p" | "l" | "s" | "D" => {
|
||||
return Err(From::from(format!("Type argument {} not supported yet", type_string)))
|
||||
return Err(From::from(format!(
|
||||
"Type argument {} not supported yet",
|
||||
type_string
|
||||
)))
|
||||
}
|
||||
_ => {
|
||||
return Err(From::from(format!(
|
||||
"Unrecognised type argument {}",
|
||||
type_string
|
||||
)))
|
||||
}
|
||||
_ => return Err(From::from(format!("Unrecognised type argument {}", type_string))),
|
||||
};
|
||||
Ok(TypeMatcher { file_type_fn: function })
|
||||
Ok(TypeMatcher {
|
||||
file_type_fn: function,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn new_box(type_string: &str) -> Result<Box<Matcher>, Box<Error>> {
|
||||
@@ -41,10 +51,10 @@ impl Matcher for TypeMatcher {
|
||||
#[cfg(test)]
|
||||
|
||||
mod tests {
|
||||
use crate::find::matchers::Matcher;
|
||||
use crate::find::matchers::tests::get_dir_entry_for;
|
||||
use crate::find::tests::FakeDependencies;
|
||||
use super::*;
|
||||
use crate::find::matchers::tests::get_dir_entry_for;
|
||||
use crate::find::matchers::Matcher;
|
||||
use crate::find::tests::FakeDependencies;
|
||||
|
||||
#[test]
|
||||
fn file_type_matcher() {
|
||||
|
||||
+239
-130
File diff suppressed because it is too large
Load Diff
@@ -21,8 +21,9 @@ struct Config {
|
||||
}
|
||||
|
||||
fn open_file(destination_dir: &str) -> File {
|
||||
let mut file_number =
|
||||
fs::read_dir(destination_dir).expect("failed to read destination").count();
|
||||
let mut file_number = fs::read_dir(destination_dir)
|
||||
.expect("failed to read destination")
|
||||
.count();
|
||||
|
||||
loop {
|
||||
file_number += 1;
|
||||
@@ -31,7 +32,8 @@ fn open_file(destination_dir: &str) -> File {
|
||||
if let Ok(f) = OpenOptions::new()
|
||||
.write(true)
|
||||
.create_new(true)
|
||||
.open(file_path) {
|
||||
.open(file_path)
|
||||
{
|
||||
return f;
|
||||
}
|
||||
}
|
||||
@@ -62,13 +64,15 @@ fn main() {
|
||||
// first two args are going to be the path to this executable and
|
||||
// the destination_dir we want to write to. Don't write either of those
|
||||
// as they'll be non-deterministic.
|
||||
f.write_fmt(format_args!("cwd={}\nargs=\n",
|
||||
env::current_dir().unwrap().to_string_lossy()))
|
||||
.expect("failed to write to file");
|
||||
f.write_fmt(format_args!(
|
||||
"cwd={}\nargs=\n",
|
||||
env::current_dir().unwrap().to_string_lossy()
|
||||
))
|
||||
.expect("failed to write to file");
|
||||
for arg in &args[2..] {
|
||||
f.write_fmt(format_args!("{}\n", arg)).expect("failed to write to file");
|
||||
f.write_fmt(format_args!("{}\n", arg))
|
||||
.expect("failed to write to file");
|
||||
}
|
||||
|
||||
}
|
||||
std::process::exit(if config.exit_with_failure { 2 } else { 0 });
|
||||
}
|
||||
|
||||
@@ -4,7 +4,6 @@
|
||||
// license that can be found in the LICENSE file or at
|
||||
// https://opensource.org/licenses/MIT.
|
||||
|
||||
|
||||
// As this module is included by all the integration tests, any function used
|
||||
// in one test but not another can cause a dead code warning.
|
||||
#[allow(dead_code)]
|
||||
|
||||
@@ -4,7 +4,6 @@
|
||||
// license that can be found in the LICENSE file or at
|
||||
// https://opensource.org/licenses/MIT.
|
||||
|
||||
|
||||
use std::cell::RefCell;
|
||||
use std::env;
|
||||
use std::io::{Cursor, Read, Write};
|
||||
@@ -55,7 +54,6 @@ impl<'a> Dependencies<'a> for FakeDependencies {
|
||||
}
|
||||
|
||||
pub fn path_to_testing_commandline() -> String {
|
||||
|
||||
let mut path_to_use = env::current_exe()
|
||||
// this will be something along the lines of /my/homedir/findutils/target/debug/deps/findutils-5532804878869ef1
|
||||
.expect("can't find path of this executable")
|
||||
@@ -67,8 +65,7 @@ pub fn path_to_testing_commandline() -> String {
|
||||
path_to_use.pop();
|
||||
}
|
||||
path_to_use = path_to_use.join("testing-commandline");
|
||||
path_to_use.to_string_lossy()
|
||||
.to_string()
|
||||
path_to_use.to_string_lossy().to_string()
|
||||
}
|
||||
|
||||
#[cfg(windows)]
|
||||
|
||||
+69
-47
@@ -4,7 +4,6 @@
|
||||
// license that can be found in the LICENSE file or at
|
||||
// https://opensource.org/licenses/MIT.
|
||||
|
||||
|
||||
/// ! This file contains what would be normally be unit tests for find::matchers::exec.
|
||||
/// ! But as the tests require running an external executable, they need to be run
|
||||
/// ! as integration tests so we can ensure that our testing-commandline binary
|
||||
@@ -13,70 +12,78 @@ extern crate findutils;
|
||||
extern crate tempdir;
|
||||
extern crate walkdir;
|
||||
|
||||
|
||||
use std::env;
|
||||
use std::fs::File;
|
||||
use std::io::Read;
|
||||
use tempdir::TempDir;
|
||||
use walkdir::WalkDir;
|
||||
|
||||
|
||||
use findutils::find::matchers::Matcher;
|
||||
use findutils::find::matchers::exec::*;
|
||||
use common::test_helpers::*;
|
||||
use findutils::find::matchers::exec::*;
|
||||
use findutils::find::matchers::Matcher;
|
||||
|
||||
mod common;
|
||||
|
||||
#[test]
|
||||
fn matching_executes_code() {
|
||||
|
||||
let temp_dir = TempDir::new("matching_executes_code").unwrap();
|
||||
let temp_dir_path = temp_dir.path().to_string_lossy();
|
||||
|
||||
let abbbc = get_dir_entry_for("test_data/simple", "abbbc");
|
||||
let matcher = SingleExecMatcher::new(&path_to_testing_commandline(),
|
||||
&vec![temp_dir_path.as_ref(), "abc", "{}", "xyz"],
|
||||
false)
|
||||
.expect("Failed to create matcher");
|
||||
let matcher = SingleExecMatcher::new(
|
||||
&path_to_testing_commandline(),
|
||||
&vec![temp_dir_path.as_ref(), "abc", "{}", "xyz"],
|
||||
false,
|
||||
)
|
||||
.expect("Failed to create matcher");
|
||||
let deps = FakeDependencies::new();
|
||||
assert!(matcher.matches(&abbbc, &mut deps.new_matcher_io()));
|
||||
|
||||
let mut f = File::open(temp_dir.path().join("1.txt")).expect("Failed to open output file");
|
||||
let mut s = String::new();
|
||||
f.read_to_string(&mut s).expect("failed to read output file");
|
||||
assert_eq!(s,
|
||||
fix_up_slashes(&format!("cwd={}\nargs=\nabc\ntest_data/simple/abbbc\nxyz\n",
|
||||
env::current_dir().unwrap().to_string_lossy())));
|
||||
f.read_to_string(&mut s)
|
||||
.expect("failed to read output file");
|
||||
assert_eq!(
|
||||
s,
|
||||
fix_up_slashes(&format!(
|
||||
"cwd={}\nargs=\nabc\ntest_data/simple/abbbc\nxyz\n",
|
||||
env::current_dir().unwrap().to_string_lossy()
|
||||
))
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn matching_executes_code_in_files_directory() {
|
||||
|
||||
let temp_dir = TempDir::new("matching_executes_code_in_files_directory").unwrap();
|
||||
let temp_dir_path = temp_dir.path().to_string_lossy();
|
||||
|
||||
let abbbc = get_dir_entry_for("test_data/simple", "abbbc");
|
||||
let matcher = SingleExecMatcher::new(&path_to_testing_commandline(),
|
||||
&vec![temp_dir_path.as_ref(), "abc", "{}", "xyz"],
|
||||
true)
|
||||
.expect("Failed to create matcher");
|
||||
let matcher = SingleExecMatcher::new(
|
||||
&path_to_testing_commandline(),
|
||||
&vec![temp_dir_path.as_ref(), "abc", "{}", "xyz"],
|
||||
true,
|
||||
)
|
||||
.expect("Failed to create matcher");
|
||||
let deps = FakeDependencies::new();
|
||||
assert!(matcher.matches(&abbbc, &mut deps.new_matcher_io()));
|
||||
|
||||
let mut f = File::open(temp_dir.path().join("1.txt")).expect("Failed to open output file");
|
||||
let mut s = String::new();
|
||||
f.read_to_string(&mut s).expect("failed to read output file");
|
||||
assert_eq!(s,
|
||||
fix_up_slashes(&format!("cwd={}/test_data/simple\nargs=\nabc\n./abbbc\nxyz\n",
|
||||
env::current_dir().unwrap().to_string_lossy())));
|
||||
|
||||
f.read_to_string(&mut s)
|
||||
.expect("failed to read output file");
|
||||
assert_eq!(
|
||||
s,
|
||||
fix_up_slashes(&format!(
|
||||
"cwd={}/test_data/simple\nargs=\nabc\n./abbbc\nxyz\n",
|
||||
env::current_dir().unwrap().to_string_lossy()
|
||||
))
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
/// Running "find . -execdir whatever \;" failed with a No such file or directory error.
|
||||
/// It's now fixed, and this is a regression test to check that it stays fixed.
|
||||
fn execdir_in_current_directory() {
|
||||
|
||||
let temp_dir = TempDir::new("execdir_in_current_directory").unwrap();
|
||||
let temp_dir_path = temp_dir.path().to_string_lossy();
|
||||
|
||||
@@ -85,44 +92,59 @@ fn execdir_in_current_directory() {
|
||||
.next()
|
||||
.expect("iterator was empty")
|
||||
.expect("result wasn't OK");
|
||||
let matcher = SingleExecMatcher::new(&path_to_testing_commandline(),
|
||||
&vec![temp_dir_path.as_ref(), "abc", "{}", "xyz"],
|
||||
true)
|
||||
.expect("Failed to create matcher");
|
||||
let matcher = SingleExecMatcher::new(
|
||||
&path_to_testing_commandline(),
|
||||
&vec![temp_dir_path.as_ref(), "abc", "{}", "xyz"],
|
||||
true,
|
||||
)
|
||||
.expect("Failed to create matcher");
|
||||
let deps = FakeDependencies::new();
|
||||
assert!(matcher.matches(¤t_dir_entry, &mut deps.new_matcher_io()));
|
||||
|
||||
let mut f = File::open(temp_dir.path().join("1.txt")).expect("Failed to open output file");
|
||||
let mut s = String::new();
|
||||
f.read_to_string(&mut s).expect("failed to read output file");
|
||||
assert_eq!(s,
|
||||
fix_up_slashes(&format!("cwd={}\nargs=\nabc\n./.\nxyz\n",
|
||||
env::current_dir().unwrap().to_string_lossy())));
|
||||
f.read_to_string(&mut s)
|
||||
.expect("failed to read output file");
|
||||
assert_eq!(
|
||||
s,
|
||||
fix_up_slashes(&format!(
|
||||
"cwd={}\nargs=\nabc\n./.\nxyz\n",
|
||||
env::current_dir().unwrap().to_string_lossy()
|
||||
))
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn matching_fails_if_executable_fails() {
|
||||
|
||||
let temp_dir = TempDir::new("matching_fails_if_executable_fails").unwrap();
|
||||
let temp_dir_path = temp_dir.path().to_string_lossy();
|
||||
|
||||
let abbbc = get_dir_entry_for("test_data/simple", "abbbc");
|
||||
let matcher = SingleExecMatcher::new(&path_to_testing_commandline(),
|
||||
&vec![temp_dir_path.as_ref(),
|
||||
"--exit_with_failure",
|
||||
"abc",
|
||||
"{}",
|
||||
"xyz"],
|
||||
true)
|
||||
.expect("Failed to create matcher");
|
||||
let matcher = SingleExecMatcher::new(
|
||||
&path_to_testing_commandline(),
|
||||
&vec![
|
||||
temp_dir_path.as_ref(),
|
||||
"--exit_with_failure",
|
||||
"abc",
|
||||
"{}",
|
||||
"xyz",
|
||||
],
|
||||
true,
|
||||
)
|
||||
.expect("Failed to create matcher");
|
||||
let deps = FakeDependencies::new();
|
||||
assert!(!matcher.matches(&abbbc, &mut deps.new_matcher_io()));
|
||||
|
||||
let mut f = File::open(temp_dir.path().join("1.txt")).expect("Failed to open output file");
|
||||
let mut s = String::new();
|
||||
f.read_to_string(&mut s).expect("failed to read output file");
|
||||
assert_eq!(s,
|
||||
fix_up_slashes(&format!("cwd={}/test_data/simple\nargs=\n--exit_with_failure\nabc\n.\
|
||||
/abbbc\nxyz\n",
|
||||
env::current_dir().unwrap().to_string_lossy())));
|
||||
f.read_to_string(&mut s)
|
||||
.expect("failed to read output file");
|
||||
assert_eq!(
|
||||
s,
|
||||
fix_up_slashes(&format!(
|
||||
"cwd={}/test_data/simple\nargs=\n--exit_with_failure\nabc\n.\
|
||||
/abbbc\nxyz\n",
|
||||
env::current_dir().unwrap().to_string_lossy()
|
||||
))
|
||||
);
|
||||
}
|
||||
|
||||
+51
-36
@@ -4,7 +4,6 @@
|
||||
// license that can be found in the LICENSE file or at
|
||||
// https://opensource.org/licenses/MIT.
|
||||
|
||||
|
||||
/// ! This file contains what would be normally be unit tests for find::find_main
|
||||
/// ! related to -exec[dir] and ok[dir] clauses.
|
||||
/// ! But as the tests require running an external executable, they need to be run
|
||||
@@ -14,14 +13,13 @@ extern crate findutils;
|
||||
extern crate tempdir;
|
||||
extern crate walkdir;
|
||||
|
||||
|
||||
use std::env;
|
||||
use std::fs::File;
|
||||
use std::io::Read;
|
||||
use tempdir::TempDir;
|
||||
|
||||
use findutils::find::find_main;
|
||||
use common::test_helpers::*;
|
||||
use findutils::find::find_main;
|
||||
|
||||
mod common;
|
||||
#[test]
|
||||
@@ -30,18 +28,22 @@ fn find_exec() {
|
||||
let temp_dir_path = temp_dir.path().to_string_lossy();
|
||||
let deps = FakeDependencies::new();
|
||||
|
||||
let rc = find_main(&["find",
|
||||
&fix_up_slashes("./test_data/simple/subdir"),
|
||||
"-type",
|
||||
"f",
|
||||
"-exec",
|
||||
&path_to_testing_commandline(),
|
||||
temp_dir_path.as_ref(),
|
||||
"(",
|
||||
"{}",
|
||||
"-o",
|
||||
";"],
|
||||
&deps);
|
||||
let rc = find_main(
|
||||
&[
|
||||
"find",
|
||||
&fix_up_slashes("./test_data/simple/subdir"),
|
||||
"-type",
|
||||
"f",
|
||||
"-exec",
|
||||
&path_to_testing_commandline(),
|
||||
temp_dir_path.as_ref(),
|
||||
"(",
|
||||
"{}",
|
||||
"-o",
|
||||
";",
|
||||
],
|
||||
&deps,
|
||||
);
|
||||
|
||||
assert_eq!(rc, 0);
|
||||
// exec has side effects, so we won't output anything unless -print is
|
||||
@@ -51,10 +53,15 @@ fn find_exec() {
|
||||
// check the executable ran as expected
|
||||
let mut f = File::open(temp_dir.path().join("1.txt")).expect("Failed to open output file");
|
||||
let mut s = String::new();
|
||||
f.read_to_string(&mut s).expect("failed to read output file");
|
||||
assert_eq!(s,
|
||||
fix_up_slashes(&format!("cwd={}\nargs=\n(\n./test_data/simple/subdir/ABBBC\n-o\n",
|
||||
env::current_dir().unwrap().to_string_lossy())));
|
||||
f.read_to_string(&mut s)
|
||||
.expect("failed to read output file");
|
||||
assert_eq!(
|
||||
s,
|
||||
fix_up_slashes(&format!(
|
||||
"cwd={}\nargs=\n(\n./test_data/simple/subdir/ABBBC\n-o\n",
|
||||
env::current_dir().unwrap().to_string_lossy()
|
||||
))
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -64,18 +71,22 @@ fn find_execdir() {
|
||||
let deps = FakeDependencies::new();
|
||||
// only look at files because the "size" of a directory is a system (and filesystem)
|
||||
// dependent thing and we want these tests to be universal.
|
||||
let rc = find_main(&["find",
|
||||
&fix_up_slashes("./test_data/simple/subdir"),
|
||||
"-type",
|
||||
"f",
|
||||
"-execdir",
|
||||
&path_to_testing_commandline(),
|
||||
temp_dir_path.as_ref(),
|
||||
")",
|
||||
"{}",
|
||||
",",
|
||||
";"],
|
||||
&deps);
|
||||
let rc = find_main(
|
||||
&[
|
||||
"find",
|
||||
&fix_up_slashes("./test_data/simple/subdir"),
|
||||
"-type",
|
||||
"f",
|
||||
"-execdir",
|
||||
&path_to_testing_commandline(),
|
||||
temp_dir_path.as_ref(),
|
||||
")",
|
||||
"{}",
|
||||
",",
|
||||
";",
|
||||
],
|
||||
&deps,
|
||||
);
|
||||
|
||||
assert_eq!(rc, 0);
|
||||
// exec has side effects, so we won't output anything unless -print is
|
||||
@@ -85,9 +96,13 @@ fn find_execdir() {
|
||||
// check the executable ran as expected
|
||||
let mut f = File::open(temp_dir.path().join("1.txt")).expect("Failed to open output file");
|
||||
let mut s = String::new();
|
||||
f.read_to_string(&mut s).expect("failed to read output file");
|
||||
assert_eq!(s,
|
||||
fix_up_slashes(&format!("cwd={}/test_data/simple/subdir\nargs=\n)\n./ABBBC\n,\n",
|
||||
env::current_dir().unwrap().to_string_lossy())));
|
||||
|
||||
f.read_to_string(&mut s)
|
||||
.expect("failed to read output file");
|
||||
assert_eq!(
|
||||
s,
|
||||
fix_up_slashes(&format!(
|
||||
"cwd={}/test_data/simple/subdir\nargs=\n)\n./ABBBC\n,\n",
|
||||
env::current_dir().unwrap().to_string_lossy()
|
||||
))
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user