merger/main.go

102 lines
1.8 KiB
Go
Raw Permalink Normal View History

2024-05-04 20:11:36 +03:00
package main
import (
"encoding/json"
2024-05-04 20:11:36 +03:00
"flag"
"fmt"
2024-05-04 20:11:36 +03:00
"os"
"strings"
"gopkg.in/yaml.v3"
)
var (
input = stringsArray{}
output = ""
replaceArrays = false
outType = "yaml"
2024-05-04 20:11:36 +03:00
)
func main() {
flag.Var(&input, "i", "input files")
flag.StringVar(&output, "o", "out.yaml", "output file")
flag.BoolVar(&replaceArrays, "replace_arrays", false, "replace arrays with same keys. Merge otherwise.")
flag.StringVar(&outType, "out_type", "yaml", "output type, 'yaml' (default) or 'json'")
2024-05-04 20:11:36 +03:00
flag.Parse()
result := map[string]any{}
for _, inputFile := range input {
b, err := os.ReadFile(inputFile)
if err != nil {
panic(err)
}
m := map[string]any{}
if err := yaml.Unmarshal(b, m); err != nil {
panic(err)
}
merge(result, m, replaceArrays)
}
fp, err := os.Create(output)
if err != nil {
panic(err)
}
defer fp.Close()
var enc Encoder
switch outType {
case "yaml":
enc = yaml.NewEncoder(fp)
case "json":
enc = json.NewEncoder(fp)
default:
panic(fmt.Errorf("unknown output type: %s", outType))
}
2024-05-04 20:11:36 +03:00
if err := enc.Encode(result); err != nil {
panic(err)
}
}
func merge(target map[string]any, in map[string]any, replaceArrays bool) {
for k, v := range in {
old, exist := target[k]
if !exist {
target[k] = v
continue
}
switch old := old.(type) {
case map[string]any:
v, ok := v.(map[string]any)
if ok {
merge(old, v, replaceArrays)
target[k] = old
continue
}
case []any:
v, ok := v.([]any)
if ok && !replaceArrays {
old = append(old, v...)
target[k] = old
continue
}
}
target[k] = v
}
}
type stringsArray []string
func (i *stringsArray) Set(value string) error {
*i = append(*i, value)
return nil
}
func (i *stringsArray) String() string {
return strings.Join(*i, ",")
}
type Encoder interface {
Encode(any) error
}