refactor(recipe): improve error handling and restructure in runner
- Move FileChange struct to top-level for better organization. - Enhance createUnifiedPatch with proper error handling on writes. - Remove unused bufio import and update comments. - Delete obsolete runner_test.go file.
This commit is contained in:
parent
7cb9eb3eb7
commit
0b5aa5eb57
@ -1,7 +1,6 @@
|
|||||||
package recipe
|
package recipe
|
||||||
|
|
||||||
import (
|
import (
|
||||||
_ "bufio"
|
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
@ -77,7 +76,7 @@ Execute this step now. Respond ONLY with the expected output format — no expla
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// discoverFiles does a real filesystem scan
|
// discoverFiles — temporary .go hard-code (we'll generalize with extensions next)
|
||||||
func (r *Runner) discoverFiles() []string {
|
func (r *Runner) discoverFiles() []string {
|
||||||
var files []string
|
var files []string
|
||||||
root := "internal"
|
root := "internal"
|
||||||
@ -99,7 +98,11 @@ func (r *Runner) discoverFiles() []string {
|
|||||||
return files
|
return files
|
||||||
}
|
}
|
||||||
|
|
||||||
// handleApplyStep parses strict JSON from the refactor step — no regex at all
|
type FileChange struct {
|
||||||
|
File string `json:"file"`
|
||||||
|
Content string `json:"content"`
|
||||||
|
}
|
||||||
|
|
||||||
func (r *Runner) handleApplyStep(previousResults []string) {
|
func (r *Runner) handleApplyStep(previousResults []string) {
|
||||||
if len(previousResults) == 0 {
|
if len(previousResults) == 0 {
|
||||||
fmt.Println(" ⚠️ No previous results to apply — skipping.")
|
fmt.Println(" ⚠️ No previous results to apply — skipping.")
|
||||||
@ -118,11 +121,6 @@ func (r *Runner) handleApplyStep(previousResults []string) {
|
|||||||
|
|
||||||
jsonStr := lastResult[start:end]
|
jsonStr := lastResult[start:end]
|
||||||
|
|
||||||
type FileChange struct {
|
|
||||||
File string `json:"file"`
|
|
||||||
Content string `json:"content"`
|
|
||||||
}
|
|
||||||
|
|
||||||
var changes []FileChange
|
var changes []FileChange
|
||||||
if err := json.Unmarshal([]byte(jsonStr), &changes); err != nil {
|
if err := json.Unmarshal([]byte(jsonStr), &changes); err != nil {
|
||||||
fmt.Printf(" ⚠️ Could not parse JSON: %v\n", err)
|
fmt.Printf(" ⚠️ Could not parse JSON: %v\n", err)
|
||||||
@ -144,17 +142,28 @@ func (r *Runner) handleApplyStep(previousResults []string) {
|
|||||||
fmt.Println(" Review it, then run with dry_run=false to apply.")
|
fmt.Println(" Review it, then run with dry_run=false to apply.")
|
||||||
}
|
}
|
||||||
|
|
||||||
func createUnifiedPatch(changes []struct{ File, Content string }, patchPath string) error {
|
func createUnifiedPatch(changes []FileChange, patchPath string) error {
|
||||||
f, err := os.Create(patchPath)
|
f, err := os.Create(patchPath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
defer f.Close()
|
defer func(f *os.File) {
|
||||||
|
err := f.Close()
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}(f)
|
||||||
|
|
||||||
for _, ch := range changes {
|
for _, ch := range changes {
|
||||||
fmt.Fprintf(f, "--- %s\n+++ %s\n@@ -0,0 +1,%d @@\n", ch.File, ch.File, strings.Count(ch.Content, "\n")+1)
|
_, err := fmt.Fprintf(f, "--- %s\n+++ %s\n@@ -0,0 +1,%d @@\n", ch.File, ch.File, strings.Count(ch.Content, "\n")+1)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
for _, line := range strings.Split(ch.Content, "\n") {
|
for _, line := range strings.Split(ch.Content, "\n") {
|
||||||
fmt.Fprintf(f, "+%s\n", line)
|
_, err := fmt.Fprintf(f, "+%s\n", line)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
|
|||||||
@ -1,61 +0,0 @@
|
|||||||
package recipe
|
|
||||||
|
|
||||||
import (
|
|
||||||
"reflect"
|
|
||||||
"testing"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestExtractCodeBlocks(t *testing.T) {
|
|
||||||
t.Parallel()
|
|
||||||
|
|
||||||
tests := []struct {
|
|
||||||
name string
|
|
||||||
input string
|
|
||||||
expected map[string]string
|
|
||||||
}{
|
|
||||||
{
|
|
||||||
name: "Single block",
|
|
||||||
input: "// main.go\n```go\npackage main\n\nfunc main() {}\n```",
|
|
||||||
expected: map[string]string{
|
|
||||||
"main.go": "package main\n\nfunc main() {}",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "Multiple blocks",
|
|
||||||
input: `// internal/utils.go
|
|
||||||
` + "```" + `go
|
|
||||||
package utils
|
|
||||||
func Help() {}
|
|
||||||
` + "```" + `
|
|
||||||
Some commentary.
|
|
||||||
// cmd/root.go
|
|
||||||
` + "```" + `go
|
|
||||||
package cmd
|
|
||||||
func Execute() {}
|
|
||||||
` + "```",
|
|
||||||
expected: map[string]string{
|
|
||||||
"internal/utils.go": "package utils\nfunc Help() {}",
|
|
||||||
"cmd/root.go": "package cmd\nfunc Execute() {}",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "No blocks",
|
|
||||||
input: "Just some text without any blocks.",
|
|
||||||
expected: map[string]string{},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "Incomplete block",
|
|
||||||
input: "// oops.go\n```go\nfunc incomplete() {",
|
|
||||||
expected: map[string]string{},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, tt := range tests {
|
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
|
||||||
got := extractCodeBlocks(tt.input)
|
|
||||||
if !reflect.DeepEqual(got, tt.expected) {
|
|
||||||
t.Errorf("extractCodeBlocks() = %v, want %v", got, tt.expected)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Loading…
Reference in New Issue
Block a user