-
Notifications
You must be signed in to change notification settings - Fork 2.5k
Negation of subdir ignore causes other subdirs to be unignored #5020
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
Conversation
When a directory's contents are ignored, and then a glob negation is made to a nested subdir, other subdirectories are now unignored
Matching on the prefix of a negated pattern was triggering false negatives on siblings of that pattern. e.g. Given the .gitignore: dir/* !dir/sub1/sub2/** The path `dir/a.text` would not be ignored.
@pks-t It seems you were in this area last time, some guidance would be appreciated! We're seeing this problem prop up in GitKraken and wanted to try and get to the bottom of it. Let me know if there's something we're not able to grok, but it seems that the block that sat there is now no longer performing its function adequately. It seems that removal of that block is closer to the gitignore spec than the current iteration is now. The big question I have is what do you think we broke instead? |
This is the single most important question when it comes to gitignore code. You know, on the surface the rules look quite easy. But whenever you feel like you've improved the code to more closely match git.git, then nope. Some weird corner case you weren't aware of just broke. To be honest, by now I don't care for what I think anymore, as I started to trust our gitignore tests a lot more than my own judgement. I'm not able to grok all those intricacies and every time I take a look atthat code I need to re-learn everything from the beginning. Anyway, let's see where this block comes from. Blame shows f25bc0b (Fix rejection of parent dir of negated ignores, 2014-08-08):
Unfortunately, no test has been added for that. From my guess, this looks like one of the following two scenarios:
We do not want to unignore "/parent/child/file" in this case. Second guess:
We do not want to unignore "/parent/child" here either. So right now libgit2 does the right thing with regards to the above two scenarios, which might be what that commit wanted to fix. After removing the block, we still do the right thing, so it can't be required for them. Either my inferred scenarios are plain wrong or we have modified enough code for it to not be required anymore. Long story short: your changes look quite sensible to me, at least judging from the spec. |
tests/status/ignore.c
Outdated
@@ -1213,3 +1213,41 @@ void test_status_ignore__unignored_subdirs(void) | |||
assert_is_ignored("dir/a.test"); | |||
refute_is_ignored("dir/subdir/a.test"); | |||
} | |||
|
|||
void test_status_ignore__ignored_subdirfiles_with_subdir_rule(void) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I feel like you should add these two tests to "tests/attr/ignore.c" instead.
tests/status/ignore.c
Outdated
"!dir/sub1/sub2/**\n"); | ||
|
||
assert_is_ignored("dir/a.test"); | ||
assert_is_ignored("dir/sub1/a.test"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You'd definitely want to test that "dir/sub1/sub2/foobar" is ignored, too.
tests/status/ignore.c
Outdated
"empty_standard_repo/dir/a.test", | ||
"empty_standard_repo/dir/sub1/sub2/b.test", | ||
NULL | ||
}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There's no need to create those testfiles in "test/attr/ignore.c". You can just rewrite the gitignore file and then immediately use assert_is_ignored
in there.
You are definitely on point with your suggestion that there should be a test case for For comparison, I pushed up test/ignore-0.28.1, test/ignore-0.27.8, and test/ignore-0.27.0. On these branches, I added test cases for each of the assertions in 0.27.0: 0.27.8 0.28.1 This PR: |
@pks-t So I think if we look at the recent history of gitignore in libgit2, we're actually in a better position than we were before if this PR were to be merged. One of the selling points on merging this PR without necessarily fixing the negation case as well is that it is a vastly simpler discussion for customers. When their ignore file produces changes in GitKraken that are ignored in the CLI, if the reason is "That rule you added isn't supported in Git and should be removed from your .gitignore", then it's a super quick fix as a support issue. Right now, the gitignore system as is produces very odd and less fixable behavior. What are your thoughts? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry it took me so long to get back. Have been scavenging off in the last few weeks to make my desktop environment workable again :/
I'm happy to merge. It seems to pass everything we'd expect it to, except for the case where we erroneously unignore files in ignored deep directories. And that case didn't work before either, so we may as well handle that in a separate PR.
Excellent. Appreciate the merge! |
When a directory's contents are ignored, and then a glob negation is made to a nested subdir, other subdirectories are now unignored.
The best example I have is:
After the second rule is added, files in
/dir/sub1
are now unignored.