Skip to content

Commit

Permalink
feat: added command circleci orb diff
Browse files Browse the repository at this point in the history
  • Loading branch information
JulesFaucherre authored and AbrahamTewa committed Dec 16, 2022
1 parent 802994b commit c92cb9c
Show file tree
Hide file tree
Showing 3 changed files with 100 additions and 0 deletions.
97 changes: 97 additions & 0 deletions cmd/orb.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import (
"github.com/CircleCI-Public/circleci-cli/references"
"github.com/CircleCI-Public/circleci-cli/settings"
"github.com/CircleCI-Public/circleci-cli/version"
"github.com/fatih/color"
"github.com/pkg/errors"
"github.com/spf13/cobra"
"gopkg.in/yaml.v3"
Expand All @@ -34,13 +35,19 @@ import (
"github.com/go-git/go-git/v5/config"
"github.com/go-git/go-git/v5/plumbing"
"github.com/go-git/go-git/v5/plumbing/object"

"github.com/hexops/gotextdiff"
"github.com/hexops/gotextdiff/myers"
"github.com/hexops/gotextdiff/span"
)

type orbOptions struct {
cfg *settings.Config
cl *graphql.Client
args []string

color string

listUncertified bool
listJSON bool
listDetails bool
Expand Down Expand Up @@ -320,6 +327,18 @@ Please note that at this time all orbs created in the registry are world-readabl
}
orbInit.PersistentFlags().BoolVarP(&opts.private, "private", "", false, "initialize a private orb")

orbDiff := &cobra.Command{
Use: "diff <orb> <version1> <version2>",
Short: "Shows the difference between two versions of the same orb",
RunE: func(_ *cobra.Command, _ []string) error {
return orbDiff(opts)
},
Args: cobra.ExactArgs(3),
Annotations: make(map[string]string),
}
orbDiff.Annotations["<orb>"] = "An orb with only a namespace and a name. This takes this form namespace/orb"
orbDiff.PersistentFlags().StringVar(&opts.color, "color", "auto", "Show colored diff. Can be one of always, never, or auto")

orbCreate.Flags().BoolVar(&opts.integrationTesting, "integration-testing", false, "Enable test mode to bypass interactive UI.")
if err := orbCreate.Flags().MarkHidden("integration-testing"); err != nil {
panic(err)
Expand Down Expand Up @@ -354,6 +373,7 @@ Please note that at this time all orbs created in the registry are world-readabl
orbCommand.AddCommand(removeCategorizationFromOrbCommand)
orbCommand.AddCommand(listCategoriesCommand)
orbCommand.AddCommand(orbInit)
orbCommand.AddCommand(orbDiff)

return orbCommand
}
Expand Down Expand Up @@ -1609,3 +1629,80 @@ func orbTemplate(fileContents string, projectName string, orgName string, orbNam

return x
}

func orbDiff(opts orbOptions) error {
colorOpt := opts.color
if colorOpt != "auto" && colorOpt != "always" && colorOpt != "never" {
return fmt.Errorf("option `color' expects \"always\", \"auto\", or \"never\"")
}

orbName := opts.args[0]
version1 := opts.args[1]
version2 := opts.args[2]
orb1 := fmt.Sprintf("%s@%s", orbName, version1)
orb2 := fmt.Sprintf("%s@%s", orbName, version2)

orb1Source, err := api.OrbSource(opts.cl, orb1)
if err != nil {
return errors.Wrapf(err, "Failed to get source for '%s'", orb1)
}
orb2Source, err := api.OrbSource(opts.cl, orb2)
if err != nil {
return errors.Wrapf(err, "Failed to get source for '%s'", orb2)
}

edits := myers.ComputeEdits(span.URIFromPath(orb1), orb1Source, orb2Source)
unified := gotextdiff.ToUnified(orb1, orb2, orb1Source, edits)
diff := stringifyDiff(unified, colorOpt)
if diff == "" {
fmt.Println("No diff found")
} else {
fmt.Println(diff)
}

return nil
}

// Stringifies the unified diff passed as argument, and colorize it depending on the colorOpt value
func stringifyDiff(diff gotextdiff.Unified, colorOpt string) string {
if len(diff.Hunks) == 0 {
return ""
}

headerColor := color.New(color.BgYellow, color.FgBlack)
diffStartColor := color.New(color.BgBlue, color.FgWhite)
deleteColor := color.New(color.FgRed)
insertColor := color.New(color.FgGreen)
untouchedColor := color.New(color.Reset)

// The color library already takes care of disabling the color when stdout is redirected so we
// just enforce the color behavior for "never" and "always" and let the library handle the 'auto'
// case
oldNoColor := color.NoColor
if colorOpt == "never" {
color.NoColor = true
}
if colorOpt == "always" {
color.NoColor = false
}

diffString := fmt.Sprintf("%s", diff)
lines := strings.Split(diffString, "\n")

for i, line := range lines {
if strings.HasPrefix(line, "--- ") || strings.HasPrefix(line, "+++ ") {
lines[i] = headerColor.Sprint(line)
} else if strings.HasPrefix(line, "@@ ") {
lines[i] = diffStartColor.Sprint(line)
} else if strings.HasPrefix(line, "-") {
lines[i] = deleteColor.Sprint(line)
} else if strings.HasPrefix(line, "+") {
lines[i] = insertColor.Sprint(line)
} else {
lines[i] = untouchedColor.Sprint(line)
}
}

color.NoColor = oldNoColor
return strings.Join(lines, "\n")
}
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ require (
require (
github.com/charmbracelet/lipgloss v0.5.0
github.com/erikgeiser/promptkit v0.7.0
github.com/hexops/gotextdiff v1.0.3
)

require (
Expand Down
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -190,6 +190,8 @@ github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+
github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk=
github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
github.com/hexops/gotextdiff v1.0.3 h1:gitA9+qJrrTCsiCl7+kh75nPqQt1cx4ZkudSTLoUqJM=
github.com/hexops/gotextdiff v1.0.3/go.mod h1:pSWU5MAI3yDq+fZBTazCSJysOMbxWL1BSow5/V2vxeg=
github.com/hinshun/vt10x v0.0.0-20180616224451-1954e6464174/go.mod h1:DqJ97dSdRW1W22yXSB90986pcOyQ7r45iio1KN2ez1A=
github.com/hinshun/vt10x v0.0.0-20220301184237-5011da428d02 h1:AgcIVYPa6XJnU3phs104wLj8l5GEththEw6+F79YsIY=
github.com/hinshun/vt10x v0.0.0-20220301184237-5011da428d02/go.mod h1:Q48J4R4DvxnHolD5P8pOtXigYlRuPLGl6moFx3ulM68=
Expand Down

0 comments on commit c92cb9c

Please sign in to comment.