diff --git a/utils/modifycommand.go b/utils/modifycommand.go index 248c006..b3ae52c 100644 --- a/utils/modifycommand.go +++ b/utils/modifycommand.go @@ -62,6 +62,7 @@ func (c *ModifyCommand) Validate() error { // Ehh.. Not much better... Guess this wasn't the big deal var matchesMemoTable map[string]bool = make(map[string]bool) +var globMemoTable map[string][]string = make(map[string][]string) func Matches(path string, glob string) (bool, error) { matchesLogger := modifyCommandLogger.WithPrefix("Matches").WithField("path", path).WithField("glob", glob) @@ -225,10 +226,16 @@ func ExpandGlobs(patterns map[string]struct{}) ([]string, error) { for pattern := range patterns { expandGlobsLogger.Debug("Processing glob pattern: %q", pattern) static, pattern := SplitPattern(pattern) - matches, err := doublestar.Glob(os.DirFS(static), pattern) - if err != nil { - expandGlobsLogger.Warning("Error expanding glob %q in %q: %v", pattern, static, err) - continue + key := static + "|" + pattern + matches, ok := globMemoTable[key] + if !ok { + var err error + matches, err = doublestar.Glob(os.DirFS(static), pattern) + if err != nil { + expandGlobsLogger.Warning("Error expanding glob %q in %q: %v", pattern, static, err) + continue + } + globMemoTable[key] = matches } expandGlobsLogger.Debug("Found %d matches for pattern %q", len(matches), pattern) expandGlobsLogger.Trace("Raw matches for pattern %q: %v", pattern, matches) diff --git a/utils/modifycommand_test.go b/utils/modifycommand_test.go index 82659d3..3e54ddf 100644 --- a/utils/modifycommand_test.go +++ b/utils/modifycommand_test.go @@ -705,6 +705,58 @@ func TestLoadCommandsFromCookFilesNoYamlFiles(t *testing.T) { // } // } +func TestExpandGlobsMemoization(t *testing.T) { + tmpDir, err := os.MkdirTemp("", "expand-globs-memo-test") + if err != nil { + t.Fatalf("Failed to create temp dir: %v", err) + } + defer os.RemoveAll(tmpDir) + + err = os.WriteFile(filepath.Join(tmpDir, "test1.go"), []byte("test"), 0644) + if err != nil { + t.Fatalf("Failed to create test file: %v", err) + } + err = os.WriteFile(filepath.Join(tmpDir, "test2.go"), []byte("test"), 0644) + if err != nil { + t.Fatalf("Failed to create test file: %v", err) + } + + origDir, _ := os.Getwd() + os.Chdir(tmpDir) + defer os.Chdir(origDir) + + cwd, _ := os.Getwd() + resolvedCwd := ResolvePath(cwd) + pattern1 := resolvedCwd + "/*.go" + patterns := map[string]struct{}{pattern1: {}} + + globMemoTable = make(map[string][]string) + + files1, err := ExpandGlobs(patterns) + if err != nil { + t.Fatalf("ExpandGlobs failed: %v", err) + } + if len(files1) != 2 { + t.Fatalf("Expected 2 files, got %d", len(files1)) + } + + if len(globMemoTable) != 1 { + t.Fatalf("Expected 1 entry in memo table, got %d", len(globMemoTable)) + } + + files2, err := ExpandGlobs(patterns) + if err != nil { + t.Fatalf("ExpandGlobs failed: %v", err) + } + if len(files2) != 2 { + t.Fatalf("Expected 2 files, got %d", len(files2)) + } + + if len(globMemoTable) != 1 { + t.Fatalf("Expected memo table to still have 1 entry, got %d", len(globMemoTable)) + } +} + // LoadCommandsFromCookFile returns an error for a malformed YAML file // func TestLoadCommandsFromCookFilesMalformedYAML(t *testing.T) { // // Setup test directory with mock YAML files