Add support for embedded "{}"

Given

  find . -exec foo{}bar \;

GNU find will replace `{}` by the filename. This commit matches that
behavior.

Note that this is not required by the POSIX spec.

The GNU testsuite doesn't cover this case, so I've added a test in this
repo.
This commit is contained in:
Jez Ng
2023-02-20 16:56:44 -05:00
committed by Sylvestre Ledru
parent a3287a978f
commit 30a22453d6
2 changed files with 44 additions and 8 deletions
+13 -8
View File
@@ -14,7 +14,7 @@ use walkdir::DirEntry;
use super::{Matcher, MatcherIO};
enum Arg {
Filename,
FileArg(Vec<OsString>),
LiteralArg(OsString),
}
@@ -32,9 +32,14 @@ impl SingleExecMatcher {
) -> Result<Self, Box<dyn Error>> {
let transformed_args = args
.iter()
.map(|&a| match a {
"{}" => Arg::Filename,
_ => Arg::LiteralArg(OsString::from(a)),
.map(|&a| {
let parts = a.split("{}").collect::<Vec<_>>();
if parts.len() == 1 {
// No {} present
Arg::LiteralArg(OsString::from(a))
} else {
Arg::FileArg(parts.iter().map(OsString::from).collect())
}
})
.collect();
@@ -60,10 +65,10 @@ impl Matcher for SingleExecMatcher {
};
for arg in &self.args {
command.arg(match *arg {
Arg::LiteralArg(ref a) => a.as_os_str(),
Arg::Filename => path_to_file.as_os_str(),
});
match *arg {
Arg::LiteralArg(ref a) => command.arg(a.as_os_str()),
Arg::FileArg(ref parts) => command.arg(&parts.join(path_to_file.as_os_str())),
};
}
if self.exec_in_parent_dir {
match file_info.path().parent() {
+31
View File
@@ -85,6 +85,37 @@ fn matching_executes_code_in_files_directory() {
);
}
#[test]
fn matching_embedded_filename() {
let temp_dir = Builder::new()
.prefix("matching_embedded_filename")
.tempdir()
.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(),
&[temp_dir_path.as_ref(), "abc{}x{}yz"],
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=\nabctest_data/simple/abbbcxtest_data/simple/abbbcyz\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.