diff --git a/cli/format.go b/cli/format.go index aa72ff5c..4b14220c 100644 --- a/cli/format.go +++ b/cli/format.go @@ -372,20 +372,24 @@ func applyFormatters(ctx context.Context) func() error { // iterate the files channel, checking if any pipeline wants it, and attempting to apply if so. for file := range filesCh { - var matched bool + var matches []string + for key, pipeline := range pipelines { if !pipeline.Wants(file) { continue } - matched = true + matches = append(matches, key) tryApply(key, file) } - if matched { - stats.Add(stats.Matched, 1) - } else { + switch len(matches) { + case 0: log.Debugf("no match found: %s", file.Path) // no match, so we send it direct to the processed channel processedCh <- file + case 1: + stats.Add(stats.Matched, 1) + default: + return fmt.Errorf("path '%s' matched multiple formatters/pipelines %v", file.Path, matches) } } diff --git a/cli/format_test.go b/cli/format_test.go index 51d26a8f..e4c3b2a3 100644 --- a/cli/format_test.go +++ b/cli/format_test.go @@ -196,6 +196,37 @@ func TestIncludesAndExcludes(t *testing.T) { assertStats(t, as, 31, 31, 2, 0) } +func TestMatchingMultiplePipelines(t *testing.T) { + as := require.New(t) + + tempDir := test.TempExamples(t) + configPath := tempDir + "/multiple.toml" + + cfg := config2.Config{ + Formatters: map[string]*config2.Formatter{ + "echo": { + Command: "echo", + Includes: []string{"*"}, + }, + "touch": { + Command: "touch", + Includes: []string{"*"}, + }, + }, + } + + test.WriteConfig(t, configPath, cfg) + _, err := cmd(t, "-c", "--config-file", configPath, "--tree-root", tempDir) + as.ErrorContains(err, "matched multiple formatters/pipelines") + as.ErrorContains(err, "echo") + as.ErrorContains(err, "touch") + + // run with only one formatter + test.WriteConfig(t, configPath, cfg) + _, err = cmd(t, "-c", "--config-file", configPath, "--tree-root", tempDir, "-f", "echo") + as.NoError(err) +} + func TestCache(t *testing.T) { as := require.New(t)