Skip to content

Commit

Permalink
Avoid rewriting the file if nothing changed
Browse files Browse the repository at this point in the history
This avoids changing the indentation or number of blank lines etc unnecessarily
if nothing has changed.
  • Loading branch information
stefanhaller committed Jun 24, 2023
1 parent bd54b67 commit dcbe7f7
Show file tree
Hide file tree
Showing 2 changed files with 32 additions and 13 deletions.
29 changes: 16 additions & 13 deletions pkg/utils/yaml_utils/yaml_utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ func UpdateYamlValue(yamlBytes []byte, path []string, value string) ([]byte, err
return yamlBytes, errors.New("yaml document is not a dictionary")
}

if err := updateYamlNode(body, path, value); err != nil {
if didChange, err := updateYamlNode(body, path, value); err != nil || !didChange {
return yamlBytes, err
}

Expand All @@ -43,17 +43,20 @@ func UpdateYamlValue(yamlBytes []byte, path []string, value string) ([]byte, err
}

// Recursive function to update the YAML node.
func updateYamlNode(node *yaml.Node, path []string, value string) error {
func updateYamlNode(node *yaml.Node, path []string, value string) (bool, error) {
if len(path) == 0 {
if node.Kind != yaml.ScalarNode {
return errors.New("yaml node is not a scalar")
return false, errors.New("yaml node is not a scalar")
}
node.Value = value
return nil
if node.Value != value {
node.Value = value
return true, nil
}
return false, nil
}

if node.Kind != yaml.MappingNode {
return errors.New("yaml node in path is not a dictionary")
return false, errors.New("yaml node in path is not a dictionary")
}

key := path[0]
Expand All @@ -72,7 +75,7 @@ func updateYamlNode(node *yaml.Node, path []string, value string) error {
Kind: yaml.ScalarNode,
Value: value,
})
return nil
return true, nil
}

// otherwise, create the missing intermediate node and continue
Expand Down Expand Up @@ -113,7 +116,7 @@ func RenameYamlKey(yamlBytes []byte, path []string, newKey string) ([]byte, erro

body := node.Content[0]

if err := renameYamlKey(body, path, newKey); err != nil {
if didRename, err := renameYamlKey(body, path, newKey); err != nil || !didRename {
return yamlBytes, err
}

Expand All @@ -127,25 +130,25 @@ func RenameYamlKey(yamlBytes []byte, path []string, newKey string) ([]byte, erro
}

// Recursive function to rename the YAML key.
func renameYamlKey(node *yaml.Node, path []string, newKey string) error {
func renameYamlKey(node *yaml.Node, path []string, newKey string) (bool, error) {
if node.Kind != yaml.MappingNode {
return errors.New("yaml node in path is not a dictionary")
return false, errors.New("yaml node in path is not a dictionary")
}

keyNode, valueNode := lookupKey(node, path[0])
if keyNode == nil {
return nil
return false, nil
}

// end of path reached: rename key
if len(path) == 1 {
// Check that new key doesn't exist yet
if newKeyNode, _ := lookupKey(node, newKey); newKeyNode != nil {
return fmt.Errorf("new key `%s' already exists", newKey)
return false, fmt.Errorf("new key `%s' already exists", newKey)
}

keyNode.Value = newKey
return nil
return true, nil
}

return renameYamlKey(valueNode, path[1:], newKey)
Expand Down
16 changes: 16 additions & 0 deletions pkg/utils/yaml_utils/yaml_utils_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,14 @@ func TestUpdateYamlValue(t *testing.T) {
expectedOut: "foo:\n bar:\n baz: qux\n",
expectedErr: "",
},
{
name: "don't rewrite file if value didn't change",
in: "foo:\n bar: baz\n",
path: []string{"foo", "bar"},
value: "baz",
expectedOut: "foo:\n bar: baz\n",
expectedErr: "",
},

// Error cases
{
Expand Down Expand Up @@ -140,6 +148,14 @@ func TestRenameYamlKey(t *testing.T) {
expectedOut: "qux:\n bar: 5\n",
expectedErr: "",
},
{
name: "don't rewrite file if value didn't change",
in: "foo:\n bar: 5\n",
path: []string{"nonExistingKey"},
newKey: "qux",
expectedOut: "foo:\n bar: 5\n",
expectedErr: "",
},

// Error cases
{
Expand Down

0 comments on commit dcbe7f7

Please sign in to comment.