command: Restore single-file support in "terraform fmt"

This possibility was lost in the rewrite to use HCL2, but it's used by
a number of external utilities and text editor integrations, so we'll
restore it here.

Using the stdin/stdout mode is generally preferable for text editor use
since it allows formatting of the in-memory buffer rather than directly
the file on disk, but for editors that don't have support for that sort of
tooling it can be convenient to just launch a single command and directly
modify the on-disk file.
This commit is contained in:
Martin Atkins 2019-01-17 10:58:59 -08:00
parent b0a43cab84
commit 176a5abfd3
2 changed files with 59 additions and 7 deletions

View File

@ -64,14 +64,14 @@ func (c *FmtCommand) Run(args []string) int {
return 1
}
var dirs []string
var paths []string
if len(args) == 0 {
dirs = []string{"."}
paths = []string{"."}
} else if args[0] == stdinArg {
c.list = false
c.write = false
} else {
dirs = []string{args[0]}
paths = []string{args[0]}
}
var output io.Writer
@ -86,7 +86,7 @@ func (c *FmtCommand) Run(args []string) int {
output = &cli.UiWriter{Ui: c.Ui}
}
diags := c.fmt(dirs, c.input, output)
diags := c.fmt(paths, c.input, output)
c.showDiagnostics(diags)
if diags.HasErrors() {
return 2
@ -123,8 +123,33 @@ func (c *FmtCommand) fmt(paths []string, stdin io.Reader, stdout io.Writer) tfdi
for _, path := range paths {
path = c.normalizePath(path)
dirDiags := c.processDir(path, stdout)
diags = diags.Append(dirDiags)
info, err := os.Stat(path)
if err != nil {
diags = diags.Append(fmt.Errorf("No file or directory at %s", path))
return diags
}
if info.IsDir() {
dirDiags := c.processDir(path, stdout)
diags = diags.Append(dirDiags)
} else {
switch filepath.Ext(path) {
case ".tf", ".tfvars":
f, err := os.Open(path)
if err != nil {
// Open does not produce error messages that are end-user-appropriate,
// so we'll need to simplify here.
diags = diags.Append(fmt.Errorf("Failed to read file %s", path))
continue
}
fileDiags := c.processFile(c.normalizePath(path), f, stdout, false)
diags = diags.Append(fileDiags)
f.Close()
default:
diags = diags.Append(fmt.Errorf("Only .tf and .tfvars files can be processed with terraform fmt"))
continue
}
}
}
return diags

View File

@ -29,7 +29,7 @@ func TestFmt_nonexist(t *testing.T) {
t.Fatalf("wrong exit code. errors: \n%s", ui.ErrorWriter.String())
}
expected := "There is no configuration directory at"
expected := "No file or directory at"
if actual := ui.ErrorWriter.String(); !strings.Contains(actual, expected) {
t.Fatalf("expected:\n%s\n\nto include: %q", actual, expected)
}
@ -148,6 +148,33 @@ func TestFmt_directoryArg(t *testing.T) {
}
}
func TestFmt_fileArg(t *testing.T) {
tempDir := fmtFixtureWriteDir(t)
ui := new(cli.MockUi)
c := &FmtCommand{
Meta: Meta{
testingOverrides: metaOverridesForProvider(testProvider()),
Ui: ui,
},
}
args := []string{filepath.Join(tempDir, fmtFixture.filename)}
if code := c.Run(args); code != 0 {
t.Fatalf("wrong exit code. errors: \n%s", ui.ErrorWriter.String())
}
got, err := filepath.Abs(strings.TrimSpace(ui.OutputWriter.String()))
if err != nil {
t.Fatal(err)
}
want := filepath.Join(tempDir, fmtFixture.filename)
if got != want {
t.Fatalf("wrong output\ngot: %s\nwant: %s", got, want)
}
}
func TestFmt_stdinArg(t *testing.T) {
input := new(bytes.Buffer)
input.Write(fmtFixture.input)