Skip to content

Commit b742ca9

Browse files
committed
fix: Fixed matching bug ".gitignore" also matched "foo.gitignore"
1 parent 397e226 commit b742ca9

File tree

3 files changed

+49
-2
lines changed

3 files changed

+49
-2
lines changed

CHANGELOG.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ This is intended as an overview of the major changes
44

55
NEXT VERSION
66
===
7-
- ...
7+
- Fixed matching bug ".gitignore" also matched "foo.gitignore"
88

99
v.1.14.0
1010
===

codeowners-reader/src/main/java/nl/basjes/codeowners/Rule.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ public Rule(String fileExpression) {
3333
.replace("\\ ", " ") // The escaped spaces must become spaces again.
3434

3535
// If a path does not start with a /, the path is treated as if it starts with a globstar. README.md is treated the same way as /**/README.md
36-
.replaceAll("^([^/*.])", "/**/$1")
36+
.replaceAll("^([^/*])", "/**/$1")
3737
// "/foo" --> End can be a filename (so we pin to the end) or a directory name (so we expect another / )
3838
.replaceAll("([^/*])$", "$1(/|\\$)")
3939

codeowners-reader/src/test/java/nl/basjes/codeowners/TestCodeOwnersGitlab.java

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -471,4 +471,51 @@ void gitlabExclusionMultipleSections() {
471471
assertOwners(codeOwners, "/config/something.conf", "@ops-team");
472472
}
473473

474+
@Test
475+
void gitlabExclusionRealUsecase() {
476+
CodeOwners codeOwners = new CodeOwners(
477+
"[Code Quality][3] @quality\n" +
478+
"*\n" +
479+
"\n" +
480+
"[Change Management Process][1] @changemanagement\n" +
481+
"!/docs/\n" +
482+
"!*.md\n" +
483+
"!*.example\n" +
484+
"!.gitignore\n" +
485+
"!.prettierignore\n" +
486+
"*"
487+
);
488+
489+
codeOwners.setVerbose(true);
490+
assertOwners(codeOwners, "README.md", "@quality"); // Not for *.md
491+
assertOwners(codeOwners, "docs/README.md", "@quality"); // Not for *.md
492+
assertOwners(codeOwners, "subdir/README.md", "@quality"); // Not for *.md
493+
assertOwners(codeOwners, "Something.rb", "@quality", "@changemanagement");
494+
assertOwners(codeOwners, "docs/Something.rb", "@quality"); // Not in /docs/
495+
assertOwners(codeOwners, "subdir/Something.rb", "@quality", "@changemanagement");
496+
assertOwners(codeOwners, "Foo.gitignore", "@quality", "@changemanagement");
497+
assertOwners(codeOwners, ".gitignore", "@quality"); // Not .gitignore
498+
assertOwners(codeOwners, "docs/Foo.gitignore", "@quality"); // Not in /docs/
499+
assertOwners(codeOwners, "docs/.gitignore", "@quality"); // Not in /docs/ AND Not .gitignore
500+
assertOwners(codeOwners, "subdir/Foo.gitignore", "@quality", "@changemanagement");
501+
assertOwners(codeOwners, "subdir/.gitignore", "@quality"); // Not .gitignore
502+
}
503+
504+
505+
@Test
506+
void gitlabFileMatchingBugReproduction() {
507+
// The bug: The second line also matches "foo.gitignore"
508+
CodeOwners codeOwners = new CodeOwners(
509+
"*.gitignore @one\n" +
510+
".gitignore @two\n"
511+
);
512+
codeOwners.setVerbose(true);
513+
assertOwners(codeOwners, ".gitignore", "@two"); // Last match in a section is used
514+
assertOwners(codeOwners, "foo.gitignore", "@one");
515+
assertOwners(codeOwners, "/.gitignore", "@two"); // Last match in a section is used
516+
assertOwners(codeOwners, "/foo.gitignore", "@one");
517+
assertOwners(codeOwners, "/subdir/.gitignore", "@two");
518+
assertOwners(codeOwners, "/subdir/foo.gitignore", "@one");
519+
}
520+
474521
}

0 commit comments

Comments
 (0)