Skip to content

Commit

Permalink
add --with-comments to preserve comments when returning an attribute
Browse files Browse the repository at this point in the history
  • Loading branch information
wondersd committed Aug 28, 2024
1 parent 26c04bc commit a5e5f44
Show file tree
Hide file tree
Showing 6 changed files with 173 additions and 99 deletions.
7 changes: 6 additions & 1 deletion cmd/attribute.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,10 @@ Arguments:
RunE: runAttributeGetCmd,
}

flags := cmd.Flags()
flags.Bool("with-comments", false, "return comments along with attribute value")
_ = viper.BindPFlag("attribute.get.withComments", flags.Lookup("with-comments"))

return cmd
}

Expand All @@ -55,11 +59,12 @@ func runAttributeGetCmd(cmd *cobra.Command, args []string) error {
address := args[0]
file := viper.GetString("file")
update := viper.GetBool("update")
withComments := viper.GetBool("attribute.get.withComments")
if update {
return errors.New("The update flag is not allowed")
}

sink := editor.NewAttributeGetSink(address)
sink := editor.NewAttributeGetSink(address, withComments)
c := newDefaultClient(cmd)
return c.Derive(file, sink)
}
Expand Down
41 changes: 41 additions & 0 deletions cmd/attribute_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,13 @@ func TestAttributeGet(t *testing.T) {
key = "services/hoge/dev/terraform.tfstate"
}
}
locals {
map = {
# comment
attribute = "bar"
}
attribute = "foo" # comment
}
`

cases := []struct {
Expand Down Expand Up @@ -44,6 +51,40 @@ func TestAttributeGet(t *testing.T) {
ok: false,
want: "",
},
{
name: "with comments",
args: []string{"--with-comments", "locals.map"},
ok: true,
want: `{
# comment
attribute = "bar"
}
`,
},
{
name: "without comments",
args: []string{"locals.map"},
ok: true,
want: `{
attribute = "bar"
}
`,
},
// does not pass at current
// {
// name: "single with comments",
// args: []string{"--with-comments", "locals.attribute"},
// ok: true,
// want: `"foo" #comment`,
// },
{
name: "single without comments",
args: []string{"locals.attribute"},
ok: true,
want: `"foo"
`,
},
}

for _, tc := range cases {
Expand Down
2 changes: 1 addition & 1 deletion editor/client_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@ a1 = v1
a0 = v3
a2 = v2
`
sink := NewAttributeGetSink("a0")
sink := NewAttributeGetSink("a0", false)

cases := []struct {
name string
Expand Down
85 changes: 47 additions & 38 deletions editor/operator_derive_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,31 +7,34 @@ import (

func TestOperatorDeriveApply(t *testing.T) {
cases := []struct {
name string
src string
address string
ok bool
want string
name string
src string
address string
withComments bool
ok bool
want string
}{
{
name: "match",
src: `
a0 = v0
a1 = v1
`,
address: "a0",
ok: true,
want: "v0\n",
address: "a0",
withComments: false,
ok: true,
want: "v0\n",
},
{
name: "not found",
src: `
a0 = v0
a1 = v1
`,
address: "a2",
ok: true,
want: "",
address: "a2",
withComments: false,
ok: true,
want: "",
},
{
name: "syntax error",
Expand All @@ -46,7 +49,7 @@ b1 {

for _, tc := range cases {
t.Run(tc.name, func(t *testing.T) {
o := NewDeriveOperator(NewAttributeGetSink(tc.address))
o := NewDeriveOperator(NewAttributeGetSink(tc.address, tc.withComments))
output, err := o.Apply([]byte(tc.src), "test")
if tc.ok && err != nil {
t.Fatalf("unexpected err = %s", err)
Expand All @@ -66,39 +69,42 @@ b1 {

func TestDeriveStream(t *testing.T) {
cases := []struct {
name string
src string
address string
ok bool
want string
name string
src string
address string
withComments bool
ok bool
want string
}{
{
name: "match",
src: `
a0 = v0
a1 = v1
`,
address: "a0",
ok: true,
want: "v0\n",
address: "a0",
withComments: false,
ok: true,
want: "v0\n",
},
{
name: "not found",
src: `
a0 = v0
a1 = v1
`,
address: "a2",
ok: true,
want: "",
address: "a2",
withComments: false,
ok: true,
want: "",
},
}

for _, tc := range cases {
t.Run(tc.name, func(t *testing.T) {
inStream := bytes.NewBufferString(tc.src)
outStream := new(bytes.Buffer)
sink := NewAttributeGetSink(tc.address)
sink := NewAttributeGetSink(tc.address, tc.withComments)
err := DeriveStream(inStream, outStream, "test", sink)
if tc.ok && err != nil {
t.Fatalf("unexpected err = %s", err)
Expand All @@ -118,40 +124,43 @@ a1 = v1

func TestDeriveFile(t *testing.T) {
cases := []struct {
name string
src string
address string
value string
ok bool
want string
name string
src string
address string
withComments bool
value string
ok bool
want string
}{
{
name: "match",
src: `
a0 = v0
a1 = v1
`,
address: "a0",
ok: true,
want: "v0\n",
address: "a0",
withComments: false,
ok: true,
want: "v0\n",
},
{
name: "not found",
src: `
a0 = v0
a1 = v1
`,
address: "a2",
ok: true,
want: "",
address: "a2",
withComments: false,
ok: true,
want: "",
},
}

for _, tc := range cases {
t.Run(tc.name, func(t *testing.T) {
path := setupTestFile(t, tc.src)
outStream := new(bytes.Buffer)
sink := NewAttributeGetSink(tc.address)
sink := NewAttributeGetSink(tc.address, tc.withComments)
err := DeriveFile(path, outStream, sink)
if tc.ok && err != nil {
t.Fatalf("unexpected err = %s", err)
Expand All @@ -175,7 +184,7 @@ a1 = v1
}

func TestDeriveFileNotFound(t *testing.T) {
sink := NewAttributeGetSink("foo")
sink := NewAttributeGetSink("foo", false)
outStream := new(bytes.Buffer)
err := DeriveFile("not_found", outStream, sink)
if err == nil {
Expand Down
14 changes: 8 additions & 6 deletions editor/sink_attribute_get.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,15 +10,17 @@ import (

// AttributeGetSink is a sink implementation for getting a value of attribute.
type AttributeGetSink struct {
address string
address string
withComments bool
}

var _ Sink = (*AttributeGetSink)(nil)

// NewAttributeGetSink creates a new instance of AttributeGetSink.
func NewAttributeGetSink(address string) Sink {
func NewAttributeGetSink(address string, withComments bool) Sink {
return &AttributeGetSink{
address: address,
address: address,
withComments: withComments,
}
}

Expand All @@ -35,7 +37,7 @@ func (s *AttributeGetSink) Sink(inFile *hclwrite.File) ([]byte, error) {
}

// treat expr as a string without interpreting its meaning.
out, err := GetAttributeValueAsString(attr)
out, err := GetAttributeValueAsString(attr, s.withComments)
if err != nil {
return []byte{}, err
}
Expand Down Expand Up @@ -183,15 +185,15 @@ func longestMatchingLabels(labels []string, prefix []string) []string {
// GetAttributeValueAsString returns a value of Attribute as string.
// There is no way to get value as string directly,
// so we parses tokens of Attribute and build string representation.
func GetAttributeValueAsString(attr *hclwrite.Attribute) (string, error) {
func GetAttributeValueAsString(attr *hclwrite.Attribute, withComments bool) (string, error) {
// find TokenEqual
expr := attr.Expr()
exprTokens := expr.BuildTokens(nil)

// append tokens until find TokenComment
var valueTokens hclwrite.Tokens
for _, t := range exprTokens {
if t.Type == hclsyntax.TokenComment {
if t.Type == hclsyntax.TokenComment && !withComments {
t.Bytes = []byte("\n")
t.SpacesBefore = 0
}
Expand Down
Loading

0 comments on commit a5e5f44

Please sign in to comment.