aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--go.mod5
-rw-r--r--go.sum3
-rw-r--r--main.go88
-rw-r--r--readme.md78
4 files changed, 174 insertions, 0 deletions
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