Skip to content

Commit

Permalink
print diff between revisions
Browse files Browse the repository at this point in the history
  • Loading branch information
davidmdm committed Feb 25, 2024
1 parent 6aa96a5 commit 706e050
Show file tree
Hide file tree
Showing 3 changed files with 97 additions and 8 deletions.
102 changes: 95 additions & 7 deletions cmd/halloumi/cmd_blackbox.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,17 +13,21 @@ import (
"strings"

"github.com/jedib0t/go-pretty/v6/table"
"github.com/pmezard/go-difflib/difflib"
"gopkg.in/yaml.v3"
"k8s.io/client-go/tools/clientcmd"

"github.com/davidmdm/ansi"
"github.com/davidmdm/halloumi/internal"
"github.com/davidmdm/halloumi/internal/k8"
)

type BlackboxParams struct {
GlobalSettings
Release string
RevisionID int
Release string
RevisionID int
DiffRevisionID int
Context int
}

//go:embed cmd_blackbox_help.txt
Expand All @@ -44,6 +48,7 @@ func GetBlackBoxParams(settings GlobalSettings, args []string) (*BlackboxParams,
params := BlackboxParams{GlobalSettings: settings}

RegisterGlobalFlags(flagset, &params.GlobalSettings)
flagset.IntVar(&params.Context, "context", 4, "number of lines of context in diff (ignored if not comparing revisions)")

flagset.Parse(args)

Expand All @@ -57,6 +62,14 @@ func GetBlackBoxParams(settings GlobalSettings, args []string) (*BlackboxParams,
params.RevisionID = revisionID
}

if revision := flagset.Arg(2); revision != "" {
revisionID, err := strconv.Atoi(flagset.Arg(2))
if err != nil {
return nil, fmt.Errorf("revision to diff must be an integer ID: %w", err)
}
params.DiffRevisionID = revisionID
}

return &params, nil
}

Expand Down Expand Up @@ -118,20 +131,62 @@ func Blackbox(ctx context.Context, params BlackboxParams) error {
return fmt.Errorf("revision %d not found", params.RevisionID)
}

output := make(map[string]any, len(revision.Resources))
primaryRevision := make(map[string]any, len(revision.Resources))
for _, resource := range revision.Resources {
primaryRevision[internal.Canonical(resource)] = resource.Object
}

if params.DiffRevisionID == 0 {
encoder := yaml.NewEncoder(os.Stdout)
encoder.SetIndent(2)

if err := encoder.Encode(primaryRevision); err != nil {
return fmt.Errorf("failed to encode resources: %w", err)
}
return nil
}

revision, ok = Find(revisions.History, func(revision internal.Revision) bool {
return revision.ID == params.DiffRevisionID
})
if !ok {
return fmt.Errorf("revision %d not found", params.DiffRevisionID)
}

diffRevision := make(map[string]any, len(revision.Resources))
for _, resource := range revision.Resources {
output[internal.Canonical(resource)] = resource.Object
diffRevision[internal.Canonical(resource)] = resource.Object
}

var buffer bytes.Buffer
encoder := yaml.NewEncoder(&buffer)
encoder.SetIndent(2)

if err := encoder.Encode(output); err != nil {
return fmt.Errorf("failed to encode resources: %w", err)
if err := encoder.Encode(primaryRevision); err != nil {
return err
}

a := buffer.String()

buffer.Reset()

if err := encoder.Encode(diffRevision); err != nil {
return err
}

_, err = fmt.Fprint(os.Stdout, buffer.String())
b := buffer.String()

diff, _ := difflib.GetUnifiedDiffString(difflib.UnifiedDiff{
A: indentLines(difflib.SplitLines(a), "\t"),
B: indentLines(difflib.SplitLines(b), "\t"),
FromFile: fmt.Sprintf("revision %d", params.RevisionID),
ToFile: fmt.Sprintf("revision %d", params.DiffRevisionID),
Context: params.Context,
})

diff = colorizeDiff(diff)

_, err = fmt.Fprint(os.Stdout, diff)
return err
}

Expand All @@ -144,3 +199,36 @@ func Find[S ~[]E, E any](slice S, fn func(E) bool) (E, bool) {
return slice[idx], true
}
}

var (
green = ansi.MakeStyle(ansi.FgGreen)
red = ansi.MakeStyle(ansi.FgRed)
)

func colorizeDiff(value string) string {
lines := strings.Split(value, "\n")
colorized := make([]string, len(lines))
for i, line := range lines {
if len(line) == 0 {
continue
}
switch line[0] {
case '-':
colorized[i] = green.Sprint(line)
case '+':
colorized[i] = red.Sprint(line)
default:
colorized[i] = line
}
}

return strings.Join(colorized, "\n")
}

func indentLines(lines []string, indent string) []string {
result := make([]string, len(lines))
for i, line := range lines {
result[i] = indent + line
}
return result
}
2 changes: 1 addition & 1 deletion cmd/halloumi/cmd_blackbox_help.txt
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
!yellow halloumi blackox

!cyan Usage:
halloumi blackbox [flags] [release] [revision-id]
halloumi blackbox [flags] [release] [revision-id] [revision-id-to-compare]

!cyan Aliases:
inspect
Expand Down
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ require (
github.com/davidmdm/x/xcontext v0.0.2
github.com/davidmdm/x/xerr v0.0.3
github.com/jedib0t/go-pretty/v6 v6.5.4
github.com/pmezard/go-difflib v1.0.0
github.com/tetratelabs/wazero v1.6.0
golang.org/x/term v0.17.0
gopkg.in/yaml.v3 v3.0.1
Expand Down

0 comments on commit 706e050

Please sign in to comment.