Skip to content

Instantly share code, notes, and snippets.

@shahidhk
Created October 14, 2019 04:53
Show Gist options
  • Save shahidhk/f39bf76e5fdf1e7a364638de1d12114b to your computer and use it in GitHub Desktop.
Save shahidhk/f39bf76e5fdf1e7a364638de1d12114b to your computer and use it in GitHub Desktop.
Utility function to print YAML diff
// usage:
// DiffYaml(d2, d1, os.Stdout)
package diff
import (
"fmt"
"io"
"strings"
"github.com/aryann/difflib"
"github.com/ghodss/yaml"
"github.com/mgutz/ansi"
)
func yamlToMap(y []byte) (map[string]string, error) {
var obj map[string]interface{}
m := make(map[string]string)
err := yaml.Unmarshal(y, &obj)
if err != nil {
return nil, err
}
for key, value := range obj {
val, err := yaml.Marshal(value)
if err != nil {
return m, err
}
m[key] = string(val)
}
return m, nil
}
func DiffYaml(oldYaml, newYaml []byte, to io.Writer) error {
oldIndex, err := yamlToMap(oldYaml)
if err != nil {
return err
}
newIndex, err := yamlToMap(newYaml)
if err != nil {
return err
}
for key, oldContent := range oldIndex {
if newContent, ok := newIndex[key]; ok {
if oldContent != newContent {
// modified
fmt.Fprintf(to, ansi.Color("%s has changed:", "yellow")+"\n", key)
PrintDiff(oldContent, newContent, to)
}
} else {
// removed
fmt.Fprintf(to, ansi.Color("%s has been removed:", "yellow")+"\n", key)
PrintDiff(oldContent, "", to)
}
}
for key, newContent := range newIndex {
if _, ok := oldIndex[key]; !ok {
// added
fmt.Fprintf(to, ansi.Color("%s has been added:", "yellow")+"\n", key)
PrintDiff("", newContent, to)
}
}
return nil
}
func PrintDiff(before, after string, to io.Writer) {
diffs := difflib.Diff(strings.Split(before, "\n"), strings.Split(after, "\n"))
for _, diff := range diffs {
text := diff.Payload
switch diff.Delta {
case difflib.RightOnly:
fmt.Fprintf(to, "%s\n", ansi.Color("+ "+text, "green"))
case difflib.LeftOnly:
fmt.Fprintf(to, "%s\n", ansi.Color("- "+text, "red"))
case difflib.Common:
fmt.Fprintf(to, "%s\n", " "+text)
}
}
}
func DiffString(before, after string, to io.Writer) {
diffs := difflib.Diff(strings.Split(before, "\n"), strings.Split(after, "\n"))
for _, diff := range diffs {
text := diff.Payload
switch diff.Delta {
case difflib.RightOnly:
fmt.Fprintf(to, "%s\n", ansi.Color("+ "+text, "green"))
case difflib.LeftOnly:
fmt.Fprintf(to, "%s\n", ansi.Color("- "+text, "red"))
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment