refactor: add error handling and refactor git utilities

- Enhance error checking in all commands using git.Run
- Refactor git helper to return errors properly
- Fix README.md filename typo
- Update .gitignore with additional ignores
- Add fallback for config home dir
- Improve request handling in grok client
This commit is contained in:
Greg Gauthier 2026-03-01 12:08:49 +00:00
parent f1dc9b457d
commit 9bd3e1d00e
12 changed files with 84 additions and 28 deletions

3
.gitignore vendored
View File

@ -4,3 +4,6 @@ grokkit
*.bak
*.log
*.tmp
.env
coverage.out
coverage.html

View File

@ -15,7 +15,11 @@ var commitCmd = &cobra.Command{
Use: "commit",
Short: "Generate message and commit staged changes",
Run: func(cmd *cobra.Command, args []string) {
diff := git.Run([]string{"diff", "--cached", "--no-color"})
diff, err := git.Run([]string{"diff", "--cached", "--no-color"})
if err != nil {
color.Red("Failed to get staged changes: %v", err)
return
}
if diff == "" {
color.Yellow("No staged changes!")
return

View File

@ -14,7 +14,11 @@ var commitMsgCmd = &cobra.Command{
Use: "commit-msg",
Short: "Generate conventional commit message from staged changes",
Run: func(cmd *cobra.Command, args []string) {
diff := git.Run([]string{"diff", "--cached", "--no-color"})
diff, err := git.Run([]string{"diff", "--cached", "--no-color"})
if err != nil {
color.Red("Failed to get staged changes: %v", err)
return
}
if diff == "" {
color.Yellow("No staged changes!")
return

View File

@ -28,11 +28,18 @@ var editCmd = &cobra.Command{
os.Exit(1)
}
original, _ := os.ReadFile(filePath)
original, err := os.ReadFile(filePath)
if err != nil {
color.Red("Failed to read file: %v", err)
os.Exit(1)
}
cleanedOriginal := removeLastModifiedComments(string(original))
backupPath := filePath + ".bak"
_ = os.WriteFile(backupPath, original, 0644)
if err := os.WriteFile(backupPath, original, 0644); err != nil {
color.Red("Failed to create backup: %v", err)
os.Exit(1)
}
client := grok.NewClient()
messages := []map[string]string{
@ -57,7 +64,10 @@ var editCmd = &cobra.Command{
return
}
_ = os.WriteFile(filePath, []byte(newContent), 0644)
if err := os.WriteFile(filePath, []byte(newContent), 0644); err != nil {
color.Red("Failed to write file: %v", err)
os.Exit(1)
}
color.Green("✅ Applied successfully! Backup: %s", backupPath)
},
}

View File

@ -12,7 +12,11 @@ var historyCmd = &cobra.Command{
Use: "history",
Short: "Summarize recent git history",
Run: func(cmd *cobra.Command, args []string) {
log := git.Run([]string{"log", "--oneline", "-10"})
log, err := git.Run([]string{"log", "--oneline", "-10"})
if err != nil {
color.Red("Failed to get git log: %v", err)
return
}
if log == "" {
color.Yellow("No commits found.")
return

View File

@ -14,9 +14,13 @@ var prDescribeCmd = &cobra.Command{
Use: "pr-describe",
Short: "Generate full PR description from current branch",
Run: func(cmd *cobra.Command, args []string) {
diff := git.Run([]string{"diff", "main..HEAD", "--no-color"})
if diff == "" {
diff = git.Run([]string{"diff", "origin/main..HEAD", "--no-color"})
diff, err := git.Run([]string{"diff", "main..HEAD", "--no-color"})
if err != nil || diff == "" {
diff, err = git.Run([]string{"diff", "origin/main..HEAD", "--no-color"})
if err != nil {
color.Red("Failed to get branch diff: %v", err)
return
}
}
if diff == "" {
color.Yellow("No changes on this branch compared to main/origin/main.")

View File

@ -18,8 +18,16 @@ var reviewCmd = &cobra.Command{
model := config.GetModel(modelFlag)
client := grok.NewClient()
diff := git.Run([]string{"diff", "--no-color"})
status := git.Run([]string{"status", "--short"})
diff, err := git.Run([]string{"diff", "--no-color"})
if err != nil {
color.Red("Failed to get git diff: %v", err)
return
}
status, err := git.Run([]string{"status", "--short"})
if err != nil {
color.Red("Failed to get git status: %v", err)
return
}
messages := []map[string]string{
{"role": "system", "content": "You are an expert code reviewer. Give a concise summary + 3-5 actionable improvements."},

View File

@ -8,7 +8,11 @@ import (
)
func Load() {
home, _ := os.UserHomeDir()
home, err := os.UserHomeDir()
if err != nil {
// Fall back to current directory if home not found
home = "."
}
configPath := filepath.Join(home, ".config", "grokkit")
viper.SetConfigName("config")
@ -20,6 +24,7 @@ func Load() {
viper.SetDefault("default_model", "grok-4")
viper.SetDefault("temperature", 0.7)
// Config file is optional, so we ignore read errors
_ = viper.ReadInConfig()
}

19
internal/git/git.go Normal file
View File

@ -0,0 +1,19 @@
package git
import (
"fmt"
"os/exec"
)
func Run(args []string) (string, error) {
out, err := exec.Command("git", args...).Output()
if err != nil {
return "", fmt.Errorf("git command failed: %w", err)
}
return string(out), nil
}
func IsRepo() bool {
_, err := exec.Command("git", "rev-parse", "--is-inside-work-tree").Output()
return err == nil
}

View File

@ -1,13 +0,0 @@
package git
import "os/exec"
func Run(args []string) string {
out, _ := exec.Command("git", args...).Output()
return string(out)
}
func IsRepo() bool {
_, err := exec.Command("git", "rev-parse", "--is-inside-work-tree").Output()
return err == nil
}

View File

@ -49,8 +49,16 @@ func (c *Client) streamInternal(messages []map[string]string, model string, prin
"stream": true,
}
body, _ := json.Marshal(payload)
req, _ := http.NewRequest("POST", url, bytes.NewReader(body))
body, err := json.Marshal(payload)
if err != nil {
color.Red("Failed to marshal request: %v", err)
os.Exit(1)
}
req, err := http.NewRequest("POST", url, bytes.NewReader(body))
if err != nil {
color.Red("Failed to create request: %v", err)
os.Exit(1)
}
req.Header.Set("Authorization", "Bearer "+c.APIKey)
req.Header.Set("Content-Type", "application/json")