diff --git a/cmd/yamldiff/yamldiff.go b/cmd/yamltool/diff.go similarity index 50% rename from cmd/yamldiff/yamldiff.go rename to cmd/yamltool/diff.go index 42c12e4..63fa450 100644 --- a/cmd/yamldiff/yamldiff.go +++ b/cmd/yamltool/diff.go @@ -1,54 +1,13 @@ package main import ( - "bytes" "fmt" - yaml "github.com/goccy/go-yaml" + "github.com/goccy/go-yaml" "github.com/spf13/cobra" "os" "reflect" ) -var VERBOSITY = 2 - -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 - } -} - // hack to be able to compare slices and dictionires that cannot be put into a map. func strval(v any) string { return fmt.Sprintf("%v", v) @@ -104,44 +63,41 @@ func subtract(yaml2 yaml.MapSlice, yaml1 yaml.MapSlice) yaml.MapSlice { return res } -func execute(cmd *cobra.Command, args []string) error { +func diff(cmd *cobra.Command, args []string) error { if len(args) != 2 { - return fmt.Errorf("Parameters expected") + return fmt.Errorf("Expected 2 files") } - if VERBOSITY < 1 || VERBOSITY > 3 { + if VERBOSITY < 0 || VERBOSITY > 3 { return fmt.Errorf("Array verbosity out of range") } - file1 := os.Args[1] - file2 := os.Args[2] + file1 := args[0] + file2 := args[1] yaml1 := parse(read(file1)) yaml2 := parse(read(file2)) - yaml2 = 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) - return err -} - -func main() { - - cmd := &cobra.Command{ - Use: "yamldiff ", - Short: "Shows one-way difference between yaml files", - Long: ` -Shows the changes in compared to `, - RunE: func(cmd *cobra.Command, args []string) error { - return execute(cmd, args) - }, + diff1 := subtract(yaml2, yaml1) + diff2 := make(yaml.MapSlice, 0) + if SYMMETRIC_DIFF { + diff2 = subtract(yaml1, yaml2) } - cmd.PersistentFlags().IntVarP(&VERBOSITY, "array-output-level", - "v", 1, "Array output level: , 1: only show changed/added values, 2 (default) show identical as , 3: show all values") + diff := diff1 + if SYMMETRIC_DIFF { + diff = make(yaml.MapSlice, 0) + diff = append(diff, + yaml.MapItem{Key: "forward", Value: diff1}, + yaml.MapItem{Key: "backward", Value: diff2}, + ) + } - cmd.Execute() + if VERBOSITY > 0 { + if err := encode(os.Stdout, diff); err != nil { + return err + } + } + if len(diff1) > 0 || len(diff2) > 0 { + os.Exit(1) + } + return nil } diff --git a/cmd/yamltool/encode.go b/cmd/yamltool/encode.go new file mode 100644 index 0000000..d2484da --- /dev/null +++ b/cmd/yamltool/encode.go @@ -0,0 +1,16 @@ +package main + +import ( + "github.com/goccy/go-yaml" + "io" + "os" +) + +func encode(writer io.Writer, data any) error { + enc := yaml.NewEncoder(os.Stdout, + yaml.UseLiteralStyleIfMultiline(true), + yaml.Indent(2), // Set indentation + //yaml.UseOrderedMap(), // Preserve map order + ) + return enc.Encode(data) +} diff --git a/cmd/yamltool/merge.go b/cmd/yamltool/merge.go new file mode 100644 index 0000000..49c415c --- /dev/null +++ b/cmd/yamltool/merge.go @@ -0,0 +1,30 @@ +package main + +import ( + "github.com/goccy/go-yaml" + "github.com/spf13/cobra" + "os" +) + +func mergeMap(yaml1 yaml.MapSlice, yaml2 yaml.MapSlice) yaml.MapSlice { + res := yaml1 + + //for key, item := range yaml2 { + // switch { + // case res.ToMap()[key] != nil && type + // + // } + //} + + return res +} + +func merge(cmd *cobra.Command, args []string) error { + res := make(yaml.MapSlice, 0) + for _, arg := range args { + config := parse(read(arg)) + res = mergeMap(res, config) + } + encode(os.Stdout, res) + return nil +} diff --git a/cmd/yamltool/parse.go b/cmd/yamltool/parse.go new file mode 100644 index 0000000..08d8309 --- /dev/null +++ b/cmd/yamltool/parse.go @@ -0,0 +1,26 @@ +package main + +import ( + "bytes" + "github.com/goccy/go-yaml" + "os" +) + +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 +} diff --git a/cmd/yamltool/yamltool.go b/cmd/yamltool/yamltool.go new file mode 100644 index 0000000..0aeb324 --- /dev/null +++ b/cmd/yamltool/yamltool.go @@ -0,0 +1,70 @@ +package main + +import ( + yaml "github.com/goccy/go-yaml" + "github.com/spf13/cobra" +) + +var VERBOSITY = 3 +var SYMMETRIC_DIFF = false + +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 main() { + + cmd := &cobra.Command{ + Use: "yamltool", + Short: "Shows one-way difference between yaml files", + Long: ` +Shows the changes in compared to `, + } + + diff := &cobra.Command{ + Use: "diff [file1] [file2]", + Short: "Shows one-way difference between yaml files", + Long: ` +Shows the additions and modifications in compared to `, + RunE: func(cmd *cobra.Command, args []string) error { + return diff(cmd, args) + }, + } + cmd.AddCommand(diff) + + merge := &cobra.Command{ + Use: "merge [file1] ... [fileN]", + Short: "Merge yaml files.", + Long: `Changes will be merged into the first file, so later files override earlier ones`, + RunE: func(cmd *cobra.Command, args []string) error { + return merge(cmd, args) + }, + } + cmd.AddCommand(merge) + + cmd.PersistentFlags().IntVarP(&VERBOSITY, "array-output-level", + "v", 3, `Array output level: , + 0: no output, only exit status, + 1: only show changed/added values, + 2: show identical as , + 3: show all values`) + diff.Flags().BoolVarP(&SYMMETRIC_DIFF, "symmetric-diff", + "s", false, `Symmetric difference, compare in both directions`) + + cmd.Execute() +} diff --git a/go.mod b/go.mod index 53b3ae7..fd159ba 100644 --- a/go.mod +++ b/go.mod @@ -1,6 +1,6 @@ module git.wamblee.org/public/gotools -go 1.23.3 +go 1.23.4 require ( github.com/goccy/go-yaml v1.15.13