Repository navigation
find: implement -ignore_readdir_race and -noignore_readdir_race - #903
DominicThemiya wants to merge 4 commits into
Conversation
Both options were rejected as unknown predicates. They are now accepted as global options: they apply wherever they appear in the expression, and the last one given wins, as in GNU find. With -ignore_readdir_race, -delete no longer reports a file that has already disappeared, and evaluates to true. Errors from tests that stat a vanished file (e.g. -size) are still reported; those are printed by each matcher and are left for a follow-up.
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #903 +/- ##
==========================================
+ Coverage 92.52% 92.60% +0.08%
==========================================
Files 36 36
Lines 7694 7738 +44
Branches 391 392 +1
==========================================
+ Hits 7119 7166 +47
+ Misses 437 433 -4
- Partials 138 139 +1 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
Merging this PR will not alter performance
|
|
Commit 6dc7f51 has test result changes: bfs testsuite: |
| } | ||
| Ok(entry) => { | ||
| let mut matcher_io = matchers::MatcherIO::new(deps); | ||
| matcher_io.set_ignore_readdir_race(config.ignore_readdir_race); |
There was a problem hiding this comment.
what about the Err(err) branch just above?
a file or dir vanishing during the walk ends up there and is still reported with exit 1.
that's the main readdir race case, no? please handle it too (with is_not_found()), or change "Closes" to a reference
There was a problem hiding this comment.
Good catch, thanks. Handled in 1fc1ff1: a walk error is now skipped when the option is set, is_not_found() is true and the depth is greater than 0, so missing starting points are still reported, as GNU does. Covered by vanished_dir_during_walk_is_an_error_by_default, vanished_dir_during_walk_with_ignore_readdir_race and missing_start_point_still_reported_with_ignore_readdir_race.
| } | ||
| Ok(entry) => { | ||
| let mut matcher_io = matchers::MatcherIO::new(deps); | ||
| matcher_io.set_ignore_readdir_race(config.ignore_readdir_race); |
There was a problem hiding this comment.
the MatcherIO built after the loop for finished_dir/finished doesn't get the flag, could you please set it there too?
| assert_eq!( | ||
| deps.get_output_as_string(), | ||
| fix_up_slashes("./test_data/simple/subdir\n./test_data/simple/subdir/ABBBC\n") | ||
| ); |
There was a problem hiding this comment.
this only checks that the option is parsed, the integration tests already cover it. do we need it?
There was a problem hiding this comment.
Agreed, the integration tests cover parsing. Removed in d511206.
| -d / -depth Process directory contents before directory itself | ||
| -mount / -xdev Do not descend into other file systems | ||
| -noleaf Do not optimize by assuming 2+ hard links | ||
| -ignore_readdir_race Do not report files that vanish during the search |
There was a problem hiding this comment.
did you run the GNU testsuite for this?
git clone https://git.savannah.gnu.org/git/findutils.git ../findutils.gnu
bash util/build-gnu.sh tests/find/.sh
There was a problem hiding this comment.
Yes, I ran it locally with util/build-gnu.sh (full suite, including the DejaGnu tests) on main and on this branch: 495 tests, 425 passed in both, and no test changed status. GNU's suite has no -ignore_readdir_race test, though; the bfs suite covers it, and CI on the first commit showed gnu/ignore_readdir_race and gnu/ignore_readdir_race_notdir going from failing to passing.
…_race A file or directory removed after its parent directory was read reaches the walk error branch and was still reported with exit status 1, even with -ignore_readdir_race. Skip such "not found" errors when the option is set. Starting points (depth 0) are still reported, as GNU find does.
The MatcherIO built after the walk for finished_dir() and finished() did not get the flag, unlike the one built for each entry.
The integration tests already pass both options and check their effect.
Closes #377
What
findrejected both options as unknown predicates:This adds them as global options, matching GNU find 4.11.0:
-ignore_readdir_race/-noignore_readdir_racewins.-ignore_readdir_race, a file or directory that vanishes after its parent directory was read is not reported during the walk.-ignore_readdir_race,-deleteon a file that has already disappeared prints nothing and evaluates to true.How
Configgets anignore_readdir_raceflag, set while parsing the expression.process_dir, a walk error is skipped when the flag is set,is_not_found()is true and the depth is greater than 0, so starting points are still reported.process_dirpasses the flag to everyMatcherIO, including the one used forfinished_dir/finished, soDeleteMatcherreads it when it runs rather than when it is built. That is what makes the option work when it comes after-delete.DeleteMatchertreatsErrorKind::NotFoundas success when the flag is set.--help.Not covered
stat(e.g.-size) hits a vanished file. Here each matcher prints its own error, so that needs a wider change (related to CodeHealth: tidy up Errors #15) and is left for a follow-up.Tests
find::matchers::delete::tests::delete_matcher_vanished_filedelete_vanished_file_is_an_error_by_default(tests/test_find.rs)delete_vanished_file_with_ignore_readdir_race(tests/test_find.rs)vanished_dir_during_walk_is_an_error_by_default(tests/test_find.rs)vanished_dir_during_walk_with_ignore_readdir_race(tests/test_find.rs)missing_start_point_still_reported_with_ignore_readdir_race(tests/test_find.rs)The walk tests use
-sortedso thatais always visited beforeb.cargo test,cargo fmt --checkandcargo clippy --all-targets -- -D warningspass locally. The GNU testsuite (util/build-gnu.sh, including the DejaGnu tests) gives the same results on main and on this branch: 495 tests, 425 passed, no test changed status.