diff --git a/.gitignore b/.gitignore index becf222..f2a47c0 100644 --- a/.gitignore +++ b/.gitignore @@ -3,4 +3,7 @@ build/ grokkit *.bak *.log -*.tmp \ No newline at end of file +*.tmp +.env +coverage.out +coverage.html \ No newline at end of file diff --git a/REAMDE.md b/README.md similarity index 100% rename from REAMDE.md rename to README.md diff --git a/cmd/commit.go b/cmd/commit.go index 17c41fe..c8b4b0c 100644 --- a/cmd/commit.go +++ b/cmd/commit.go @@ -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 diff --git a/cmd/commitmsg.go b/cmd/commitmsg.go index 5881ac6..3d3f990 100644 --- a/cmd/commitmsg.go +++ b/cmd/commitmsg.go @@ -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 diff --git a/cmd/edit.go b/cmd/edit.go index ff9d080..bad68fb 100644 --- a/cmd/edit.go +++ b/cmd/edit.go @@ -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) }, } diff --git a/cmd/history.go b/cmd/history.go index 7f9d453..2cf3558 100644 --- a/cmd/history.go +++ b/cmd/history.go @@ -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 diff --git a/cmd/prdescribe.go b/cmd/prdescribe.go index 9c73132..bd83d8a 100644 --- a/cmd/prdescribe.go +++ b/cmd/prdescribe.go @@ -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.") diff --git a/cmd/review.go b/cmd/review.go index 90dce62..98d0ef4 100644 --- a/cmd/review.go +++ b/cmd/review.go @@ -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."}, diff --git a/config/config.go b/config/config.go index 55f3533..d6d3b92 100644 --- a/config/config.go +++ b/config/config.go @@ -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() } diff --git a/internal/git/git.go b/internal/git/git.go new file mode 100644 index 0000000..56ada0b --- /dev/null +++ b/internal/git/git.go @@ -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 +} diff --git a/internal/git/helper.go b/internal/git/helper.go deleted file mode 100644 index 4f7f897..0000000 --- a/internal/git/helper.go +++ /dev/null @@ -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 -} diff --git a/internal/grok/client.go b/internal/grok/client.go index daa36fd..5c08bc1 100644 --- a/internal/grok/client.go +++ b/internal/grok/client.go @@ -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")