forked from grafana/loki
/
inspector.go
129 lines (103 loc) · 2.57 KB
/
inspector.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
package stages
import (
"fmt"
"io"
"strings"
"github.com/fatih/color"
"github.com/google/go-cmp/cmp"
)
type inspector struct {
writer io.Writer
formatter *formatter
}
func newInspector(writer io.Writer, disableFormatting bool) *inspector {
f := &formatter{
red: color.New(color.FgRed),
yellow: color.New(color.FgYellow),
green: color.New(color.FgGreen),
bold: color.New(color.Bold),
}
if disableFormatting {
f.disable()
}
return &inspector{
writer: writer,
formatter: f,
}
}
type formatter struct {
red *color.Color
yellow *color.Color
green *color.Color
bold *color.Color
}
func (f *formatter) disable() {
f.red.DisableColor()
f.yellow.DisableColor()
f.green.DisableColor()
f.bold.DisableColor()
}
func (i inspector) inspect(stageName string, before *Entry, after Entry) {
if before == nil {
fmt.Fprintln(i.writer, i.formatter.red.Sprintf("could not copy entry in '%s' stage; inspect aborted", stageName))
return
}
r := diffReporter{
formatter: i.formatter,
}
cmp.Equal(*before, after, cmp.Reporter(&r))
diff := r.String()
if strings.TrimSpace(diff) == "" {
diff = i.formatter.red.Sprintf("none")
}
fmt.Fprintf(i.writer, "[inspect: %s stage]: %s\n", i.formatter.bold.Sprintf("%s", stageName), diff)
}
// diffReporter is a simple custom reporter that only records differences
// detected during comparison.
type diffReporter struct {
path cmp.Path
formatter *formatter
diffs []string
}
func (r *diffReporter) PushStep(ps cmp.PathStep) {
r.path = append(r.path, ps)
}
func (r *diffReporter) Report(rs cmp.Result) {
if rs.Equal() {
return
}
vx, vy := r.path.Last().Values()
// TODO(dannyk): try using go-cmp to filter this condition out with Equal(), but for now this just makes it work
if fmt.Sprintf("%v", vx) == fmt.Sprintf("%v", vy) {
return
}
change := vx.IsValid()
addition := vy.IsValid()
removal := change && !addition
mod := addition && change
var titleColor *color.Color
switch {
case mod:
titleColor = r.formatter.yellow
case removal:
titleColor = r.formatter.red
default:
titleColor = r.formatter.green
}
r.diffs = append(r.diffs, titleColor.Sprintf("%#v:", r.path))
if removal {
r.diffs = append(r.diffs, r.formatter.red.Sprintf("\t-: %v", vx))
}
if mod {
r.diffs = append(r.diffs, r.formatter.yellow.Sprintf("\t-: %v", vx))
}
if addition {
r.diffs = append(r.diffs, r.formatter.green.Sprintf("\t+: %v", vy))
}
}
func (r *diffReporter) PopStep() {
r.path = r.path[:len(r.path)-1]
}
func (r *diffReporter) String() string {
return fmt.Sprintf("\n%s", strings.Join(r.diffs, "\n"))
}