diff --git a/diff/diff.go b/diff/diff.go index 01bd9269..6b596ffd 100644 --- a/diff/diff.go +++ b/diff/diff.go @@ -6,20 +6,36 @@ import ( "strings" lflags "github.com/launchdarkly/find-code-references-in-pull-request/flags" - "github.com/launchdarkly/find-code-references-in-pull-request/ignore" - diff_util "github.com/launchdarkly/find-code-references-in-pull-request/internal/util/diff_util" + i "github.com/launchdarkly/find-code-references-in-pull-request/ignore" + diff_util "github.com/launchdarkly/find-code-references-in-pull-request/internal/utils/diff_util" + "github.com/launchdarkly/ld-find-code-refs/v2/aliases" lsearch "github.com/launchdarkly/ld-find-code-refs/v2/search" "github.com/sourcegraph/go-diff/diff" ) -type DiffPaths struct { - FileToParse string - Skip bool +func PreprocessDiffs(dir string, multiFiles []*diff.FileDiff) aliases.FileContentsMap { + diffMap := make(map[string][]byte, len(multiFiles)) + + for _, parsedDiff := range multiFiles { + filePath, ignore := checkDiffFile(parsedDiff, dir) + if ignore { + continue + } + + if _, ok := diffMap[filePath]; !ok { + diffMap[filePath] = make([]byte, 0) + } + + for _, hunk := range parsedDiff.Hunks { + diffMap[filePath] = append(diffMap[filePath], hunk.Body...) + } + } + + return diffMap } -func CheckDiff(parsedDiff *diff.FileDiff, workspace string) *DiffPaths { - diffPaths := DiffPaths{} - allIgnores := ignore.NewIgnore(workspace) +func checkDiffFile(parsedDiff *diff.FileDiff, workspace string) (filePath string, ignore bool) { + allIgnores := i.NewIgnore(workspace) // If file is being renamed we don't want to check it for flags. parsedFileA := strings.SplitN(parsedDiff.OrigName, "/", 2) @@ -27,32 +43,32 @@ func CheckDiff(parsedDiff *diff.FileDiff, workspace string) *DiffPaths { fullPathToA := workspace + "/" + parsedFileA[1] fullPathToB := workspace + "/" + parsedFileB[1] info, err := os.Stat(fullPathToB) + if err != nil { + fmt.Println(err) + } var isDir bool // If there is no 'b' parse 'a', means file is deleted. if info == nil { isDir = false - diffPaths.FileToParse = fullPathToA + filePath = fullPathToA } else { isDir = info.IsDir() - diffPaths.FileToParse = fullPathToB - } - if err != nil { - fmt.Println(err) + filePath = fullPathToB } // Similar to ld-find-code-refs do not match dotfiles, and read in ignore files. - if strings.HasPrefix(parsedFileB[1], ".") && strings.HasPrefix(parsedFileA[1], ".") || allIgnores.Match(diffPaths.FileToParse, isDir) { - diffPaths.Skip = true + if strings.HasPrefix(parsedFileB[1], ".") && strings.HasPrefix(parsedFileA[1], ".") || allIgnores.Match(filePath, isDir) { + return filePath, true } // We don't want to run on renaming of files. if (parsedFileA[1] != parsedFileB[1]) && (!strings.Contains(parsedFileB[1], "dev/null") && !strings.Contains(parsedFileA[1], "dev/null")) { - diffPaths.Skip = true + return filePath, true } - return &diffPaths + return filePath, false } -func ProcessDiffs(matcher lsearch.Matcher, hunk *diff.Hunk, builder *lflags.ReferenceBuilder) { - diffLines := strings.Split(string(hunk.Body), "\n") +func ProcessDiffs(matcher lsearch.Matcher, contents []byte, builder *lflags.ReferenceBuilder) { + diffLines := strings.Split(string(contents), "\n") for _, line := range diffLines { op := diff_util.LineOperation(line) if op == diff_util.OperationEqual { diff --git a/diff/diff_test.go b/diff/diff_test.go index 59f84e58..aa89d4b2 100644 --- a/diff/diff_test.go +++ b/diff/diff_test.go @@ -67,7 +67,7 @@ func newProcessFlagAccEnv() *testProcessor { } } -func TestCheckDiff(t *testing.T) { +func Test_checkDiffFile(t *testing.T) { cases := []struct { name string fileName string @@ -105,8 +105,10 @@ func TestCheckDiff(t *testing.T) { NewName: tc.newName, Hunks: []*diff.Hunk{hunk}, } - results := CheckDiff(&diff, "../testdata") - assert.Equal(t, &DiffPaths{FileToParse: "../testdata/" + tc.fileName, Skip: tc.skip}, results, "") + filePath, ignore := checkDiffFile(&diff, "../testdata") + expectedFilePath := "../testdata/" + tc.fileName + assert.Equal(t, expectedFilePath, filePath) + assert.Equal(t, tc.skip, ignore) }) } } @@ -236,20 +238,12 @@ func TestProcessDiffs_BuildReferences(t *testing.T) { for _, tc := range cases { processor := newProcessFlagAccEnv() t.Run(tc.name, func(t *testing.T) { - hunk := &diff.Hunk{ - NewLines: 1, - NewStartLine: 1, - OrigLines: 0, - OrigStartLine: 0, - StartPosition: 1, - Body: []byte(tc.sampleBody), - } elements := []lsearch.ElementMatcher{} elements = append(elements, lsearch.NewElementMatcher("default", "", tc.delimiters, processor.flagKeys(), tc.aliases)) matcher := lsearch.Matcher{ Elements: elements, } - ProcessDiffs(matcher, hunk, processor.Builder) + ProcessDiffs(matcher, []byte(tc.sampleBody), processor.Builder) flagsRef := processor.Builder.Build() assert.Equal(t, tc.expected, flagsRef) }) diff --git a/flags/builder.go b/flags/builder.go index 4e311885..91cf0a66 100644 --- a/flags/builder.go +++ b/flags/builder.go @@ -5,7 +5,7 @@ import ( "sort" "strings" - diff_util "github.com/launchdarkly/find-code-references-in-pull-request/internal/util/diff_util" + diff_util "github.com/launchdarkly/find-code-references-in-pull-request/internal/utils/diff_util" ) type ReferenceBuilder struct { diff --git a/go.mod b/go.mod index 0ceb1016..34025585 100644 --- a/go.mod +++ b/go.mod @@ -17,7 +17,7 @@ require ( github.com/jstemmer/go-junit-report/v2 v2.1.0 github.com/kyoh86/richgo v0.3.12 github.com/launchdarkly/api-client-go/v13 v13.0.0 - github.com/launchdarkly/ld-find-code-refs/v2 v2.11.4 + github.com/launchdarkly/ld-find-code-refs/v2 v2.11.5-0.20231103194119-5133ae5a5429 ) require ( @@ -33,10 +33,10 @@ require ( require ( github.com/Masterminds/goutils v1.1.1 // indirect github.com/Masterminds/semver/v3 v3.2.0 // indirect - github.com/bmatcuk/doublestar/v4 v4.6.0 // indirect + github.com/bmatcuk/doublestar/v4 v4.6.1 // indirect github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect github.com/fsnotify/fsnotify v1.6.0 // indirect - github.com/go-git/go-git/v5 v5.9.0 // indirect + github.com/go-git/go-git/v5 v5.10.0 // indirect github.com/golang/protobuf v1.5.3 // indirect github.com/google/uuid v1.3.0 // indirect github.com/hashicorp/go-cleanhttp v0.5.2 // indirect diff --git a/go.sum b/go.sum index 15f1f220..8716c258 100644 --- a/go.sum +++ b/go.sum @@ -44,8 +44,8 @@ github.com/Masterminds/semver/v3 v3.2.0 h1:3MEsd0SM6jqZojhjLWWeBY+Kcjy9i6MQAeY7Y github.com/Masterminds/semver/v3 v3.2.0/go.mod h1:qvl/7zhW3nngYb5+80sSMF+FG2BjYrf8m9wsX0PNOMQ= github.com/Masterminds/sprig/v3 v3.2.3 h1:eL2fZNezLomi0uOLqjQoN6BfsDD+fyLtgbJMAj9n6YA= github.com/Masterminds/sprig/v3 v3.2.3/go.mod h1:rXcFaZ2zZbLRJv/xSysmlgIM1u11eBaRMhvYXJNkGuM= -github.com/bmatcuk/doublestar/v4 v4.6.0 h1:HTuxyug8GyFbRkrffIpzNCSK4luc0TY3wzXvzIZhEXc= -github.com/bmatcuk/doublestar/v4 v4.6.0/go.mod h1:xBQ8jztBU6kakFMg+8WGxn0c6z1fTSPVIjEY1Wr7jzc= +github.com/bmatcuk/doublestar/v4 v4.6.1 h1:FH9SifrbvJhnlQpztAx++wlkk70QBf0iBWDwNy7PA4I= +github.com/bmatcuk/doublestar/v4 v4.6.1/go.mod h1:xBQ8jztBU6kakFMg+8WGxn0c6z1fTSPVIjEY1Wr7jzc= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= @@ -68,8 +68,8 @@ github.com/fatih/color v1.14.1 h1:qfhVLaG5s+nCROl1zJsZRxFeYrHLqWroPOQ8BWiNb4w= github.com/frankban/quicktest v1.14.4 h1:g2rn0vABPOOXmZUj+vbmUp0lPoXEMuhTpIluN0XL9UY= github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY= github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw= -github.com/go-git/go-git/v5 v5.9.0 h1:cD9SFA7sHVRdJ7AYck1ZaAa/yeuBvGPxwXDL8cxrObY= -github.com/go-git/go-git/v5 v5.9.0/go.mod h1:RKIqga24sWdMGZF+1Ekv9kylsDz6LzdTSI2s/OsZWE0= +github.com/go-git/go-git/v5 v5.10.0 h1:F0x3xXrAWmhwtzoCokU4IMPcBdncG+HAAqi9FcOOjbQ= +github.com/go-git/go-git/v5 v5.10.0/go.mod h1:1FOZ/pQnqw24ghP2n7cunVl0ON55BsjPYvhWHvZGhoo= github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= @@ -180,8 +180,8 @@ github.com/launchdarkly/api-client-go/v7 v7.1.1 h1:3VBkFt9xHljMw5KDlVFDUogxfH78Y github.com/launchdarkly/api-client-go/v7 v7.1.1/go.mod h1:GVl1inKsWoKX3yLgdqrjxWw8k4ih0HlSmdnrhi5NNDs= github.com/launchdarkly/json-patch v0.0.0-20180720210516-dd68d883319f h1:jfiPiz2hE/7mHv2NOS4cm07sSJCsKlbxmR7pzPhhvpU= github.com/launchdarkly/json-patch v0.0.0-20180720210516-dd68d883319f/go.mod h1:CHbYdMs8UjvNnS2fatlQvi4UYnBTRYGxRHc/0kQupSQ= -github.com/launchdarkly/ld-find-code-refs/v2 v2.11.4 h1:kIKFvpaO+zGjvDNPiem5GwZZYFsdA4CLPtJJzFLmM8E= -github.com/launchdarkly/ld-find-code-refs/v2 v2.11.4/go.mod h1:fbIEMBJ4dZYNRC0vrc7V4s2sUWlZhujVef3k8pPGv88= +github.com/launchdarkly/ld-find-code-refs/v2 v2.11.5-0.20231103194119-5133ae5a5429 h1:BzV5r4c7tYaiAngMi3dnU3JcWIkMwS7q4kDR14Tumbc= +github.com/launchdarkly/ld-find-code-refs/v2 v2.11.5-0.20231103194119-5133ae5a5429/go.mod h1:0cSnc1X1lrnw/9uDnuzfLfi//ZsGahmC2Xq2QfudEiA= github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY= github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0= github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= diff --git a/internal/aliases/aliases.go b/internal/aliases/aliases.go new file mode 100644 index 00000000..4253f11f --- /dev/null +++ b/internal/aliases/aliases.go @@ -0,0 +1,42 @@ +package aliases + +import ( + "github.com/launchdarkly/ld-find-code-refs/v2/aliases" + "github.com/launchdarkly/ld-find-code-refs/v2/options" + + "github.com/launchdarkly/find-code-references-in-pull-request/internal/utils" +) + +// Generate aliases, making sure to identify aliases in the removed diff contents +func GenerateAliases(opts options.Options, flagKeys []string, diffContents aliases.FileContentsMap) (map[string][]string, error) { + aliasesByFlagKey, err := aliases.GenerateAliases(flagKeys, opts.Aliases, opts.Dir) + if err != nil { + return nil, err + } + + filePatternAliases := getFilepatternAliases(opts.Aliases) + for _, flag := range flagKeys { + for _, alias := range filePatternAliases { + aliases, err := aliases.GenerateAliasesFromFilePattern(alias, flag, opts.Dir, diffContents) + if err != nil { + // skip aliases that fail to generate + continue + } + aliasesByFlagKey[flag] = append(aliasesByFlagKey[flag], aliases...) + } + aliasesByFlagKey[flag] = utils.Dedupe(aliasesByFlagKey[flag]) + } + + return aliasesByFlagKey, nil +} + +func getFilepatternAliases(aliases []options.Alias) []options.Alias { + filePatternAliases := make([]options.Alias, 0, len(aliases)) + for _, alias := range aliases { + if alias.Type.Canonical() == options.FilePattern { + filePatternAliases = append(filePatternAliases, alias) + } + } + + return filePatternAliases +} diff --git a/internal/util/diff_util/operation.go b/internal/utils/diff_util/operation.go similarity index 100% rename from internal/util/diff_util/operation.go rename to internal/utils/diff_util/operation.go diff --git a/internal/utils/utils.go b/internal/utils/utils.go new file mode 100644 index 00000000..9c5375a8 --- /dev/null +++ b/internal/utils/utils.go @@ -0,0 +1,16 @@ +package utils + +func Dedupe(s []string) []string { + if len(s) <= 1 { + return s + } + keys := make(map[string]struct{}, len(s)) + ret := make([]string, 0, len(s)) + for _, elem := range s { + if _, ok := keys[elem]; !ok { + keys[elem] = struct{}{} + ret = append(ret, elem) + } + } + return ret +} diff --git a/main.go b/main.go index 89924d92..65dee39c 100644 --- a/main.go +++ b/main.go @@ -48,21 +48,17 @@ func main() { opts, err := getOptions(config) failExit(err) - matcher, err := search.GetMatcher(config, opts, flags) + multiFiles, err := getDiffs(ctx, config, *event.PullRequest.Number) failExit(err) - multiFiles, err := getDiffs(ctx, config, *event.PullRequest.Number) + diffMap := ldiff.PreprocessDiffs(opts.Dir, multiFiles) + + matcher, err := search.GetMatcher(opts, flags, diffMap) failExit(err) builder := lflags.NewReferenceBuilder(config.MaxFlags) - for _, parsedDiff := range multiFiles { - getPath := ldiff.CheckDiff(parsedDiff, config.Workspace) - if getPath.Skip { - continue - } - for _, hunk := range parsedDiff.Hunks { - ldiff.ProcessDiffs(matcher, hunk, builder) - } + for _, contents := range diffMap { + ldiff.ProcessDiffs(matcher, contents, builder) } flagsRef := builder.Build() @@ -152,6 +148,7 @@ func getDiffs(ctx context.Context, config *lcr.Config, prNumber int) ([]*diff.Fi return diff.ParseMultiFileDiff([]byte(raw)) } +// Get options from config. Note: dir will be set to workspace func getOptions(config *lcr.Config) (options.Options, error) { // Needed for ld-find-code-refs to work as a library viper.Set("dir", config.Workspace) diff --git a/search/search.go b/search/search.go index 608053e1..6e944a26 100644 --- a/search/search.go +++ b/search/search.go @@ -1,78 +1,34 @@ package search import ( - "log" "strings" ldapi "github.com/launchdarkly/api-client-go/v13" - "github.com/launchdarkly/ld-find-code-refs/v2/aliases" + laliases "github.com/launchdarkly/ld-find-code-refs/v2/aliases" "github.com/launchdarkly/ld-find-code-refs/v2/options" lsearch "github.com/launchdarkly/ld-find-code-refs/v2/search" - lcr "github.com/launchdarkly/find-code-references-in-pull-request/config" - "github.com/spf13/viper" + "github.com/launchdarkly/find-code-references-in-pull-request/internal/aliases" ) -func GetMatcher(config *lcr.Config, opts options.Options, flags []ldapi.FeatureFlag) (matcher lsearch.Matcher, err error) { +func GetMatcher(opts options.Options, flags []ldapi.FeatureFlag, diffContents laliases.FileContentsMap) (matcher lsearch.Matcher, err error) { flagKeys := make([]string, 0, len(flags)) for _, flag := range flags { flagKeys = append(flagKeys, flag.Key) } - aliasesByFlagKey, err := aliases.GenerateAliases(flagKeys, opts.Aliases, config.Workspace) + aliasesByFlagKey, err := aliases.GenerateAliases(opts, flagKeys, diffContents) if err != nil { return lsearch.Matcher{}, err } - delimiters := strings.Join(Dedupe(getDelimiters(opts)), "") - elements := []lsearch.ElementMatcher{} - elements = append(elements, lsearch.NewElementMatcher(config.LdProject, "", delimiters, flagKeys, aliasesByFlagKey)) + delimiters := strings.Join(lsearch.GetDelimiters(opts), "") + elements := make([]lsearch.ElementMatcher, 0, 1) + elements = append(elements, lsearch.NewElementMatcher(opts.ProjKey, "", delimiters, flagKeys, aliasesByFlagKey)) + matcher = lsearch.Matcher{ Elements: elements, } return matcher, nil } - -func getAliases(config *lcr.Config, flagKeys []string) (map[string][]string, error) { - // Needed for ld-find-code-refs to work as a library - viper.Set("dir", config.Workspace) - viper.Set("accessToken", config.ApiToken) - - err := options.InitYAML() - if err != nil { - log.Println(err) - } - opts, err := options.GetOptions() - if err != nil { - log.Println(err) - } - - return aliases.GenerateAliases(flagKeys, opts.Aliases, config.Workspace) -} - -func getDelimiters(opts options.Options) []string { - delims := []string{`"`, `'`, "`"} - if opts.Delimiters.DisableDefaults { - delims = []string{} - } - - delims = append(delims, opts.Delimiters.Additional...) - - return delims -} - -func Dedupe(s []string) []string { - if len(s) <= 1 { - return s - } - keys := make(map[string]struct{}, len(s)) - ret := make([]string, 0, len(s)) - for _, entry := range s { - if _, value := keys[entry]; !value { - keys[entry] = struct{}{} - ret = append(ret, entry) - } - } - return ret -} diff --git a/testdata/aliases b/testdata/aliases index 2c9bd7a6..215f69f3 100644 --- a/testdata/aliases +++ b/testdata/aliases @@ -1 +1 @@ -const myRandomAlias = useFlagValue('beta-ui') +const newRandomAlias = useFlagValue('show-widgets') diff --git a/vendor/github.com/bmatcuk/doublestar/v4/README.md b/vendor/github.com/bmatcuk/doublestar/v4/README.md index be715ff6..70117eff 100644 --- a/vendor/github.com/bmatcuk/doublestar/v4/README.md +++ b/vendor/github.com/bmatcuk/doublestar/v4/README.md @@ -387,8 +387,6 @@ ever since. In that time, it has grown into one of the most popular globbing libraries in the Go ecosystem. So, if **doublestar** is a useful library in your project, consider [sponsoring] my work! I'd really appreciate it! -[![reviewpad](../sponsors/reviewpad.png?raw=true)](https://reviewpad.com/) - Thanks for sponsoring me! ## License diff --git a/vendor/github.com/bmatcuk/doublestar/v4/match.go b/vendor/github.com/bmatcuk/doublestar/v4/match.go index 6581d998..4232c79f 100644 --- a/vendor/github.com/bmatcuk/doublestar/v4/match.go +++ b/vendor/github.com/bmatcuk/doublestar/v4/match.go @@ -301,9 +301,14 @@ MATCH: } func isZeroLengthPattern(pattern string, separator rune) (ret bool, err error) { - // `/**` is a special case - a pattern such as `path/to/a/**` *should* match - // `path/to/a` because `a` might be a directory - if pattern == "" || pattern == "*" || pattern == "**" || pattern == string(separator)+"**" { + // `/**`, `**/`, and `/**/` are special cases - a pattern such as `path/to/a/**` or `path/to/a/**/` + // *should* match `path/to/a` because `a` might be a directory + if pattern == "" || + pattern == "*" || + pattern == "**" || + pattern == string(separator)+"**" || + pattern == "**"+string(separator) || + pattern == string(separator)+"**"+string(separator) { return true, nil } diff --git a/vendor/github.com/go-git/go-git/v5/plumbing/hash/hash.go b/vendor/github.com/go-git/go-git/v5/plumbing/hash/hash.go index 82d18561..8609848f 100644 --- a/vendor/github.com/go-git/go-git/v5/plumbing/hash/hash.go +++ b/vendor/github.com/go-git/go-git/v5/plumbing/hash/hash.go @@ -24,7 +24,7 @@ func reset() { algos[crypto.SHA256] = crypto.SHA256.New } -// RegisterHash allows for the hash algorithm used to be overriden. +// RegisterHash allows for the hash algorithm used to be overridden. // This ensures the hash selection for go-git must be explicit, when // overriding the default value. func RegisterHash(h crypto.Hash, f func() hash.Hash) error { diff --git a/vendor/github.com/go-git/go-git/v5/plumbing/object.go b/vendor/github.com/go-git/go-git/v5/plumbing/object.go index 2655dee4..3ee9de9f 100644 --- a/vendor/github.com/go-git/go-git/v5/plumbing/object.go +++ b/vendor/github.com/go-git/go-git/v5/plumbing/object.go @@ -82,7 +82,7 @@ func (t ObjectType) Valid() bool { return t >= CommitObject && t <= REFDeltaObject } -// IsDelta returns true for any ObjectTyoe that represents a delta (i.e. +// IsDelta returns true for any ObjectType that represents a delta (i.e. // REFDeltaObject or OFSDeltaObject). func (t ObjectType) IsDelta() bool { return t == REFDeltaObject || t == OFSDeltaObject diff --git a/vendor/github.com/launchdarkly/ld-find-code-refs/v2/aliases/alias.go b/vendor/github.com/launchdarkly/ld-find-code-refs/v2/aliases/alias.go index c4a27ae7..38317437 100644 --- a/vendor/github.com/launchdarkly/ld-find-code-refs/v2/aliases/alias.go +++ b/vendor/github.com/launchdarkly/ld-find-code-refs/v2/aliases/alias.go @@ -45,32 +45,45 @@ func GenerateAliases(flags []string, aliases []options.Alias, dir string) (map[s return ret, nil } -func generateAlias(a options.Alias, flag, dir string, allFileContents map[string][]byte) (ret []string, err error) { +func generateAlias(a options.Alias, flag, dir string, allFileContents FileContentsMap) (ret []string, err error) { switch a.Type.Canonical() { case options.Literal: ret = a.Flags[flag] + case options.FilePattern: + ret, err = GenerateAliasesFromFilePattern(a, flag, dir, allFileContents) + case options.Command: + ret, err = GenerateAliasesFromCommand(a, flag, dir) + default: + var alias string + alias, err = GenerateNamingConventionAlias(a, flag) + ret = []string{alias} + } + + return ret, err +} + +func GenerateNamingConventionAlias(a options.Alias, flag string) (alias string, err error) { + switch a.Type.Canonical() { case options.CamelCase: - ret = []string{strcase.ToLowerCamel(flag)} + alias = strcase.ToLowerCamel(flag) case options.PascalCase: - ret = []string{strcase.ToCamel(flag)} + alias = strcase.ToCamel(flag) case options.SnakeCase: - ret = []string{strcase.ToSnake(flag)} + alias = strcase.ToSnake(flag) case options.UpperSnakeCase: - ret = []string{strcase.ToScreamingSnake(flag)} + alias = strcase.ToScreamingSnake(flag) case options.KebabCase: - ret = []string{strcase.ToKebab(flag)} + alias = strcase.ToKebab(flag) case options.DotCase: - ret = []string{strcase.ToDelimited(flag, '.')} - case options.FilePattern: - ret, err = generateAliasesFromFilePattern(a, flag, dir, allFileContents) - case options.Command: - ret, err = generateAliasesFromCommand(a, flag, dir) + alias = strcase.ToDelimited(flag, '.') + default: + err = fmt.Errorf("naming convention alias type %s not recognized", a.Type) } - return ret, err + return alias, err } -func generateAliasesFromFilePattern(a options.Alias, flag, dir string, allFileContents map[string][]byte) ([]string, error) { +func GenerateAliasesFromFilePattern(a options.Alias, flag, dir string, allFileContents FileContentsMap) ([]string, error) { ret := []string{} // Concatenate the contents of all files into a single byte array to be matched by specified patterns fileContents := []byte{} @@ -100,7 +113,7 @@ func generateAliasesFromFilePattern(a options.Alias, flag, dir string, allFileCo return ret, nil } -func generateAliasesFromCommand(a options.Alias, flag, dir string) ([]string, error) { +func GenerateAliasesFromCommand(a options.Alias, flag, dir string) ([]string, error) { ret := []string{} ctx := context.Background() if a.Timeout != nil && *a.Timeout > 0 { @@ -130,7 +143,7 @@ func generateAliasesFromCommand(a options.Alias, flag, dir string) ([]string, er } // processFileContent reads and stores the content of files specified by filePattern alias matchers to be matched for aliases -func processFileContent(aliases []options.Alias, dir string) (map[string][]byte, error) { +func processFileContent(aliases []options.Alias, dir string) (FileContentsMap, error) { allFileContents := map[string][]byte{} for idx, a := range aliases { if a.Type.Canonical() != options.FilePattern { diff --git a/vendor/github.com/launchdarkly/ld-find-code-refs/v2/aliases/types.go b/vendor/github.com/launchdarkly/ld-find-code-refs/v2/aliases/types.go new file mode 100644 index 00000000..40c17ace --- /dev/null +++ b/vendor/github.com/launchdarkly/ld-find-code-refs/v2/aliases/types.go @@ -0,0 +1,4 @@ +package aliases + +// Map of full file path to file contents +type FileContentsMap = map[string][]byte diff --git a/vendor/github.com/launchdarkly/ld-find-code-refs/v2/internal/ld/ld.go b/vendor/github.com/launchdarkly/ld-find-code-refs/v2/internal/ld/ld.go index 1962f67e..70a8c1ff 100644 --- a/vendor/github.com/launchdarkly/ld-find-code-refs/v2/internal/ld/ld.go +++ b/vendor/github.com/launchdarkly/ld-find-code-refs/v2/internal/ld/ld.go @@ -114,7 +114,7 @@ func (c ApiClient) GetFlagKeyList(projKey string) ([]string, error) { } flagReq := c.ldClient.FeatureFlagsApi.GetFeatureFlags(ctx, projKey).Summary(true) - archiveReq := c.ldClient.FeatureFlagsApi.GetFeatureFlags(ctx, projKey).Summary(true).Archived(true) + archiveReq := c.ldClient.FeatureFlagsApi.GetFeatureFlags(ctx, projKey).Summary(true).Filter("state:archived") if len(project.Environments) > 0 { // The first environment allows filtering when retrieving flags. diff --git a/vendor/github.com/launchdarkly/ld-find-code-refs/v2/search/delimiters.go b/vendor/github.com/launchdarkly/ld-find-code-refs/v2/search/delimiters.go new file mode 100644 index 00000000..26d88f1f --- /dev/null +++ b/vendor/github.com/launchdarkly/ld-find-code-refs/v2/search/delimiters.go @@ -0,0 +1,19 @@ +package search + +import ( + "github.com/launchdarkly/ld-find-code-refs/v2/internal/helpers" + "github.com/launchdarkly/ld-find-code-refs/v2/options" +) + +// Get a list of delimiters to use for flag key matching +// If defaults are disabled, only additional configured delimiters will be used +func GetDelimiters(opts options.Options) []string { + delims := []string{`"`, `'`, "`"} + if opts.Delimiters.DisableDefaults { + delims = []string{} + } + + delims = append(delims, opts.Delimiters.Additional...) + + return helpers.Dedupe(delims) +} diff --git a/vendor/github.com/launchdarkly/ld-find-code-refs/v2/search/element_matcher.go b/vendor/github.com/launchdarkly/ld-find-code-refs/v2/search/element_matcher.go new file mode 100644 index 00000000..9ebf97ee --- /dev/null +++ b/vendor/github.com/launchdarkly/ld-find-code-refs/v2/search/element_matcher.go @@ -0,0 +1,82 @@ +package search + +import ( + "github.com/launchdarkly/ld-find-code-refs/v2/internal/helpers" + ahocorasick "github.com/petar-dambovaliev/aho-corasick" +) + +type ElementMatcher struct { + ProjKey string + Elements []string + Dir string + allElementAndAliasesMatcher ahocorasick.AhoCorasick + matcherByElement map[string]ahocorasick.AhoCorasick + aliasMatcherByElement map[string]ahocorasick.AhoCorasick + + elementsByPatternIndex [][]string +} + +func (m ElementMatcher) FindMatches(line string) []string { + elements := make([]string, 0) + iter := m.allElementAndAliasesMatcher.IterOverlapping(line) + for match := iter.Next(); match != nil; match = iter.Next() { + elements = append(elements, m.elementsByPatternIndex[match.Pattern()]...) + } + return helpers.Dedupe(elements) +} + +func (m ElementMatcher) FindAliases(line, element string) []string { + aliasMatches := make([]string, 0) + if aliasMatcher, exists := m.aliasMatcherByElement[element]; exists { + iter := aliasMatcher.IterOverlapping(line) + for match := iter.Next(); match != nil; match = iter.Next() { + aliasMatches = append(aliasMatches, line[match.Start():match.End()]) + } + } + return aliasMatches +} + +func NewElementMatcher(projKey, dir, delimiters string, elements []string, aliasesByElement map[string][]string) ElementMatcher { + matcherBuilder := ahocorasick.NewAhoCorasickBuilder(ahocorasick.Opts{DFA: true, MatchKind: ahocorasick.StandardMatch}) + + allFlagPatternsAndAliases := make([]string, 0) + elementsByPatternIndex := make([][]string, 0) + patternIndex := make(map[string]int) + + recordPatternsForElement := func(element string, patterns []string) { + for _, p := range patterns { + index, exists := patternIndex[p] + if !exists { + allFlagPatternsAndAliases = append(allFlagPatternsAndAliases, p) + index = len(elementsByPatternIndex) + elementsByPatternIndex = append(elementsByPatternIndex, []string{}) + } + patternIndex[p] = index + elementsByPatternIndex[index] = append(elementsByPatternIndex[index], element) + } + } + + patternsByElement := buildElementPatterns(elements, delimiters) + flagMatcherByKey := make(map[string]ahocorasick.AhoCorasick, len(patternsByElement)) + for element, patterns := range patternsByElement { + flagMatcherByKey[element] = matcherBuilder.Build(patterns) + recordPatternsForElement(element, patterns) + } + + aliasMatcherByElement := make(map[string]ahocorasick.AhoCorasick, len(aliasesByElement)) + for element, elementAliases := range aliasesByElement { + aliasMatcherByElement[element] = matcherBuilder.Build(elementAliases) + recordPatternsForElement(element, elementAliases) + } + + return ElementMatcher{ + Elements: elements, + ProjKey: projKey, + Dir: dir, + matcherByElement: flagMatcherByKey, + aliasMatcherByElement: aliasMatcherByElement, + allElementAndAliasesMatcher: matcherBuilder.Build(allFlagPatternsAndAliases), + + elementsByPatternIndex: elementsByPatternIndex, + } +} diff --git a/vendor/github.com/launchdarkly/ld-find-code-refs/v2/search/matcher.go b/vendor/github.com/launchdarkly/ld-find-code-refs/v2/search/matcher.go index 6478f0ca..765fb13a 100644 --- a/vendor/github.com/launchdarkly/ld-find-code-refs/v2/search/matcher.go +++ b/vendor/github.com/launchdarkly/ld-find-code-refs/v2/search/matcher.go @@ -3,36 +3,20 @@ package search import ( "strings" - ahocorasick "github.com/petar-dambovaliev/aho-corasick" - "github.com/launchdarkly/ld-find-code-refs/v2/aliases" - "github.com/launchdarkly/ld-find-code-refs/v2/flags" "github.com/launchdarkly/ld-find-code-refs/v2/internal/helpers" - "github.com/launchdarkly/ld-find-code-refs/v2/internal/ld" "github.com/launchdarkly/ld-find-code-refs/v2/internal/log" "github.com/launchdarkly/ld-find-code-refs/v2/options" ) -type ElementMatcher struct { - ProjKey string - Elements []string - Dir string - allElementAndAliasesMatcher ahocorasick.AhoCorasick - matcherByElement map[string]ahocorasick.AhoCorasick - aliasMatcherByElement map[string]ahocorasick.AhoCorasick - - elementsByPatternIndex [][]string -} - type Matcher struct { Elements []ElementMatcher ctxLines int } -// Scan checks the configured directory for flags base on the options configured for Code References. -func Scan(opts options.Options, repoParams ld.RepoParams, dir string) (Matcher, []ld.ReferenceHunksRep) { - flagKeys := flags.GetFlagKeys(opts, repoParams) - elements := []ElementMatcher{} +func NewMultiProjectMatcher(opts options.Options, dir string, flagKeys map[string][]string) Matcher { + elements := make([]ElementMatcher, 0, len(opts.Projects)) + delimiters := strings.Join(GetDelimiters(opts), "") for _, project := range opts.Projects { projectFlags := flagKeys[project.Key] @@ -43,76 +27,13 @@ func Scan(opts options.Options, repoParams ld.RepoParams, dir string) (Matcher, log.Error.Fatalf("failed to generate aliases: %s for project: %s", err, project.Key) } - delimiters := strings.Join(helpers.Dedupe(getDelimiters(opts)), "") elements = append(elements, NewElementMatcher(project.Key, project.Dir, delimiters, projectFlags, aliasesByFlagKey)) } - matcher := Matcher{ + + return Matcher{ ctxLines: opts.ContextLines, Elements: elements, } - - refs, err := SearchForRefs(dir, matcher) - if err != nil { - log.Error.Fatalf("error searching for flag key references: %s", err) - } - - return matcher, refs -} - -func NewElementMatcher(projKey, dir, delimiters string, elements []string, aliasesByElement map[string][]string) ElementMatcher { - matcherBuilder := ahocorasick.NewAhoCorasickBuilder(ahocorasick.Opts{DFA: true, MatchKind: ahocorasick.StandardMatch}) - - allFlagPatternsAndAliases := make([]string, 0) - elementsByPatternIndex := make([][]string, 0) - patternIndex := make(map[string]int) - - recordPatternsForElement := func(element string, patterns []string) { - for _, p := range patterns { - index, exists := patternIndex[p] - if !exists { - allFlagPatternsAndAliases = append(allFlagPatternsAndAliases, p) - index = len(elementsByPatternIndex) - elementsByPatternIndex = append(elementsByPatternIndex, []string{}) - } - patternIndex[p] = index - elementsByPatternIndex[index] = append(elementsByPatternIndex[index], element) - } - } - - patternsByElement := buildElementPatterns(elements, delimiters) - flagMatcherByKey := make(map[string]ahocorasick.AhoCorasick, len(patternsByElement)) - for element, patterns := range patternsByElement { - flagMatcherByKey[element] = matcherBuilder.Build(patterns) - recordPatternsForElement(element, patterns) - } - - aliasMatcherByElement := make(map[string]ahocorasick.AhoCorasick, len(aliasesByElement)) - for element, elementAliases := range aliasesByElement { - aliasMatcherByElement[element] = matcherBuilder.Build(elementAliases) - recordPatternsForElement(element, elementAliases) - } - - return ElementMatcher{ - Elements: elements, - ProjKey: projKey, - Dir: dir, - matcherByElement: flagMatcherByKey, - aliasMatcherByElement: aliasMatcherByElement, - allElementAndAliasesMatcher: matcherBuilder.Build(allFlagPatternsAndAliases), - - elementsByPatternIndex: elementsByPatternIndex, - } -} - -func getDelimiters(opts options.Options) []string { - delims := []string{`"`, `'`, "`"} - if opts.Delimiters.DisableDefaults { - delims = []string{} - } - - delims = append(delims, opts.Delimiters.Additional...) - - return delims } func (m Matcher) MatchElement(line, element string) bool { @@ -146,24 +67,11 @@ func (m Matcher) FindAliases(line, element string) []string { return helpers.Dedupe(matches) } -func (m ElementMatcher) FindMatches(line string) []string { - elements := make([]string, 0) - iter := m.allElementAndAliasesMatcher.IterOverlapping(line) - for match := iter.Next(); match != nil; match = iter.Next() { - elements = append(elements, m.elementsByPatternIndex[match.Pattern()]...) - } - return helpers.Dedupe(elements) -} - -func (m ElementMatcher) FindAliases(line, element string) []string { - aliasMatches := make([]string, 0) - if aliasMatcher, exists := m.aliasMatcherByElement[element]; exists { - iter := aliasMatcher.IterOverlapping(line) - for match := iter.Next(); match != nil; match = iter.Next() { - aliasMatches = append(aliasMatches, line[match.Start():match.End()]) - } +func (m Matcher) GetElements() (elements [][]string) { + for _, element := range m.Elements { + elements = append(elements, element.Elements) } - return aliasMatches + return elements } func buildElementPatterns(flags []string, delimiters string) map[string][]string { @@ -189,10 +97,3 @@ func buildElementPatterns(flags []string, delimiters string) map[string][]string } return patternsByFlag } - -func (m Matcher) GetElements() (elements [][]string) { - for _, element := range m.Elements { - elements = append(elements, element.Elements) - } - return elements -} diff --git a/vendor/github.com/launchdarkly/ld-find-code-refs/v2/search/scan.go b/vendor/github.com/launchdarkly/ld-find-code-refs/v2/search/scan.go new file mode 100644 index 00000000..692130e8 --- /dev/null +++ b/vendor/github.com/launchdarkly/ld-find-code-refs/v2/search/scan.go @@ -0,0 +1,21 @@ +package search + +import ( + "github.com/launchdarkly/ld-find-code-refs/v2/flags" + "github.com/launchdarkly/ld-find-code-refs/v2/internal/ld" + "github.com/launchdarkly/ld-find-code-refs/v2/internal/log" + "github.com/launchdarkly/ld-find-code-refs/v2/options" +) + +// Scan checks the configured directory for flags based on the options configured for Code References. +func Scan(opts options.Options, repoParams ld.RepoParams, dir string) (Matcher, []ld.ReferenceHunksRep) { + flagKeys := flags.GetFlagKeys(opts, repoParams) + matcher := NewMultiProjectMatcher(opts, dir, flagKeys) + + refs, err := SearchForRefs(dir, matcher) + if err != nil { + log.Error.Fatalf("error searching for flag key references: %s", err) + } + + return matcher, refs +} diff --git a/vendor/modules.txt b/vendor/modules.txt index ed7af267..ddac4e0f 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -7,7 +7,7 @@ github.com/Masterminds/semver/v3 # github.com/Masterminds/sprig/v3 v3.2.3 ## explicit; go 1.13 github.com/Masterminds/sprig/v3 -# github.com/bmatcuk/doublestar/v4 v4.6.0 +# github.com/bmatcuk/doublestar/v4 v4.6.1 ## explicit; go 1.16 github.com/bmatcuk/doublestar/v4 # github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc @@ -16,7 +16,7 @@ github.com/davecgh/go-spew/spew # github.com/fsnotify/fsnotify v1.6.0 ## explicit; go 1.16 github.com/fsnotify/fsnotify -# github.com/go-git/go-git/v5 v5.9.0 +# github.com/go-git/go-git/v5 v5.10.0 ## explicit; go 1.19 github.com/go-git/go-git/v5/plumbing github.com/go-git/go-git/v5/plumbing/hash @@ -86,7 +86,7 @@ github.com/launchdarkly/api-client-go/v7 # github.com/launchdarkly/json-patch v0.0.0-20180720210516-dd68d883319f ## explicit github.com/launchdarkly/json-patch -# github.com/launchdarkly/ld-find-code-refs/v2 v2.11.4 +# github.com/launchdarkly/ld-find-code-refs/v2 v2.11.5-0.20231103194119-5133ae5a5429 ## explicit; go 1.20 github.com/launchdarkly/ld-find-code-refs/v2/aliases github.com/launchdarkly/ld-find-code-refs/v2/flags