Skip to content

Commit cb39487

Browse files
committed
Uncompleted 7th step
1 parent 793a148 commit cb39487

File tree

12 files changed

+235
-7
lines changed

12 files changed

+235
-7
lines changed

gendiff.cast

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
[5.303537, "o", "\r\u001b[0m\u001b[27m\u001b[24m\u001b[J\u001b[0m\u001b[49m\u001b[39m\u001b[0m\u001b[49m\u001b[38;5;31m\u001b[1m\u001b[38;5;31m\u001b[38;5;39m~\u001b[0m\u001b[38;5;39m\u001b[49m\u001b[38;5;31m/\u001b[1m\u001b[38;5;31m\u001b[38;5;39mgo-project-244\u001b[0m\u001b[38;5;39m\u001b[49m\u001b[38;5;31m\u001b[0m\u001b[38;5;31m\u001b[49m\u001b[38;5;31m\u001b[0m\u001b[38;5;31m\u001b[49m \u001b[0m\u001b[38;5;31m\u001b[49m\u001b[38;5;178m\u001b[39mon \u001b[0m\u001b[49m\u001b[38;5;178m\u001b[38;5;76mmain \u001b[38;5;178m!5 \u001b[38;5;39m?1\u001b[0m\u001b[38;5;39m\u001b[49m\u001b[38;5;178m\u001b[0m\u001b[38;5;178m\u001b[49m \u001b[0m\u001b[38;5;178m\u001b[49m\u001b[38;5;76m❯\u001b[0m\u001b[38;5;76m\u001b[49m\u001b[38;5;76m\u001b[0m\u001b[38;5;76m\u001b[49m\u001b[30m\u001b[0m\u001b[30m\u001b[49m\u001b[39m \u001b[0m\u001b[49m\u001b[39m\u001b[K\u001b[101C\u001b[0m\u001b[49m\u001b[38;5;66m\u001b[39mat \u001b[0m\u001b[49m\u001b[38;5;66m21:00:17\u001b[0m\u001b[38;5;66m\u001b[49m\u001b[38;5;66m\u001b[0m\u001b[38;5;66m\u001b[49m\u001b[38;5;66m\u001b[0m\u001b[38;5;66m\u001b[49m\u001b[39m\u001b[112D\u001b[?1h\u001b="]
2020
[5.304445, "o", "\u001b[?2004h"]
2121
[6.862786, "o", "b"]
22-
[6.864874, "o", "\bb\u001b[90min/gendiff testdata/file1.json testdata/file2.json\u001b[39m\u001b[50D"]
22+
[6.864874, "o", "\bb\u001b[90min/gendiff testres1/file1.json testdata/file2.json\u001b[39m\u001b[50D"]
2323
[7.07186, "o", "\bb\u001b[39mi"]
2424
[7.880969, "o", "\u001b[39mn\u001b[39m/\u001b[39mg\u001b[39me\u001b[39mn\u001b[39md\u001b[39mi\u001b[39mf\u001b[39mf\u001b[39m \u001b[39mt\u001b[39me\u001b[39ms\u001b[39mt\u001b[39md\u001b[39ma\u001b[39mt\u001b[39ma\u001b[39m/\u001b[39mf\u001b[39mi\u001b[39ml\u001b[39me\u001b[39m1\u001b[39m.\u001b[39mj\u001b[39ms\u001b[39mo\u001b[39mn\u001b[39m \u001b[39mt\u001b[39me\u001b[39ms\u001b[39mt\u001b[39md\u001b[39ma\u001b[39mt\u001b[39ma\u001b[39m/\u001b[39mf\u001b[39mi\u001b[39ml\u001b[39me\u001b[39m2\u001b[39m.\u001b[39mj\u001b[39ms\u001b[39mo\u001b[39mn"]
2525
[10.474883, "o", "\u001b[?1l\u001b>"]

go.mod

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,10 @@ go 1.24
55
require (
66
github.com/stretchr/testify v1.11.1
77
github.com/urfave/cli/v3 v3.4.1
8+
gopkg.in/yaml.v3 v3.0.1
89
)
910

1011
require (
1112
github.com/davecgh/go-spew v1.1.1 // indirect
1213
github.com/pmezard/go-difflib v1.0.0 // indirect
13-
gopkg.in/yaml.v3 v3.0.1 // indirect
1414
)

src/compare.go

Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
package src
2+
3+
import (
4+
"fmt"
5+
"sort"
6+
)
7+
8+
type Diff struct {
9+
Difference string
10+
Message string
11+
}
12+
13+
func Compare(obj1, obj2 map[string]interface{}, basePath string) []Diff {
14+
var diffs []Diff
15+
16+
// Создаём множество ключей из обеих map
17+
uniqueKeys := make(map[string]struct{}) // Убираю дубликаты ключей
18+
for key := range obj1 {
19+
uniqueKeys[key] = struct{}{}
20+
}
21+
for key := range obj2 {
22+
uniqueKeys[key] = struct{}{}
23+
}
24+
commonKeys := make([]string, 0, len(uniqueKeys)) //Сразу аллоцирую память под известное количество элементов
25+
for key := range uniqueKeys {
26+
commonKeys = append(commonKeys, key)
27+
}
28+
// Сортируем ключи в алфавитном порядке
29+
sort.Slice(commonKeys, func(i, j int) bool {
30+
return commonKeys[i] < commonKeys[j]
31+
})
32+
repeatedKeys := make(map[string]bool) //для обработки повторяющихся ключей
33+
for _, key := range commonKeys {
34+
if repeatedKeys[key] {
35+
continue
36+
}
37+
38+
value1, ok := obj1[key]
39+
value2, yes := obj2[key]
40+
currentPath := buildPath(basePath, key)
41+
42+
if isObject(value2) && isObject(value1) {
43+
o1 := value1.(map[string]interface{})
44+
o2 := value2.(map[string]interface{})
45+
childDiff := Compare(o1, o2, currentPath) // рекурсивный шаг
46+
diffs = append(diffs, childDiff...)
47+
repeatedKeys[key] = true
48+
continue
49+
}
50+
switch {
51+
case !ok && yes:
52+
strData2 := fmt.Sprintf(" + %v: %v", key, value2)
53+
diffs = append(diffs, Diff{Difference: strData2, Message: "# Добавлена"})
54+
case ok && !yes:
55+
strData1 := fmt.Sprintf(" - %v: %v", key, value1)
56+
diffs = append(diffs, Diff{Difference: strData1, Message: "# Удалена"})
57+
58+
default:
59+
isSimple1 := simpleType(value1)
60+
isSimple2 := simpleType(value2)
61+
// Оба простых типа и значения не равны
62+
if isSimple1 && isSimple2 && value1 != value2 {
63+
strData1 := fmt.Sprintf(" - %v: %v", key, value1)
64+
diffs = append(diffs, Diff{Difference: strData1, Message: "# Старое значение"})
65+
strData2 := fmt.Sprintf(" + %v: %v", key, value2)
66+
diffs = append(diffs, Diff{Difference: strData2, Message: "# Новое значение"})
67+
// Оба простых типа и значения равны
68+
} else if isSimple1 && isSimple2 && value1 == value2 {
69+
strData1 := fmt.Sprintf(" %v: %v", key, value1)
70+
diffs = append(diffs, Diff{Difference: strData1, Message: ""})
71+
// Если оба типа и не простые типы и не объекты
72+
} else {
73+
strData1 := fmt.Sprintf(" - %v: %v", key, value1)
74+
diffs = append(diffs, Diff{Difference: strData1, Message: "# Старое значение"})
75+
strData2 := fmt.Sprintf(" + %v: %v", key, value2)
76+
diffs = append(diffs, Diff{Difference: strData2, Message: "# Новое значение"})
77+
}
78+
}
79+
}
80+
return diffs
81+
}
82+
83+
func buildPath(basePath, key string) string {
84+
if basePath == "" {
85+
return key
86+
}
87+
return basePath + "." + key
88+
}
89+
90+
func simpleType(value interface{}) bool {
91+
switch value.(type) {
92+
case string, int, int8, int16, int32, int64, float32, float64, bool:
93+
return true
94+
default:
95+
return false
96+
}
97+
}
98+
99+
func isArray(value interface{}) bool {
100+
_, ok := value.([]interface{})
101+
if ok {
102+
return true
103+
} else {
104+
return false
105+
}
106+
}
107+
108+
func isObject(value interface{}) bool {
109+
_, ok := value.(map[string]interface{})
110+
if ok {
111+
return true
112+
} else {
113+
return false
114+
}
115+
}

src/compare_test.go

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
package src
2+
3+
import (
4+
"code/src/parsers"
5+
"fmt"
6+
"path/filepath"
7+
"testing"
8+
)
9+
10+
func TestCompare(t *testing.T) {
11+
path1 := filepath.Join("../testdata/fixture/complicated/file1-1.yaml") //фикстура №1
12+
path2 := filepath.Join("../testdata/fixture/complicated/file2-1.yaml") //фикстура №2
13+
//path1 := filepath.Join("../testdata/fixture/file1.yml")
14+
//path2 := filepath.Join("../testdata/fixture/file2.yml")
15+
obj1, obj2, _ := parsers.ParseDataFromFiles(path1, path2)
16+
17+
res := Compare(obj1, obj2, "")
18+
fmt.Println(res)
19+
}

src/formatter/stylish.go

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
package formatter
2+
3+
import "code/src"
4+
5+
type Stylish struct{}
6+
7+
func (st *Stylish) Format(diff *[]src.Diff) string {
8+
9+
return ""
10+
}

src/gendiff.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
package code
1+
package src
22

33
import (
44
"code/src/parsers"
@@ -15,6 +15,7 @@ func GenDiff(path1, path2, format string) (string, error) {
1515
return "", fmt.Errorf("parseDataFromFiles: %w", err)
1616
}
1717
str := genDiff(data1, data2)
18+
//str := compareTreeStructures(data1, data2)
1819
return str, nil
1920
}
2021

src/gendiff_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
package code
1+
package src
22

33
import (
44
"os"

src/parsers/parsers.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,10 @@ package parsers
33
import (
44
"encoding/json"
55
"errors"
6-
"gopkg.in/yaml.v3"
76
"os"
87
"path/filepath"
8+
9+
"gopkg.in/yaml.v3"
910
)
1011

1112
func ParseDataFromFiles(path1, path2 string) (res1, res2 map[string]interface{}, err error) {

src/parsers/parsers_test.go

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package parsers
22

33
import (
44
"errors"
5+
"fmt"
56
"path/filepath"
67
"testing"
78

@@ -24,8 +25,8 @@ func TestParseDataFromFiles(t *testing.T) {
2425
},
2526
{
2627
name: "BothFilesAreYaml",
27-
filename1: filepath.Join("../../testdata/fixture/file1.yml"),
28-
filename2: filepath.Join("../../testdata/fixture/file2.yml"),
28+
filename1: filepath.Join("../../testdata/fixture/file1-1.yaml"),
29+
filename2: filepath.Join("../../testdata/fixture/file2-1.yaml"),
2930
expected: [3]interface{}{map[string]interface{}{"follow": false, "host": "hexlet.io", "proxy": "123.234.53.22", "timeout": 50},
3031
map[string]interface{}{"host": "hexlet.io", "timeout": 20, "verbose": true}, nil},
3132
},
@@ -45,6 +46,7 @@ func TestParseDataFromFiles(t *testing.T) {
4546
for _, tc := range testCases {
4647
t.Run(tc.name, func(t *testing.T) {
4748
got1, got2, err := ParseDataFromFiles(tc.filename1, tc.filename2)
49+
fmt.Println(got1, got2)
4850
if got1 != nil && got2 != nil {
4951
assert.Equal(t, got1, tc.expected[0])
5052
assert.Equal(t, got2, tc.expected[1])
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
common: {
2+
+ follow: false # Добавлена
3+
setting1: Value 1
4+
- setting2: 200 # Удалена
5+
- setting3: true # Старое значение
6+
+ setting3: null # Новое значение
7+
+ setting4: blah blah
8+
+ setting5: {
9+
key5: value5
10+
}
11+
setting6: {
12+
doge: {
13+
- wow: # значения нет, но пробел после : есть
14+
+ wow: so much
15+
}
16+
key: value
17+
+ ops: vops
18+
}
19+
}
20+
group1: {
21+
- baz: bas
22+
+ baz: bars
23+
foo: bar
24+
- nest: {
25+
key: value
26+
}
27+
+ nest: str
28+
}
29+
- group2: {
30+
abc: 12345
31+
deep: {
32+
id: 45
33+
}
34+
}
35+
+ group3: {
36+
deep: {
37+
id: {
38+
number: 45
39+
}
40+
}
41+
fee: 100500
42+
}

0 commit comments

Comments
 (0)