commit fd22b325e5c1fd29f7d8e91a6b78be2cc482f0ef Author: Alexander NeonXP Kiryukhin Date: Sat May 4 20:11:36 2024 +0300 Начальный коммит diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..9f211b5 --- /dev/null +++ b/go.mod @@ -0,0 +1,5 @@ +module go.neonxp.ru/merger + +go 1.22.2 + +require gopkg.in/yaml.v3 v3.0.1 diff --git a/go.sum b/go.sum new file mode 100644 index 0000000..4bc0337 --- /dev/null +++ b/go.sum @@ -0,0 +1,3 @@ +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/main.go b/main.go new file mode 100644 index 0000000..b41afa4 --- /dev/null +++ b/main.go @@ -0,0 +1,88 @@ +package main + +import ( + "flag" + "os" + "strings" + + "gopkg.in/yaml.v3" +) + +var ( + input = stringsArray{} + output = "" + indent = 2 + replaceArrays = false +) + +func main() { + flag.Var(&input, "i", "input files") + flag.StringVar(&output, "o", "out.yaml", "output file") + flag.IntVar(&indent, "indent", 2, "changes the used indentation used when encoding") + flag.BoolVar(&replaceArrays, "replace_arrays", false, "replace arrays with same keys. Merge otherwise.") + 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() + + enc := yaml.NewEncoder(fp) + enc.SetIndent(indent) + 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, ",") +} diff --git a/readme.md b/readme.md new file mode 100644 index 0000000..09122e9 --- /dev/null +++ b/readme.md @@ -0,0 +1,78 @@ +# merger + +Простейший мерджер yaml'ов + +## Установка + +``` +go install go.neonxp.ru/merger@latest +``` + +## Использование + +``` +merger -i file1.yaml -i file2.yaml -i fileN.yaml -o output.yaml +``` + +Есть ещё ключи: + +- `-indent 2` устанавливает отступ в результирующем yaml'е +- `-replace_arrays false` - если true то массивы по одинаковым ключам будут перезатираться. По умолчанию - соединяться. + +## Пример + +file1.yaml +```yaml +a1: + a11: + - one + - two + a12: "one" +a2: + a21: + - one + - two + a22: "one" + a23: + a231: 231 + a232: 232 + a233: 233 +``` + +file2.yaml +```yaml +a1: + a11: + - three + - four + a12: "two" +a2: + a23: + a231: "!!!" + a232: "???" + a233: + sub: tree + to: merge +``` + +output.yaml +```yaml +a1: + a11: + - one + - two + - three + - four + a12: two +a2: + a21: + - one + - two + a22: one + a23: + a231: '!!!' + a232: ??? + a233: + sub: tree + to: merge +``` \ No newline at end of file