Skip to content

Commit d915d49

Browse files
committed
Allow to omit large common parts in diff output
By default disabled, can be enabled and configured with `--context NUM`.
1 parent 993b7db commit d915d49

File tree

2 files changed

+73
-15
lines changed

2 files changed

+73
-15
lines changed

cmd/upgrade.go

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ type diffCmd struct {
2020
reuseValues bool
2121
resetValues bool
2222
suppressedKinds []string
23+
outputContext int
2324
}
2425

2526
const globalUsage = `Show a diff explaining what a helm upgrade would change.
@@ -69,6 +70,7 @@ func newChartCommand() *cobra.Command {
6970
f.BoolVar(&diff.reuseValues, "reuse-values", false, "reuse the last release's values and merge in any new values")
7071
f.BoolVar(&diff.resetValues, "reset-values", false, "reset the values to the ones built into the chart and merge in any new values")
7172
f.StringArrayVar(&diff.suppressedKinds, "suppress", []string{}, "allows suppression of the values listed in the diff output")
73+
f.IntVarP(&diff.outputContext, "context", "C", -1, "output NUM lines of context around changes")
7274

7375
return cmd
7476

@@ -110,7 +112,7 @@ func (d *diffCmd) run() error {
110112
currentSpecs := manifest.Parse(releaseResponse.Release.Manifest)
111113
newSpecs := manifest.Parse(upgradeResponse.Release.Manifest)
112114

113-
diff.DiffManifests(currentSpecs, newSpecs, d.suppressedKinds, os.Stdout)
115+
diff.DiffManifests(currentSpecs, newSpecs, d.suppressedKinds, d.outputContext, os.Stdout)
114116

115117
return nil
116118
}

diff/diff.go

Lines changed: 70 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -4,38 +4,39 @@ import (
44
"fmt"
55
"io"
66
"strings"
7+
"math"
78

89
"github.com/aryann/difflib"
910
"github.com/mgutz/ansi"
1011

1112
"github.com/databus23/helm-diff/manifest"
1213
)
1314

14-
func DiffManifests(oldIndex, newIndex map[string]*manifest.MappingResult, suppressedKinds []string, to io.Writer) {
15+
func DiffManifests(oldIndex, newIndex map[string]*manifest.MappingResult, suppressedKinds []string, context int, to io.Writer) {
1516
for key, oldContent := range oldIndex {
1617
if newContent, ok := newIndex[key]; ok {
1718
if oldContent.Content != newContent.Content {
1819
// modified
1920
fmt.Fprintf(to, ansi.Color("%s has changed:", "yellow")+"\n", key)
20-
printDiff(suppressedKinds, oldContent.Kind, oldContent.Content, newContent.Content, to)
21+
printDiff(suppressedKinds, oldContent.Kind, context, oldContent.Content, newContent.Content, to)
2122
}
2223
} else {
2324
// removed
2425
fmt.Fprintf(to, ansi.Color("%s has been removed:", "yellow")+"\n", key)
25-
printDiff(suppressedKinds, oldContent.Kind, oldContent.Content, "", to)
26+
printDiff(suppressedKinds, oldContent.Kind, context, oldContent.Content, "", to)
2627
}
2728
}
2829

2930
for key, newContent := range newIndex {
3031
if _, ok := oldIndex[key]; !ok {
3132
// added
3233
fmt.Fprintf(to, ansi.Color("%s has been added:", "yellow")+"\n", key)
33-
printDiff(suppressedKinds, newContent.Kind, "", newContent.Content, to)
34+
printDiff(suppressedKinds, newContent.Kind, context, "", newContent.Content, to)
3435
}
3536
}
3637
}
3738

38-
func printDiff(suppressedKinds []string, kind, before, after string, to io.Writer) {
39+
func printDiff(suppressedKinds []string, kind string, context int, before, after string, to io.Writer) {
3940
diffs := difflib.Diff(strings.Split(before, "\n"), strings.Split(after, "\n"))
4041

4142
for _, ckind := range suppressedKinds {
@@ -46,16 +47,71 @@ func printDiff(suppressedKinds []string, kind, before, after string, to io.Write
4647
}
4748
}
4849

49-
for _, diff := range diffs {
50-
text := diff.Payload
50+
if context >= 0 {
51+
distances := calculateDistances(diffs)
52+
omitting := false
53+
for i, diff := range diffs {
54+
if distances[i] > context {
55+
if !omitting {
56+
fmt.Fprintln(to, "...")
57+
omitting = true
58+
}
59+
} else {
60+
omitting = false
61+
printDiffRecord(diff, to)
62+
}
63+
}
64+
} else {
65+
for _, diff := range diffs {
66+
printDiffRecord(diff, to)
67+
}
68+
}
69+
}
70+
71+
func printDiffRecord(diff difflib.DiffRecord, to io.Writer) {
72+
text := diff.Payload
73+
74+
switch diff.Delta {
75+
case difflib.RightOnly:
76+
fmt.Fprintf(to, "%s\n", ansi.Color("+ "+text, "green"))
77+
case difflib.LeftOnly:
78+
fmt.Fprintf(to, "%s\n", ansi.Color("- "+text, "red"))
79+
case difflib.Common:
80+
fmt.Fprintf(to, "%s\n", " "+text)
81+
}
82+
}
5183

52-
switch diff.Delta {
53-
case difflib.RightOnly:
54-
fmt.Fprintf(to, "%s\n", ansi.Color("+ "+text, "green"))
55-
case difflib.LeftOnly:
56-
fmt.Fprintf(to, "%s\n", ansi.Color("- "+text, "red"))
57-
case difflib.Common:
58-
fmt.Fprintf(to, "%s\n", " "+text)
84+
// Calculate distance of every diff-line to the closest change
85+
func calculateDistances(diffs []difflib.DiffRecord) map[int]int {
86+
distances := map[int]int{}
87+
88+
// Iterate forwards through diffs, set 'distance' based on closest 'change' before this line
89+
change := -1
90+
for i, diff := range diffs {
91+
if diff.Delta != difflib.Common {
92+
change = i
93+
}
94+
distance := math.MaxInt32
95+
if change != -1 {
96+
distance = i - change
97+
}
98+
distances[i] = distance
99+
}
100+
101+
// Iterate backwards through diffs, reduce 'distance' based on closest 'change' after this line
102+
change = -1
103+
for i := len(diffs) - 1; i >= 0; i-- {
104+
diff := diffs[i]
105+
if diff.Delta != difflib.Common {
106+
change = i
107+
}
108+
if change != -1 {
109+
distance := change - i
110+
if distance < distances[i] {
111+
distances[i] = distance
112+
}
59113
}
60114
}
115+
116+
return distances
61117
}

0 commit comments

Comments
 (0)