Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement -follow #420

Open
wants to merge 16 commits into
base: main
Choose a base branch
from
Open

Implement -follow #420

wants to merge 16 commits into from

Conversation

hanbings
Copy link
Collaborator

Closed #308

May conflict with #416, better merge #416 first. :)

There are changes as described in man find:
(The following changes are: When matching files, match the file pointed to by the file link.)

  1. It will use noleaf by default. (But -noleaf has no behavior change yet)
  2. changes the behaviour of the -newer predicate.
  3. consideration applies to -newerXY, -anewer and -cnewer
  4. -type predicate will always match against the type of the file that a symbolic link points to rather than the link itself.
  5. causes the -lname and -ilname predicates always to return false.

Copy link

codecov bot commented Jul 16, 2024

Codecov Report

Attention: Patch coverage is 60.25641% with 31 lines in your changes missing coverage. Please review.

Project coverage is 66.01%. Comparing base (c4a56e9) to head (eed1c1e).

Files Patch % Lines
src/find/matchers/time.rs 39.39% 11 Missing and 9 partials ⚠️
src/find/matchers/type_matcher.rs 56.25% 6 Missing and 1 partial ⚠️
src/find/matchers/mod.rs 80.95% 1 Missing and 3 partials ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main     #420      +/-   ##
==========================================
- Coverage   66.03%   66.01%   -0.03%     
==========================================
  Files          34       34              
  Lines        4004     4063      +59     
  Branches      910      924      +14     
==========================================
+ Hits         2644     2682      +38     
- Misses        996     1011      +15     
- Partials      364      370       +6     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

Copy link

Commit 93b5ae2 has GNU testsuite comparison:

Run GNU findutils tests: GNU tests summary = TOTAL: 702 / PASS: 445 / FAIL: 254 / ERROR: 2
Run GNU findutils tests: Changes from main: PASS +0 / FAIL +0 / ERROR +0 / SKIP +0 
Run GNU findutils tests: Gnu tests No changes
Run BFS tests: Changes from main: PASS +1 / SKIP +0 / FAIL -1
Run BFS tests: BFS tests summary = TOTAL: 288 / PASS: 192 / SKIP: 1 / FAIL: 95

Copy link

Commit c1ebc0a has GNU testsuite comparison:

Run GNU findutils tests: GNU tests summary = TOTAL: 702 / PASS: 445 / FAIL: 254 / ERROR: 2
Run GNU findutils tests: Changes from main: PASS +0 / FAIL +0 / ERROR +0 / SKIP +0 
Run GNU findutils tests: Gnu tests No changes
Run BFS tests: Changes from main: PASS +1 / SKIP +0 / FAIL -1
Run BFS tests: BFS tests summary = TOTAL: 288 / PASS: 192 / SKIP: 1 / FAIL: 95

@hanbings hanbings marked this pull request as draft July 16, 2024 13:57
Copy link

Commit 5abaed4 has GNU testsuite comparison:

Run GNU findutils tests: GNU tests summary = TOTAL: 702 / PASS: 445 / FAIL: 254 / ERROR: 2
Run GNU findutils tests: Changes from main: PASS +0 / FAIL +0 / ERROR +0 / SKIP +0 
Run GNU findutils tests: Gnu tests No changes
Run BFS tests: Changes from main: PASS +1 / SKIP +0 / FAIL -1
Run BFS tests: BFS tests summary = TOTAL: 288 / PASS: 192 / SKIP: 1 / FAIL: 95

Copy link

Commit 1b4e25b has GNU testsuite comparison:

Run GNU findutils tests: GNU tests summary = TOTAL: 702 / PASS: 445 / FAIL: 254 / ERROR: 2
Run GNU findutils tests: Changes from main: PASS +0 / FAIL +0 / ERROR +0 / SKIP +0 
Run GNU findutils tests: Gnu tests No changes
Run BFS tests: Changes from main: PASS +1 / SKIP +0 / FAIL -1
Run BFS tests: BFS tests summary = TOTAL: 288 / PASS: 192 / SKIP: 1 / FAIL: 95

Copy link

Commit e3911be has GNU testsuite comparison:

Run BFS tests: Changes from main: PASS +1 / SKIP +0 / FAIL -1
Run BFS tests: BFS tests summary = TOTAL: 288 / PASS: 192 / SKIP: 1 / FAIL: 95
Run GNU findutils tests: GNU tests summary = TOTAL: 702 / PASS: 445 / FAIL: 254 / ERROR: 2
Run GNU findutils tests: Changes from main: PASS +0 / FAIL +0 / ERROR +0 / SKIP +0 
Run GNU findutils tests: Gnu tests No changes

Copy link

Commit 887d76c has GNU testsuite comparison:

Run GNU findutils tests: GNU tests summary = TOTAL: 702 / PASS: 445 / FAIL: 254 / ERROR: 2
Run GNU findutils tests: Changes from main: PASS +0 / FAIL +0 / ERROR +0 / SKIP +0 
Run GNU findutils tests: Gnu tests No changes
Run BFS tests: Changes from main: PASS +1 / SKIP +0 / FAIL -1
Run BFS tests: BFS tests summary = TOTAL: 288 / PASS: 192 / SKIP: 1 / FAIL: 95

@hanbings
Copy link
Collaborator Author

hanbings commented Jul 16, 2024

Sorry, the test coverage is still not up to target. :(
They almost always appear in error handling logic and, therefore, are difficult to cover by test code.
I would like to focus on improving coverage after completing all GNU feature implementations.

@hanbings hanbings marked this pull request as ready for review July 16, 2024 16:00
}
}

impl Matcher for LinkNameMatcher {
fn matches(&self, file_info: &DirEntry, _: &mut MatcherIO) -> bool {
// -follow: causes the -lname and -ilname predicates always to return false.
if self.follow {
return false;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not really:

tavianator@graphene $ ln -s nowhere broken
tavianator@graphene $ find -lname nowhere
./broken

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry, could you please give me some more detailed steps?
I noticed that the -follow parameter is missing, is that find -follow -lname nowhere?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Whoops I copy pasted the wrong part of my session, but yeah:

$ ln -s nowhere broken
$ find -follow -lname nowhere
./broken

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks. I have fixed it to the actual behavior of the GNU version in a0d4e46

Copy link

Commit 1e1846a has GNU testsuite comparison:

Run GNU findutils tests: GNU tests summary = TOTAL: 702 / PASS: 445 / FAIL: 254 / ERROR: 2
Run GNU findutils tests: Changes from main: PASS +0 / FAIL +0 / ERROR +0 / SKIP +0 
Run GNU findutils tests: Gnu tests No changes
Run BFS tests: Changes from main: PASS +1 / SKIP +0 / FAIL -1
Run BFS tests: BFS tests summary = TOTAL: 288 / PASS: 192 / SKIP: 1 / FAIL: 95

Copy link

Commit a0d4e46 has GNU testsuite comparison:

Run GNU findutils tests: GNU tests summary = TOTAL: 702 / PASS: 445 / FAIL: 254 / ERROR: 2
Run GNU findutils tests: Changes from main: PASS +0 / FAIL +0 / ERROR +0 / SKIP +0 
Run GNU findutils tests: Gnu tests No changes
Run BFS tests: Changes from main: PASS +1 / SKIP +0 / FAIL -1
Run BFS tests: BFS tests summary = TOTAL: 288 / PASS: 192 / SKIP: 1 / FAIL: 95

Copy link

Commit eed1c1e has GNU testsuite comparison:

Run GNU findutils tests: GNU tests summary = TOTAL: 702 / PASS: 445 / FAIL: 254 / ERROR: 2
Run GNU findutils tests: Changes from main: PASS +0 / FAIL +0 / ERROR +0 / SKIP +0 
Run GNU findutils tests: Gnu tests No changes
Run BFS tests: Changes from main: PASS +1 / SKIP +0 / FAIL -1
Run BFS tests: BFS tests summary = TOTAL: 288 / PASS: 194 / SKIP: 1 / FAIL: 93

FileAgeRangeMatcher::new(
file_time_type,
minutes,
config.today_start,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It might be nicer to just pass &config to the matcher constructors so we don't have to keep changing the parameters.

}

impl NewerMatcher {
pub fn new(path_to_file: &str) -> Result<Self, Box<dyn Error>> {
pub fn new(path_to_file: &str, follow: bool) -> Result<Self, Box<dyn Error>> {
let metadata = fs::metadata(path_to_file)?;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be symlink_metadata() if follow is false. I'd recommend adding a Config::metadata() method or something to centralize the logic.

})
}

/// Implementation of matches that returns a result, allowing use to use try!
/// to deal with the errors.
fn matches_impl(&self, file_info: &DirEntry) -> Result<bool, Box<dyn Error>> {
let this_time = file_info.metadata()?.modified()?;
let path = file_info.path();
let this_time = if self.follow && path.is_symlink() {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Checking self.follow here is wrong for command lines like

$ find foo -newer bar -follow

-follow should apply here, but because NewerMatcher::new() was called before -follow was parsed, self.follow will be false. I think the right implementation would pass the final -follow state to matches(), possibly as part of MatcherIO. There could be a convenience method like MatcherIO::metadata(file_info) that handles following symlinks correctly.

(Also, it would be a good idea to cache the Metadata so each matcher doesn't have to do its own stat() call, but that's probably a separate refactoring.)

// 1. -type f searches not only for regular files,
// but also for files pointed to by symbolic links.
// 2. -type l will not return any results because -follow will follow symbolic links,
// so the find command cannot find pure symbolic links.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not true:

tavianator@tachyon $ ln -s nowhere broken
tavianator@tachyon $ find -follow -type l
./broken

assert!(!matcher.matches(&dir, &mut deps.new_matcher_io()));
assert!(!matcher.matches(&file, &mut deps.new_matcher_io()));
}
[true, false].iter().for_each(|follow| {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Might as well write for follow in [true, false] { to match the loop below

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Implement -follow
2 participants