Skip to content

Commit

Permalink
Adds option to mask Go format verbs in blocks output (#29)
Browse files Browse the repository at this point in the history
  • Loading branch information
gdavison authored Oct 28, 2020
1 parent 5ff4421 commit 3912d4c
Show file tree
Hide file tree
Showing 3 changed files with 88 additions and 14 deletions.
19 changes: 18 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,24 @@ Use the `blocks` command to extract blocks from a file:

![blocks](_docs/blocks.png)

To output only the block content, separated by the null character, use the flags ``--zero-terminated` or `z`.
To output only the block content, separated by the null character, use the flags `--zero-terminated` or `z`.

To output the blocks using a JSON structure, use the flags `--json` or `-j`. The format is

```json
{
"block_count": 1,
"blocks": [
{
"start_line": 4,
"end_line": 9,
"text": "..."
}
]
}
```

Go [format verbs](https://golang.org/pkg/fmt/) can be escaped in the output blocks by using the flags `--fmtcompat` or `-f`.

To output the blocks using a JSON structure, use the flags `--json` or `-j`. The format is

Expand Down
74 changes: 63 additions & 11 deletions cli/blocks_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (

c "github.com/gookit/color"
"github.com/katbyte/terrafmt/lib/common"
"github.com/katbyte/terrafmt/lib/fmtverbs"
"github.com/kylelemons/godebug/diff"
"github.com/spf13/afero"
)
Expand Down Expand Up @@ -127,13 +128,15 @@ var blocksTestcases = []struct {
lineCount: 20,
expectedBlocks: []block{
{
endLine: 12,
startLine: 8,
endLine: 12,
text: `rrrrrresource "aws_s3_bucket" "rrrrrrr" {
bucket = "tf-test-bucket"
}`,
},
{
endLine: 19,
startLine: 16,
endLine: 19,
text: `resource "aws_s3_bucket" "unclosed" {
bucket = "tf-test-bucket"`,
},
Expand All @@ -145,7 +148,8 @@ var blocksTestcases = []struct {
lineCount: 21,
expectedBlocks: []block{
{
endLine: 20,
startLine: 8,
endLine: 20,
text: `resource "aws_s3_bucket" "multi-verb" {
bucket = "tf-test-bucket"
Expand Down Expand Up @@ -253,7 +257,7 @@ func TestCmdBlocksDefault(t *testing.T) {
var outB strings.Builder
var errB strings.Builder
log := common.CreateLogger(&errB)
err := findBlocksInFile(fs, log, testcase.sourcefile, false, false, false, nil, &outB, &errB)
err := findBlocksInFile(fs, log, testcase.sourcefile, false, false, false, false, nil, &outB, &errB)
actualStdOut := outB.String()
actualStdErr := errB.String()

Expand All @@ -262,7 +266,7 @@ func TestCmdBlocksDefault(t *testing.T) {
}

if actualStdOut != expected {
t.Errorf("Output does not match expected:\n%s", diff.Diff(actualStdOut, expected))
t.Errorf("Output does not match expected: ('-' actual, '+' expected)\n%s", diff.Diff(actualStdOut, expected))
}

if actualStdErr != "" {
Expand All @@ -285,7 +289,7 @@ func TestCmdBlocksVerbose(t *testing.T) {
var outB strings.Builder
var errB strings.Builder
log := common.CreateLogger(&errB)
err := findBlocksInFile(fs, log, testcase.sourcefile, true, false, false, nil, &outB, &errB)
err := findBlocksInFile(fs, log, testcase.sourcefile, true, false, false, false, nil, &outB, &errB)
actualStdErr := errB.String()
if err != nil {
t.Fatalf("Case %q: Got an error when none was expected: %v", testcase.name, err)
Expand All @@ -305,6 +309,7 @@ func TestCmdBlocksZeroTerminated(t *testing.T) {
t.Parallel()

for _, testcase := range blocksTestcases {
testcase := testcase
t.Run(testcase.name, func(t *testing.T) {
t.Parallel()

Expand All @@ -319,7 +324,7 @@ func TestCmdBlocksZeroTerminated(t *testing.T) {
var outB strings.Builder
var errB strings.Builder
log := common.CreateLogger(&errB)
err := findBlocksInFile(fs, log, testcase.sourcefile, false, true, false, nil, &outB, &errB)
err := findBlocksInFile(fs, log, testcase.sourcefile, false, true, false, false, nil, &outB, &errB)
actualStdOut := outB.String()
actualStdErr := errB.String()

Expand All @@ -328,7 +333,7 @@ func TestCmdBlocksZeroTerminated(t *testing.T) {
}

if actualStdOut != expected {
t.Errorf("Output does not match expected:\n%s", diff.Diff(actualStdOut, expected))
t.Errorf("Output does not match expected: ('-' actual, '+' expected)\n%s", diff.Diff(actualStdOut, expected))
}

if actualStdErr != "" {
Expand All @@ -341,7 +346,7 @@ func TestCmdBlocksZeroTerminated(t *testing.T) {
func TestCmdBlocksJson(t *testing.T) {
t.Parallel()

for _, testcase := range testcases {
for _, testcase := range blocksTestcases {
testcase := testcase
t.Run(testcase.name, func(t *testing.T) {
t.Parallel()
Expand All @@ -366,7 +371,54 @@ func TestCmdBlocksJson(t *testing.T) {
var outB strings.Builder
var errB strings.Builder
log := common.CreateLogger(&errB)
err = findBlocksInFile(fs, log, testcase.sourcefile, false, false, true, nil, &outB, &errB)
err = findBlocksInFile(fs, log, testcase.sourcefile, false, false, true, false, nil, &outB, &errB)
actualStdOut := outB.String()
actualStdErr := errB.String()

if err != nil {
t.Fatalf("Got an error when none was expected: %v", err)
}

if !equivalentJSON([]byte(actualStdOut), expected) {
t.Errorf("Output does not match expected: ('-' actual, '+' expected)\n%s", diff.Diff(actualStdOut, string(expected)))
}

if actualStdErr != "" {
t.Errorf("Got error output:\n%s", actualStdErr)
}
})
}
}

func TestCmdBlocksFmtVerbsJson(t *testing.T) {
t.Parallel()

for _, testcase := range blocksTestcases {
testcase := testcase
t.Run(testcase.name, func(t *testing.T) {
t.Parallel()

fs := afero.NewReadOnlyFs(afero.NewOsFs())

data := Output{}
for _, block := range testcase.expectedBlocks {
data.BlockCount++
blockData := Block{
StartLine: block.startLine,
EndLine: block.endLine,
Text: fmtverbs.Escape(block.text) + "\n",
}
data.Blocks = append(data.Blocks, blockData)
}
expected, err := json.Marshal(data)
if err != nil {
t.Fatalf("Error generating expected JSON output: %v", err)
}

var outB strings.Builder
var errB strings.Builder
log := common.CreateLogger(&errB)
err = findBlocksInFile(fs, log, testcase.sourcefile, false, false, true, true, nil, &outB, &errB)
actualStdOut := outB.String()
actualStdErr := errB.String()

Expand All @@ -375,7 +427,7 @@ func TestCmdBlocksJson(t *testing.T) {
}

if !equivalentJSON([]byte(actualStdOut), expected) {
t.Errorf("Output does not match expected:\n%s", diff.Diff(actualStdOut, string(expected)))
t.Errorf("Output does not match expected: ('-' actual, '+' expected)\n%s", diff.Diff(actualStdOut, string(expected)))
}

if actualStdErr != "" {
Expand Down
9 changes: 7 additions & 2 deletions cli/cmds.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import (
"github.com/hashicorp/go-multierror"
"github.com/katbyte/terrafmt/lib/blocks"
"github.com/katbyte/terrafmt/lib/common"
verbs "github.com/katbyte/terrafmt/lib/fmtverbs"
"github.com/katbyte/terrafmt/lib/format"
"github.com/katbyte/terrafmt/lib/upgrade012"
"github.com/katbyte/terrafmt/lib/version"
Expand Down Expand Up @@ -202,9 +203,10 @@ func Make() *cobra.Command {
if zeroTerminated && jsonOutput {
return fmt.Errorf("only one of zero-terminated or json can be specified")
}
fmtCompat := viper.GetBool("fmtcompat")

fs := afero.NewOsFs()
return findBlocksInFile(fs, log, filename, verbose, zeroTerminated, jsonOutput, cmd.InOrStdin(), cmd.OutOrStdout(), cmd.ErrOrStderr())
return findBlocksInFile(fs, log, filename, verbose, zeroTerminated, jsonOutput, fmtCompat, cmd.InOrStdin(), cmd.OutOrStdout(), cmd.ErrOrStderr())
},
}
root.AddCommand(blocksCmd)
Expand Down Expand Up @@ -379,7 +381,7 @@ func (w jsonBlockWriter) Close() error {
return encoder.Encode(w.data)
}

func findBlocksInFile(fs afero.Fs, log *logrus.Logger, filename string, verbose, zeroTerminated, jsonOutput bool, stdin io.Reader, stdout, stderr io.Writer) error {
func findBlocksInFile(fs afero.Fs, log *logrus.Logger, filename string, verbose, zeroTerminated, jsonOutput, fmtverbs bool, stdin io.Reader, stdout, stderr io.Writer) error {
var blockWriter blocks.BlockWriter
if zeroTerminated {
blockWriter = zeroTerminatedBlockWriter{
Expand All @@ -400,6 +402,9 @@ func findBlocksInFile(fs afero.Fs, log *logrus.Logger, filename string, verbose,
LineRead: blocks.ReaderIgnore,
BlockWriter: blockWriter,
BlockRead: func(br *blocks.Reader, i int, b string) error {
if fmtverbs {
b = verbs.Escape(b)
}
br.BlockWriter.Write(br.BlockCount, br.LineCount-br.BlockCurrentLine, br.LineCount, b)
return nil
},
Expand Down

0 comments on commit 3912d4c

Please sign in to comment.