diff --git a/.github/workflows/build-test.yml b/.github/workflows/build-test.yml index 9503674ed..b2bf21776 100644 --- a/.github/workflows/build-test.yml +++ b/.github/workflows/build-test.yml @@ -32,5 +32,7 @@ jobs: run: go mod tidy -diff - name: Run unit tests run: make test-coverage + - name: Test ignore rules with the race detector + run: go test -race ./pkg/ignore - name: Test build run: make build diff --git a/pkg/ignore/rules.go b/pkg/ignore/rules.go index a8160da2a..17fcf6306 100644 --- a/pkg/ignore/rules.go +++ b/pkg/ignore/rules.go @@ -172,8 +172,8 @@ func (r *Rules) parseRule(rule string) error { if after, ok := strings.CutPrefix(rule, "/"); ok { // Require path matches the root path. + rule = after p.match = func(n string, _ os.FileInfo) bool { - rule = after ok, err := filepath.Match(rule, n) if err != nil { slog.Error("failed to compile", slog.String("rule", rule), slog.Any("error", err)) diff --git a/pkg/ignore/rules_test.go b/pkg/ignore/rules_test.go index 30e157a52..310daca43 100644 --- a/pkg/ignore/rules_test.go +++ b/pkg/ignore/rules_test.go @@ -20,6 +20,7 @@ import ( "bytes" "os" "path/filepath" + "sync" "testing" "github.com/stretchr/testify/assert" @@ -133,3 +134,19 @@ func parseString(str string) (*Rules, error) { b := bytes.NewBuffer([]byte(str)) return Parse(b) } + +func TestIgnoreRootPatternConcurrent(t *testing.T) { + // Run with -race to detect concurrent writes even when matching results agree. + rules, err := parseString("/root.txt") + require.NoError(t, err) + var workers sync.WaitGroup + for range 8 { + workers.Go(func() { + for range 100 { + assert.True(t, rules.Ignore("root.txt", nil)) + assert.False(t, rules.Ignore("nested/root.txt", nil)) + } + }) + } + workers.Wait() +}