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

Add globbing pattern matching for search_path (Replaces #179) #215

Merged
merged 2 commits into from
Dec 17, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 19 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,8 @@ optional flags:
A comma separated list of file types to ignore
-groupby string
Group output by filetype, directory, pass-fail. Supported for Standard and JSON reports
-globbing bool
Set globbing to true to enable pattern matching for search paths. Enclose the pattern in double quotes. The flag is not compatible with -exclude-dirs and -exclude-file-types.
-quiet
If quiet flag is set. It doesn't print any output to stdout.
-reporter string
Expand Down Expand Up @@ -210,6 +212,23 @@ Passing the `--quiet` flag suppresses all output to stdout. If there are invalid
validator --quiet /path/to/search
```

### Search files using a glob pattern

Use the `-globbing` flag to validate files matching a specified pattern. Include the pattern as a positional argument in double quotes. Multiple glob patterns and direct file paths are supported. If invalid config files are detected, the validator tool exits with code 1, and errors (e.g., invalid patterns) are displayed.

[Learn more about glob patterns](https://www.digitalocean.com/community/tools/glob)

```
# Validate all `.json` files in a directory
validator -globbing "/path/to/files/*.json"

# Recursively validate all `.json` files in subdirectories
validator -globbing "/path/to/files/**/*.json"

# Mix glob patterns and paths
validator -globbing "/path/*.json" /path/to/search
```

#### Container Run
```
docker run -it --rm -v /path/to/config/files:/test config-file-validator:1.6.0 /test
Expand Down
54 changes: 48 additions & 6 deletions cmd/validator/validator.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ optional flags:
Subdirectories to exclude when searching for configuration files
-exclude-file-types string
A comma separated list of file types to ignore
-globbing bool
Set globbing to true to enable pattern matching for search paths
-reporter string
A string representing report format and optional output file path separated by colon if present.
Usage: --reporter <format>:<optional_file_path>
Expand All @@ -39,6 +41,8 @@ import (
"sort"
"strings"

"github.com/bmatcuk/doublestar/v4"

configfilevalidator "github.com/Boeing/config-file-validator"
"github.com/Boeing/config-file-validator/pkg/cli"
"github.com/Boeing/config-file-validator/pkg/filetype"
Expand All @@ -55,6 +59,7 @@ type validatorConfig struct {
versionQuery *bool
groupOutput *string
quiet *bool
globbing *bool
}

type reporterFlags []string
Expand Down Expand Up @@ -121,6 +126,7 @@ func getFlags() (validatorConfig, error) {
versionPtr = flag.Bool("version", false, "Version prints the release version of validator")
groupOutputPtr = flag.String("groupby", "", "Group output by filetype, directory, pass-fail. Supported for Standard and JSON reports")
quietPtr = flag.Bool("quiet", false, "If quiet flag is set. It doesn't print any output to stdout.")
globbingPrt = flag.Bool("globbing", false, "If globbing flag is set, check for glob patterns in the arguments.")
)
flag.Var(
&reporterConfigFlags,
Expand All @@ -144,7 +150,14 @@ Supported formats: standard, json, junit (default: "standard")`,
return validatorConfig{}, err
}

searchPaths := parseSearchPath()
if err := validateGlobbing(globbingPrt); err != nil {
return validatorConfig{}, err
}

searchPaths, err := parseSearchPath(globbingPrt)
if err != nil {
return validatorConfig{}, err
}

err = validateReporterConf(reporterConf, groupOutputPtr)
if err != nil {
Expand Down Expand Up @@ -176,6 +189,7 @@ Supported formats: standard, json, junit (default: "standard")`,
versionPtr,
groupOutputPtr,
quietPtr,
globbingPrt,
}

return config, nil
Expand Down Expand Up @@ -221,19 +235,42 @@ func validateGroupByConf(groupBy *string) error {
return nil
}

func parseSearchPath() []string {
func validateGlobbing(globbingPrt *bool) error {
if *globbingPrt && (isFlagSet("exclude-dirs") || isFlagSet("exclude-file-types")) {
fmt.Println("The -globbing flag cannot be used with --exclude-dirs or --exclude-file-types")
flag.Usage()
return errors.New("the -globbing flag cannot be used with --exclude-dirs or --exclude-file-types")
}
return nil
}

func parseSearchPath(globbingPrt *bool) ([]string, error) {
searchPaths := make([]string, 0)

// If search path arg is empty, set it to the cwd
// if not, set it to the arg. Supports n number of
// paths
if flag.NArg() == 0 {
searchPaths = append(searchPaths, ".")
} else if *globbingPrt {
return handleGlobbing(searchPaths)
} else {
searchPaths = append(searchPaths, flag.Args()...)
}

return searchPaths
return searchPaths, nil
}

func handleGlobbing(searchPaths []string) ([]string, error) {
for _, flagArg := range flag.Args() {
if isGlobPattern(flagArg) {
matches, err := doublestar.Glob(os.DirFS("."), flagArg)
if err != nil {
return nil, errors.New("Glob matching error")
}
searchPaths = append(searchPaths, matches...)
} else {
searchPaths = append(searchPaths, flagArg)
}
}
return searchPaths, nil
}

func parseReporterFlags(flags reporterFlags) (map[string]string, error) {
Expand Down Expand Up @@ -332,6 +369,11 @@ func cleanString(command string) string {
return cleanedString
}

// Function to check if a string is a glob pattern
func isGlobPattern(s string) bool {
return strings.ContainsAny(s, "*?[]")
}

func mainInit() int {
validatorConfig, err := getFlags()
if err != nil {
Expand Down
6 changes: 6 additions & 0 deletions cmd/validator/validator_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,12 @@ func Test_flags(t *testing.T) {
{"grouped sarif", []string{"-groupby=directory", "--reporter=sarif", "."}, 1},
{"groupby duplicate", []string{"--groupby=directory,directory", "."}, 1},
{"quiet flag", []string{"--quiet=true", "."}, 0},
{"globbing flag set", []string{"--globbing=true", "."}, 0},
{"globbing flag with a pattern", []string{"--globbing=true", "../../test/**/[m-t]*.json"}, 0},
{"globbing flag with no matches", []string{"--globbing=true", "../../test/**/*.nomatch"}, 0},
{"globbing flag not set", []string{"test/**/*.json", "."}, 1},
{"globbing flag with exclude-dirs", []string{"-globbing", "--exclude-dirs=subdir", "test/**/*.json", "."}, 1},
{"globbing flag with exclude-file-types", []string{"-globbing", "--exclude-file-types=hcl", "test/**/*.json", "."}, 1},
}
for _, tc := range cases {
// this call is required because otherwise flags panics,
Expand Down
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ module github.com/Boeing/config-file-validator
go 1.21.0

require (
github.com/bmatcuk/doublestar/v4 v4.7.1
github.com/editorconfig/editorconfig-core-go/v2 v2.6.2
github.com/fatih/color v1.13.0
github.com/gurkankaymak/hocon v1.2.18
Expand Down
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ github.com/apparentlymart/go-textseg/v13 v13.0.0 h1:Y+KvPE1NYz0xl601PVImeQfFyEy6
github.com/apparentlymart/go-textseg/v13 v13.0.0/go.mod h1:ZK2fH7c4NqDTLtiYLvIkEghdlcqw7yxLeM89kiTRPUo=
github.com/apparentlymart/go-textseg/v15 v15.0.0 h1:uYvfpb3DyLSCGWnctWKGj857c6ew1u1fNQOlOtuGxQY=
github.com/apparentlymart/go-textseg/v15 v15.0.0/go.mod h1:K8XmNZdhEBkdlyDdvbmmsvpAG721bKi0joRfFdHIWJ4=
github.com/bmatcuk/doublestar/v4 v4.7.1 h1:fdDeAqgT47acgwd9bd9HxJRDmc9UAmPpc+2m0CXv75Q=
github.com/bmatcuk/doublestar/v4 v4.7.1/go.mod h1:xBQ8jztBU6kakFMg+8WGxn0c6z1fTSPVIjEY1Wr7jzc=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/editorconfig/editorconfig-core-go/v2 v2.6.2 h1:dKG8sc7n321deIVRcQtwlMNoBEra7j0qQ8RwxO8RN0w=
Expand Down
Loading