yamldiff re-implementation in go
This commit is contained in:
parent
03a1a4e132
commit
3a6a913ef2
99
cmd/yamldiff/yamldiff.go
Normal file
99
cmd/yamldiff/yamldiff.go
Normal file
@ -0,0 +1,99 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
yaml "github.com/goccy/go-yaml"
|
||||
"os"
|
||||
"reflect"
|
||||
)
|
||||
|
||||
func read(file string) []byte {
|
||||
data, err := os.ReadFile(file)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return data
|
||||
}
|
||||
|
||||
func parse(data []byte) yaml.MapSlice {
|
||||
var result yaml.MapSlice
|
||||
decoder := yaml.NewDecoder(bytes.NewReader(data),
|
||||
yaml.UseOrderedMap())
|
||||
err := decoder.Decode(&result)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
type TypeId int
|
||||
|
||||
const (
|
||||
Map TypeId = iota
|
||||
Slice
|
||||
Scalar
|
||||
)
|
||||
|
||||
func Type(elem any) TypeId {
|
||||
switch elem.(type) {
|
||||
case yaml.MapSlice:
|
||||
return Map
|
||||
case []any:
|
||||
return Slice
|
||||
default:
|
||||
return Scalar
|
||||
}
|
||||
}
|
||||
|
||||
func subtract(yaml1 yaml.MapSlice, yaml2 yaml.MapSlice) yaml.MapSlice {
|
||||
res := make(yaml.MapSlice, 0)
|
||||
for _, item := range yaml2 {
|
||||
k := item.Key
|
||||
v1 := item.Value
|
||||
v2 := yaml1.ToMap()[k]
|
||||
switch {
|
||||
case reflect.DeepEqual(v1, v2):
|
||||
// delete is implicit by not copying to the output
|
||||
case Type(v1) == Map && Type(v2) == Map:
|
||||
diff := subtract(v2.(yaml.MapSlice), v1.(yaml.MapSlice))
|
||||
if len(diff) > 0 {
|
||||
res = append(res, item)
|
||||
}
|
||||
case Type(v1) == Slice && Type(v2) == Slice:
|
||||
if !reflect.DeepEqual(v1, v2) {
|
||||
res = append(res, item)
|
||||
}
|
||||
default:
|
||||
res = append(res, item)
|
||||
}
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
func main() {
|
||||
if len(os.Args) != 3 {
|
||||
fmt.Fprintf(os.Stderr, `
|
||||
Usage: yamldiff <file1> <file2>")
|
||||
Shows changes and additions made in <file2> w.r.t. <file1>
|
||||
`)
|
||||
}
|
||||
file1 := os.Args[1]
|
||||
file2 := os.Args[2]
|
||||
|
||||
yaml1 := parse(read(file1))
|
||||
yaml2 := parse(read(file2))
|
||||
|
||||
subtract(yaml2, yaml1)
|
||||
|
||||
enc := yaml.NewEncoder(os.Stdout,
|
||||
yaml.UseLiteralStyleIfMultiline(true),
|
||||
yaml.Indent(2), // Set indentation
|
||||
//yaml.UseOrderedMap(), // Preserve map order
|
||||
)
|
||||
err := enc.Encode(yaml2)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in New Issue
Block a user