Skip to content

Commit f07afcd

Browse files
committed
test message
1 parent aead069 commit f07afcd

15 files changed

Lines changed: 263 additions & 773 deletions

cmd/iterate/commands_git.go

Lines changed: 0 additions & 240 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,9 @@
11
package main
22

33
import (
4-
"context"
54
"fmt"
6-
"os"
7-
"os/exec"
85
"strconv"
96
"strings"
10-
11-
iteragent "github.com/GrayCodeAI/iteragent"
12-
"github.com/GrayCodeAI/iterate/internal/ui/selector"
137
)
148

159
// ---------------------------------------------------------------------------
@@ -85,240 +79,6 @@ func parsePRArgs(args string) parsedPR {
8579
}
8680
}
8781

88-
func handlePR(ctx context.Context, line string, a *iteragent.Agent, repoPath string) {
89-
arg := strings.TrimSpace(strings.TrimPrefix(strings.TrimPrefix(line, "/pr"), " "))
90-
parsed := parsePRArgs(arg)
91-
92-
switch parsed.sub {
93-
case prSubList:
94-
handlePRList(repoPath)
95-
case prSubView:
96-
handlePRView(repoPath, parsed.number)
97-
case prSubDiff:
98-
handlePRDiff(repoPath, parsed.number)
99-
case prSubReview:
100-
handlePRReview(repoPath, parsed.number, a, ctx)
101-
case prSubComment:
102-
handlePRComment(repoPath, parsed.number, parsed.text)
103-
case prSubCheckout:
104-
handlePRCheckout(repoPath, parsed.number)
105-
case prSubCreate:
106-
handlePRCreate(repoPath, parsed.draft)
107-
case prSubHelp:
108-
fmt.Printf(`%s/pr subcommands:%s
109-
/pr list — list open PRs
110-
/pr view [N] — view PR details
111-
/pr diff [N] — show PR diff
112-
/pr review [N] — AI code review of PR diff
113-
/pr comment N <text> — post a comment
114-
/pr checkout [N] — checkout PR branch
115-
/pr create [--draft] — create a new PR
116-
`, colorDim, colorReset)
117-
}
118-
}
119-
120-
func handlePRList(repoPath string) {
121-
cmd := exec.Command("gh", "pr", "list", "--limit", "20")
122-
cmd.Dir = repoPath
123-
cmd.Stdout = os.Stdout
124-
cmd.Stderr = os.Stderr
125-
if err := cmd.Run(); err != nil {
126-
fmt.Printf("%serror: %v%s\n", colorRed, err, colorReset)
127-
}
128-
fmt.Println()
129-
}
130-
131-
func handlePRView(repoPath string, number string) {
132-
if number == "" {
133-
var ok bool
134-
number, ok = selector.PromptLine("PR number:")
135-
if !ok || number == "" {
136-
return
137-
}
138-
}
139-
cmd := exec.Command("gh", "pr", "view", number)
140-
cmd.Dir = repoPath
141-
cmd.Stdout = os.Stdout
142-
cmd.Stderr = os.Stderr
143-
cmd.Run()
144-
fmt.Println()
145-
}
146-
147-
func handlePRDiff(repoPath string, number string) {
148-
if number == "" {
149-
var ok bool
150-
number, ok = selector.PromptLine("PR number:")
151-
if !ok || number == "" {
152-
return
153-
}
154-
}
155-
out, err := exec.Command("gh", "pr", "diff", number).Output()
156-
if err != nil {
157-
fmt.Printf("%scould not fetch PR diff: %v%s\n", colorRed, err, colorReset)
158-
return
159-
}
160-
diff := string(out)
161-
if len(diff) > 8000 {
162-
diff = diff[:8000] + "\n…[truncated]"
163-
}
164-
fmt.Printf("%s── PR #%s diff ────────────────────%s\n%s%s──────────────────────────────────%s\n\n",
165-
colorDim, number, colorReset, diff, colorDim, colorReset)
166-
}
167-
168-
func handlePRReview(repoPath string, number string, a *iteragent.Agent, ctx context.Context) {
169-
if number == "" {
170-
var ok bool
171-
number, ok = selector.PromptLine("PR number:")
172-
if !ok || number == "" {
173-
return
174-
}
175-
}
176-
out, err := exec.Command("gh", "pr", "diff", number).Output()
177-
if err != nil {
178-
fmt.Printf("%scould not fetch PR diff: %v%s\n", colorRed, err, colorReset)
179-
return
180-
}
181-
diff := string(out)
182-
if len(diff) > 8000 {
183-
diff = diff[:8000] + "\n…[truncated]"
184-
}
185-
prompt := buildPRReviewPrompt(number, diff)
186-
streamAndPrint(ctx, a, prompt, repoPath)
187-
}
188-
189-
func handlePRComment(repoPath string, number string, text string) {
190-
if number == "" {
191-
var ok bool
192-
number, ok = selector.PromptLine("PR number:")
193-
if !ok || number == "" {
194-
return
195-
}
196-
}
197-
if text == "" {
198-
var ok bool
199-
text, ok = selector.PromptLine("Comment:")
200-
if !ok || text == "" {
201-
return
202-
}
203-
}
204-
cmd := exec.Command("gh", "pr", "comment", number, "--body", text)
205-
cmd.Dir = repoPath
206-
cmd.Stdout = os.Stdout
207-
cmd.Stderr = os.Stderr
208-
if err := cmd.Run(); err != nil {
209-
fmt.Printf("%serror: %v%s\n", colorRed, err, colorReset)
210-
} else {
211-
fmt.Printf("%s✓ comment posted on PR #%s%s\n\n", colorLime, number, colorReset)
212-
}
213-
}
214-
215-
func handlePRCheckout(repoPath string, number string) {
216-
if number == "" {
217-
// List PRs and let user pick
218-
out, _ := exec.Command("gh", "pr", "list", "--json", "number,title,headRefName",
219-
"--template", `{{range .}}#{{.number}} {{.title}} ({{.headRefName}}){{"\n"}}{{end}}`).Output()
220-
prs := strings.Split(strings.TrimSpace(string(out)), "\n")
221-
var nonEmpty []string
222-
for _, pr := range prs {
223-
if strings.TrimSpace(pr) != "" {
224-
nonEmpty = append(nonEmpty, pr)
225-
}
226-
}
227-
if len(nonEmpty) == 0 {
228-
fmt.Println("No open PRs found.")
229-
return
230-
}
231-
choice, ok := selector.SelectItem("Select PR to checkout", nonEmpty)
232-
if !ok {
233-
return
234-
}
235-
// Extract number from "#123 ..."
236-
if len(choice) > 1 && choice[0] == '#' {
237-
end := strings.Index(choice[1:], " ")
238-
if end >= 0 {
239-
number = choice[1 : end+1]
240-
}
241-
}
242-
if number == "" {
243-
return
244-
}
245-
}
246-
cmd := exec.Command("gh", "pr", "checkout", number)
247-
cmd.Dir = repoPath
248-
cmd.Stdout = os.Stdout
249-
cmd.Stderr = os.Stderr
250-
if err := cmd.Run(); err != nil {
251-
fmt.Printf("%serror: %v%s\n", colorRed, err, colorReset)
252-
} else {
253-
fmt.Printf("%s✓ checked out PR #%s%s\n\n", colorLime, number, colorReset)
254-
}
255-
}
256-
257-
func handlePRCreate(repoPath string, draft bool) {
258-
branchOut, _ := exec.Command("git", "-C", repoPath, "branch", "--show-current").Output()
259-
branch := strings.TrimSpace(string(branchOut))
260-
if branch == "" || branch == "main" || branch == "master" {
261-
fmt.Printf("%screate a feature branch first. current: %s%s\n", colorRed, branch, colorReset)
262-
return
263-
}
264-
title, ok := selector.PromptLine("PR title:")
265-
if !ok || title == "" {
266-
fmt.Println("cancelled.")
267-
return
268-
}
269-
body, ok := selector.PromptLine("PR body (Enter for auto):")
270-
if !ok {
271-
return
272-
}
273-
if body == "" {
274-
body = fmt.Sprintf("Created by iterate from branch `%s`.", branch)
275-
}
276-
// Push branch first
277-
pushCmd := exec.Command("git", "-C", repoPath, "push", "-u", "origin", branch)
278-
pushCmd.Stdout = os.Stdout
279-
pushCmd.Stderr = os.Stderr
280-
pushCmd.Run()
281-
// Create PR
282-
args := []string{"pr", "create", "--title", title, "--body", body}
283-
if draft {
284-
args = append(args, "--draft")
285-
}
286-
prCmd := exec.Command("gh", args...)
287-
prCmd.Dir = repoPath
288-
prCmd.Stdout = os.Stdout
289-
prCmd.Stderr = os.Stderr
290-
prCmd.Run()
291-
fmt.Println()
292-
}
293-
294-
// ---------------------------------------------------------------------------
295-
// Enhanced /diff with stat summary
296-
// ---------------------------------------------------------------------------
297-
298-
func showGitDiffEnhanced(repoPath string) {
299-
// Get stat
300-
statOut, _ := exec.Command("git", "-C", repoPath, "diff", "--stat", "HEAD").Output()
301-
if strings.TrimSpace(string(statOut)) == "" {
302-
statOut, _ = exec.Command("git", "-C", repoPath, "diff", "--stat").Output()
303-
}
304-
// Get full colored diff
305-
diffOut, err := exec.Command("git", "-C", repoPath, "diff", "--color=always", "HEAD").Output()
306-
if err != nil || len(strings.TrimSpace(string(diffOut))) == 0 {
307-
diffOut, _ = exec.Command("git", "-C", repoPath, "diff", "--color=always").Output()
308-
}
309-
if len(strings.TrimSpace(string(diffOut))) == 0 {
310-
fmt.Printf("%s(no changes)%s\n\n", colorDim, colorReset)
311-
return
312-
}
313-
fmt.Printf("\n%s── diff ──────────────────────────%s\n", colorDim, colorReset)
314-
if stat := strings.TrimSpace(string(statOut)); stat != "" {
315-
fmt.Println(stat)
316-
fmt.Printf("%s──────────────────────────────────%s\n", colorDim, colorReset)
317-
}
318-
fmt.Print(string(diffOut))
319-
fmt.Printf("%s──────────────────────────────────%s\n\n", colorDim, colorReset)
320-
}
321-
32282
// buildPRReviewPrompt constructs the AI review prompt for the given PR number and diff.
32383
func buildPRReviewPrompt(number, diff string) string {
32484
return fmt.Sprintf(

cmd/iterate/commands_project.go

Lines changed: 0 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,8 @@
11
package main
22

33
import (
4-
"fmt"
54
"os"
6-
"os/exec"
75
"path/filepath"
8-
"strings"
96
)
107

118
// ---------------------------------------------------------------------------
@@ -110,56 +107,3 @@ func healthChecksForProject(dir string, pt projectType) []projectCheck {
110107
}
111108
}
112109

113-
func runProjectHealthChecks(repoPath string, pt projectType) []healthResult {
114-
checks := healthChecksForProject(repoPath, pt)
115-
var results []healthResult
116-
117-
for _, c := range checks {
118-
cmd := exec.Command(c.args[0], c.args[1:]...)
119-
cmd.Dir = repoPath
120-
out, err := cmd.CombinedOutput()
121-
detail := strings.TrimSpace(string(out))
122-
if len(detail) > 100 {
123-
detail = detail[:100] + "…"
124-
}
125-
results = append(results, healthResult{check: c.name, ok: err == nil, detail: detail})
126-
}
127-
128-
// git clean check
129-
statusOut, _ := exec.Command("git", "-C", repoPath, "status", "--short").Output()
130-
dirty := strings.TrimSpace(string(statusOut)) != ""
131-
gitDetail := "working tree clean"
132-
if dirty {
133-
gitDetail = "uncommitted changes"
134-
}
135-
results = append(results, healthResult{check: "git clean", ok: !dirty, detail: gitDetail})
136-
137-
return results
138-
}
139-
140-
// buildFixPromptForProject builds a fix prompt using project-type-aware build output.
141-
func buildFixPromptForProject(repoPath string, pt projectType) string {
142-
var buildCmd []string
143-
switch pt {
144-
case projectTypeGo:
145-
buildCmd = []string{"go", "build", "./..."}
146-
case projectTypeRust:
147-
buildCmd = []string{"cargo", "build"}
148-
case projectTypeNode:
149-
buildCmd = []string{"npm", "run", "build"}
150-
default:
151-
buildCmd = []string{"make"}
152-
}
153-
154-
cmd := exec.Command(buildCmd[0], buildCmd[1:]...)
155-
cmd.Dir = repoPath
156-
out, _ := cmd.CombinedOutput()
157-
errText := strings.TrimSpace(string(out))
158-
if errText == "" {
159-
return ""
160-
}
161-
return fmt.Sprintf(
162-
"Fix the following build error. Read relevant files first, then apply the minimal fix. "+
163-
"Re-run the build to verify.\n\nBuild command: %s\n\nError:\n```\n%s\n```",
164-
strings.Join(buildCmd, " "), errText)
165-
}

cmd/iterate/features.go

Lines changed: 0 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ import (
66
"fmt"
77
"io/fs"
88
"os"
9-
"os/exec"
109
"path/filepath"
1110
"strings"
1211
"time"
@@ -87,24 +86,6 @@ func findTodos(repoPath string) []string {
8786
return results
8887
}
8988

90-
// ---------------------------------------------------------------------------
91-
// /issues — list GitHub issues via gh cli
92-
// ---------------------------------------------------------------------------
93-
94-
func listGitHubIssues(repoPath string, limit int) (string, error) {
95-
cmd := exec.Command("gh", "issue", "list",
96-
"--limit", fmt.Sprintf("%d", limit),
97-
"--json", "number,title,state,labels",
98-
"--template", `{{range .}}#{{.number}} {{.title}} [{{.state}}]{{"\n"}}{{end}}`)
99-
cmd.Dir = repoPath
100-
var out strings.Builder
101-
cmd.Stdout = &out
102-
cmd.Stderr = &out
103-
if err := cmd.Run(); err != nil {
104-
return "", fmt.Errorf("gh issue list: %s", strings.TrimSpace(out.String()))
105-
}
106-
return strings.TrimSpace(out.String()), nil
107-
}
10889

10990
// ---------------------------------------------------------------------------
11091
// /search-replace — find and replace text across all Go files

0 commit comments

Comments
 (0)