aboutsummaryrefslogblamecommitdiff
path: root/main.go
blob: 588cda381cf901b5118c09ecb66fd2254538aae6 (plain) (tree)
1
2
3
4
5
6


            
                       
              
             








                                      
                             
                              




                                                               
                                                                                                                
                                                                                               





















                                                            








                                                                     









































                                                                          



                         
package main

import (
	"encoding/json"
	"flag"
	"fmt"
	"os"
	"strings"

	"gopkg.in/yaml.v3"
)

var (
	input         = stringsArray{}
	output        = ""
	replaceArrays = false
	outType       = "yaml"
)

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'")
	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))
	}
	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
}