-
Notifications
You must be signed in to change notification settings - Fork 1
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
[feature] Add globs (**/*) feature to excludes #16
base: main
Are you sure you want to change the base?
Changes from all commits
0dc5cb3
d0aaa7c
00ff0ad
8ad894d
7b8d2bf
60a60be
ca23185
c24dd98
bcf4de9
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,198 @@ | ||
/* | ||
Copyright 2024 Flant JSC | ||
|
||
Licensed under the Apache License, Version 2.0 (the "License"); | ||
you may not use this file except in compliance with the License. | ||
You may obtain a copy of the License at | ||
|
||
http://www.apache.org/licenses/LICENSE-2.0 | ||
|
||
Unless required by applicable law or agreed to in writing, software | ||
distributed under the License is distributed on an "AS IS" BASIS, | ||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
See the License for the specific language governing permissions and | ||
limitations under the License. | ||
*/ | ||
|
||
package fsutils | ||
|
||
import ( | ||
"testing" | ||
) | ||
|
||
func Test_FSUtils_toRegexp(t *testing.T) { | ||
type args struct { | ||
pattern string | ||
} | ||
|
||
tests := []struct { | ||
name string | ||
args args | ||
want string | ||
}{ | ||
{ | ||
name: "test escape slashes", | ||
args: args{ | ||
pattern: "/home/user/test/project", | ||
}, | ||
want: "^\\/home\\/user\\/test\\/project$", | ||
}, | ||
{ | ||
name: "test escape slashes and dots", | ||
args: args{ | ||
pattern: "/home/user/test/project.txt", | ||
}, | ||
want: "^\\/home\\/user\\/test\\/project\\.txt$", | ||
}, | ||
{ | ||
name: "test glob mask **", | ||
args: args{ | ||
pattern: "/home/user/**/project.txt", | ||
}, | ||
want: "^\\/home\\/user\\/.*\\/project\\.txt$", | ||
}, | ||
{ | ||
name: "test glob mask ** and file mask", | ||
args: args{ | ||
pattern: "/home/user/**/*.txt", | ||
}, | ||
want: "^\\/home\\/user\\/.*\\/[^/]*\\.txt$", | ||
}, | ||
} | ||
|
||
for _, tt := range tests { | ||
t.Run(tt.name, func(t *testing.T) { | ||
if got := toRegexp(tt.args.pattern); got != tt.want { | ||
t.Errorf("toRegexp() = %v, want %v", got, tt.want) | ||
} | ||
}) | ||
} | ||
} | ||
|
||
func TestFSUtils_FileNames_StringMatchMask(t *testing.T) { | ||
type args struct { | ||
name string | ||
pattern string | ||
} | ||
tests := []struct { | ||
name string | ||
args args | ||
want bool | ||
}{ | ||
{ | ||
name: "without any mask (exact filenames)", | ||
args: args{ | ||
name: "/home/user/test/project.txt", | ||
pattern: "/home/user/test/project.txt", | ||
}, | ||
want: true, | ||
}, | ||
{ | ||
name: "with filename mask and txt extension", | ||
args: args{ | ||
name: "/home/user/test/project.txt", | ||
pattern: "/home/user/test/*.txt", | ||
}, | ||
want: true, | ||
}, | ||
{ | ||
name: "with filename mask and log extension", | ||
args: args{ | ||
name: "/home/user/test/project.log", | ||
pattern: "/home/user/test/*.txt", | ||
}, | ||
want: false, | ||
}, | ||
{ | ||
name: "with glob mask and exact filename", | ||
args: args{ | ||
name: "/home/user/test/project.txt", | ||
juev marked this conversation as resolved.
Show resolved
Hide resolved
|
||
pattern: "/home/user/**/project.txt", | ||
}, | ||
want: true, | ||
}, | ||
{ | ||
name: "with glob mask and exact filename which not match with pattern", | ||
args: args{ | ||
name: "/home/user/test/newproject.txt", | ||
pattern: "/home/user/**/project.txt", | ||
}, | ||
want: false, | ||
}, | ||
{ | ||
name: "with glob mask and any extension with exact filename", | ||
args: args{ | ||
name: "/home/user/test/project.txt", | ||
pattern: "/home/user/**/project.*", | ||
}, | ||
want: true, | ||
}, | ||
{ | ||
name: "with mask without subdirectories", | ||
args: args{ | ||
name: "/home/user/test/project.txt", | ||
pattern: "/home/user/*.txt", | ||
}, | ||
want: false, | ||
}, | ||
{ | ||
name: "with glob mask and any file inside directories", | ||
args: args{ | ||
name: "/home/user/test/something/other/project.txt", | ||
pattern: "/home/user/**/*", | ||
}, | ||
want: true, | ||
}, | ||
} | ||
for _, tt := range tests { | ||
t.Run(tt.name, func(t *testing.T) { | ||
if got := StringMatchMask(tt.args.name, tt.args.pattern); got != tt.want { | ||
t.Errorf("StringMatchMask() = %v, want %v", got, tt.want) | ||
} | ||
}) | ||
} | ||
} | ||
|
||
func TestFSUtils_PlainStrings_StringMatchMask(t *testing.T) { | ||
type args struct { | ||
str string | ||
pattern string | ||
} | ||
tests := []struct { | ||
name string | ||
args args | ||
want bool | ||
}{ | ||
{ | ||
name: "test module-name:filename with exact name", | ||
args: args{ | ||
str: "managed-pg:/enabled", | ||
pattern: "managed-pg:/enabled", | ||
}, | ||
want: true, | ||
}, | ||
{ | ||
name: "test module-name:filename with glob mask", | ||
args: args{ | ||
str: "managed-pg:/.venv/lib/python3.13/site-packages/deckhouse/__init__.py", | ||
pattern: "managed-pg:/.venv/**/*", | ||
}, | ||
want: true, | ||
}, | ||
{ | ||
name: "plain string with mask", | ||
args: args{ | ||
str: "test-string.delimited.by.dots", | ||
pattern: "*.by.dots", | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If I understand correctly, then the pattern will fit any module without restrictions? |
||
}, | ||
want: true, | ||
}, | ||
} | ||
for _, tt := range tests { | ||
t.Run(tt.name, func(t *testing.T) { | ||
if got := StringMatchMask(tt.args.str, tt.args.pattern); got != tt.want { | ||
t.Errorf("StringMatchMask() = %v, want %v", got, tt.want) | ||
} | ||
}) | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,7 +1,6 @@ | ||
package license | ||
|
||
import ( | ||
"slices" | ||
"strings" | ||
|
||
"github.com/deckhouse/dmt/internal/fsutils" | ||
|
@@ -40,10 +39,12 @@ func (o *Copyright) Run(m *module.Module) (errors.LintRuleErrorsList, error) { | |
|
||
result.Merge(OssModuleRule(m.GetName(), m.GetPath())) | ||
|
||
moduleExcludes := getExcludes(o.cfg.CopyrightExcludes, m.GetName()) | ||
|
||
for _, fileName := range files { | ||
name, _ := strings.CutPrefix(fileName, m.GetPath()) | ||
name = m.GetName() + ":" + name | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Here we create a name including the module name so that it can be compared with the list of exceptions. The proposed change below does not do this. As a result, we will compare files with exceptions from other modules. |
||
if slices.Contains(o.cfg.CopyrightExcludes, name) { | ||
|
||
if fsutils.StringMatchAnyMask(name, moduleExcludes) { | ||
continue | ||
} | ||
|
||
|
@@ -80,6 +81,20 @@ func getFiles(rootPath string) ([]string, error) { | |
return result, nil | ||
} | ||
|
||
func getExcludes(excludesList []string, moduleName string) []string { | ||
var result = make([]string, 0) | ||
|
||
// prepare excludes by removing module name prefix | ||
for _, exclude := range excludesList { | ||
pattern, ok := strings.CutPrefix(exclude, moduleName+":") | ||
if ok { | ||
result = append(result, pattern) | ||
} | ||
} | ||
|
||
return result | ||
} | ||
|
||
func (o *Copyright) Name() string { | ||
return o.name | ||
} | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
package license | ||
|
||
import ( | ||
"reflect" | ||
"testing" | ||
) | ||
|
||
func Test_getExcludes(t *testing.T) { | ||
type args struct { | ||
excludesList []string | ||
moduleName string | ||
} | ||
tests := []struct { | ||
name string | ||
args args | ||
want []string | ||
}{ | ||
{ | ||
name: "exclude .venv folder for managed-pg module", | ||
args: args{ | ||
excludesList: []string{"managed-pg:/.venv/**/*", "somemodule:/.venv/**/*", "another-mod:/*.txt", "managed-pg:/enabled"}, | ||
moduleName: "managed-pg", | ||
}, | ||
want: []string{"/.venv/**/*", "/enabled"}, | ||
}, | ||
} | ||
for _, tt := range tests { | ||
t.Run(tt.name, func(t *testing.T) { | ||
if got := getExcludes(tt.args.excludesList, tt.args.moduleName); !reflect.DeepEqual(got, tt.want) { | ||
t.Errorf("getExcludes() = %v, want %v", got, tt.want) | ||
} | ||
}) | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -66,7 +66,7 @@ func (o *NoCyrillic) Run(m *module.Module) (errors.LintRuleErrorsList, error) { | |
for _, fileName := range files { | ||
name, _ := strings.CutPrefix(fileName, m.GetPath()) | ||
name = m.GetName() + ":" + name | ||
if slices.Contains(o.cfg.NoCyrillicFileExcludes, name) { | ||
if fsutils.StringMatchAnyMask(name, o.cfg.NoCyrillicFileExcludes) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Name will look like this: We compare it with an exception like It looks like it should work. It would not be bad to make a test for this solution. |
||
continue | ||
} | ||
if o.skipDocRe.MatchString(fileName) { | ||
|
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.
One more thing, why do we use groups here? As far as I can see, we just match whether this regexp fits our string or not.