diff --git a/command/fmt.go b/command/fmt.go index 9352cdabf..9fefd2517 100644 --- a/command/fmt.go +++ b/command/fmt.go @@ -1,6 +1,7 @@ package command import ( + "bytes" "flag" "fmt" "io" @@ -21,6 +22,7 @@ const ( type FmtCommand struct { Meta opts fmtcmd.Options + check bool input io.Reader // STDIN if nil } @@ -38,6 +40,7 @@ func (c *FmtCommand) Run(args []string) int { cmdFlags.BoolVar(&c.opts.List, "list", true, "list") cmdFlags.BoolVar(&c.opts.Write, "write", true, "write") cmdFlags.BoolVar(&c.opts.Diff, "diff", false, "diff") + cmdFlags.BoolVar(&c.check, "check", false, "check") cmdFlags.Usage = func() { c.Ui.Error(c.Help()) } if err := cmdFlags.Parse(args); err != nil { @@ -61,13 +64,37 @@ func (c *FmtCommand) Run(args []string) int { dirs = []string{args[0]} } - output := &cli.UiWriter{Ui: c.Ui} + var output io.Writer + list := c.opts.List // preserve the original value of -list + if c.check { + // set to true so we can use the list output to check + // if the input needs formatting + c.opts.List = true + c.opts.Write = false + output = &bytes.Buffer{} + } else { + output = &cli.UiWriter{Ui: c.Ui} + } + err = fmtcmd.Run(dirs, []string{fileExtension}, c.input, output, c.opts) if err != nil { c.Ui.Error(fmt.Sprintf("Error running fmt: %s", err)) return 2 } + if c.check { + buf := output.(*bytes.Buffer) + ok := buf.Len() == 0 + if list { + io.Copy(&cli.UiWriter{Ui: c.Ui}, buf) + } + if ok { + return 0 + } else { + return 3 + } + } + return 0 } @@ -84,10 +111,12 @@ Options: -list=true List files whose formatting differs (always false if using STDIN) - -write=true Write result to source file instead of STDOUT (always false if using STDIN) + -write=true Write result to source file instead of STDOUT (always false if using STDIN or -check) -diff=false Display diffs of formatting changes + -check=false Check if the input is formatted. Exit status will be 0 if all input is properly formatted and non-zero otherwise. + ` return strings.TrimSpace(helpText) } diff --git a/command/fmt_test.go b/command/fmt_test.go index 3fc34e196..ffaaa7a99 100644 --- a/command/fmt_test.go +++ b/command/fmt_test.go @@ -179,6 +179,60 @@ func TestFmt_nonDefaultOptions(t *testing.T) { } } +func TestFmt_check(t *testing.T) { + tempDir, err := fmtFixtureWriteDir() + if err != nil { + t.Fatalf("err: %s", err) + } + defer os.RemoveAll(tempDir) + + ui := new(cli.MockUi) + c := &FmtCommand{ + Meta: Meta{ + testingOverrides: metaOverridesForProvider(testProvider()), + Ui: ui, + }, + } + + args := []string{ + "-check", + tempDir, + } + if code := c.Run(args); code != 3 { + t.Fatalf("wrong exit code. expected 3") + } + + if actual := ui.OutputWriter.String(); !strings.Contains(actual, tempDir) { + t.Fatalf("expected:\n%s\n\nto include: %q", actual, tempDir) + } +} + +func TestFmt_checkStdin(t *testing.T) { + input := new(bytes.Buffer) + input.Write(fmtFixture.input) + + ui := new(cli.MockUi) + c := &FmtCommand{ + Meta: Meta{ + testingOverrides: metaOverridesForProvider(testProvider()), + Ui: ui, + }, + input: input, + } + + args := []string{ + "-check", + "-", + } + if code := c.Run(args); code != 3 { + t.Fatalf("wrong exit code. expected 3, got %d", code) + } + + if ui.OutputWriter != nil { + t.Fatalf("expected no output, got: %q", ui.OutputWriter.String()) + } +} + var fmtFixture = struct { filename string input, golden []byte