1package cmd23import (4 "fmt"5 "strings"6 "time"78 gansi "charm.land/glamour/v2/ansi"9 "github.com/charmbracelet/soft-serve/git"10 "github.com/charmbracelet/soft-serve/pkg/backend"11 "github.com/charmbracelet/soft-serve/pkg/ui/common"12 "github.com/charmbracelet/soft-serve/pkg/ui/styles"13 "github.com/charmbracelet/soft-serve/pkg/utils"14 "github.com/spf13/cobra"15)1617// commitCommand returns a command that prints the contents of a commit.18func commitCommand() *cobra.Command {19 var color bool20 var patchOnly bool2122 cmd := &cobra.Command{23 Use: "commit repo SHA",24 Short: "Print out the contents of a diff",25 Args: cobra.ExactArgs(2),26 PersistentPreRunE: checkIfReadable,27 RunE: func(cmd *cobra.Command, args []string) error {28 ctx := cmd.Context()29 be := backend.FromContext(ctx)30 repoName := args[0]31 commitSHA := args[1]3233 rr, err := be.Repository(ctx, repoName)34 if err != nil {35 return err36 }3738 r, err := rr.Open()39 if err != nil {40 return err41 }4243 commit, err := r.CommitByRevision(commitSHA)44 if err != nil {45 return err46 }4748 patch, err := r.Patch(commit)49 if err != nil {50 return err51 }5253 diff, err := r.Diff(commit)54 if err != nil {55 return err56 }5758 commonStyle := styles.DefaultStyles()59 style := commonStyle.Log6061 s := strings.Builder{}62 commitLine := "commit " + commitSHA63 authorLine := "Author: " + utils.Sanitize(commit.Author.Name)64 dateLine := "Date: " + commit.Committer.When.UTC().Format(time.UnixDate)65 msgLine := strings.ReplaceAll(utils.Sanitize(commit.Message), "\r\n", "\n")66 statsLine := renderStats(diff, commonStyle, color)67 diffLine := renderDiff(patch, color)6869 if patchOnly {70 cmd.Println(71 diffLine,72 )73 return nil74 }7576 if color {77 s.WriteString(fmt.Sprintf("%s\n%s\n%s\n%s\n",78 style.CommitHash.Render(commitLine),79 style.CommitAuthor.Render(authorLine),80 style.CommitDate.Render(dateLine),81 style.CommitBody.Render(msgLine),82 ))83 } else {84 s.WriteString(fmt.Sprintf("%s\n%s\n%s\n%s\n",85 commitLine,86 authorLine,87 dateLine,88 msgLine,89 ))90 }9192 s.WriteString(fmt.Sprintf("\n%s\n%s",93 statsLine,94 diffLine,95 ))9697 cmd.Println(98 s.String(),99 )100101 return nil102 },103 }104105 cmd.Flags().BoolVarP(&color, "color", "c", false, "Colorize output")106 cmd.Flags().BoolVarP(&patchOnly, "patch", "p", false, "Output patch only")107108 return cmd109}110111func renderDiff(patch string, color bool) string {112 c := patch113114 if color {115 var s strings.Builder116 var pr strings.Builder117118 diffChroma := &gansi.CodeBlockElement{119 Code: patch,120 Language: "diff",121 }122123 err := diffChroma.Render(&pr, common.StyleRenderer())124125 if err != nil {126 s.WriteString(fmt.Sprintf("\n%s", err.Error()))127 } else {128 s.WriteString(fmt.Sprintf("\n%s", pr.String()))129 }130131 c = s.String()132 }133134 return c135}136137func renderStats(diff *git.Diff, commonStyle *styles.Styles, color bool) string {138 style := commonStyle.Log139 c := diff.Stats().String()140141 if color {142 s := strings.Split(c, "\n")143144 for i, line := range s {145 ch := strings.Split(line, "|")146 if len(ch) > 1 {147 adddel := ch[len(ch)-1]148 adddel = strings.ReplaceAll(adddel, "+", style.CommitStatsAdd.Render("+"))149 adddel = strings.ReplaceAll(adddel, "-", style.CommitStatsDel.Render("-"))150 s[i] = strings.Join(ch[:len(ch)-1], "|") + "|" + adddel151 }152 }153154 return strings.Join(s, "\n")155 }156157 return c158}