Spaces:
Paused
Paused
File size: 3,736 Bytes
93d826e | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 | package diff
import (
"bufio"
"fmt"
"log"
"os"
"os/exec"
"path/filepath"
"strconv"
"strings"
shared "plandex-shared"
"github.com/google/uuid"
)
func GetDiffs(original, updated string) (string, error) {
// create temp directory
tempDirPath, err := os.MkdirTemp("", "tmp-diffs-*")
if err != nil {
return "", fmt.Errorf("error creating temp dir: %v", err)
}
defer func() {
go os.RemoveAll(tempDirPath)
}()
// write the original file to the temp dir
err = os.WriteFile(filepath.Join(tempDirPath, "original"), []byte(original), 0644)
if err != nil {
return "", fmt.Errorf("error writing original file: %v", err)
}
// write the updated file to the temp dir
err = os.WriteFile(filepath.Join(tempDirPath, "updated"), []byte(updated), 0644)
if err != nil {
return "", fmt.Errorf("error writing updated file: %v", err)
}
cmd := exec.Command("git", "-C", tempDirPath, "diff", "--no-color", "--no-index", "original", "updated")
res, err := cmd.CombinedOutput()
if err != nil {
exitError, ok := err.(*exec.ExitError)
if ok && exitError.ExitCode() == 1 {
// Exit status 1 means diffs were found, which is expected
} else {
log.Printf("Error getting diffs: %v\n", err)
log.Printf("Diff output: %s\n", res)
return "", fmt.Errorf("error getting diffs: %v", err)
}
}
return string(res), nil
}
type change struct {
Old string
New string
Line int
Length int
}
func GetDiffReplacements(original, updated string) ([]*shared.Replacement, error) {
diff, err := GetDiffs(original, updated)
if err != nil {
return nil, fmt.Errorf("error getting git diffs: %v", err)
}
var changes []*change
scanner := bufio.NewScanner(strings.NewReader(diff))
var currentHunk *change
var oldLines, newLines []string
for scanner.Scan() {
line := scanner.Text()
// Parse hunk header
if strings.HasPrefix(line, "@@") {
// If we have a previous hunk, process it
if currentHunk != nil {
change := processHunk(oldLines, newLines, currentHunk.Line)
if change != nil {
changes = append(changes, change)
}
}
// Parse the new hunk header
lineInfo := strings.Split(line, " ")[1:] // Skip @@ part
oldInfo := strings.Split(lineInfo[0], ",")
startLine, _ := strconv.Atoi(strings.TrimPrefix(oldInfo[0], "-"))
currentHunk = &change{
Line: startLine,
}
oldLines = []string{}
newLines = []string{}
continue
}
if currentHunk == nil {
continue // Skip until we find a hunk
}
// Process the lines within a hunk
switch {
case strings.HasPrefix(line, "-"):
oldLines = append(oldLines, strings.TrimPrefix(line, "-"))
case strings.HasPrefix(line, "+"):
newLines = append(newLines, strings.TrimPrefix(line, "+"))
case strings.HasPrefix(line, " "):
// Context lines - add to both
line = strings.TrimPrefix(line, " ")
oldLines = append(oldLines, line)
newLines = append(newLines, line)
}
}
if err := scanner.Err(); err != nil {
return nil, fmt.Errorf("error scanning diff: %v", err)
}
// Process the last hunk if exists
if currentHunk != nil {
change := processHunk(oldLines, newLines, currentHunk.Line)
if change != nil {
changes = append(changes, change)
}
}
replacements := make([]*shared.Replacement, len(changes))
for i, change := range changes {
replacements[i] = &shared.Replacement{
Id: uuid.New().String(),
Old: change.Old,
New: change.New,
}
}
return replacements, nil
}
func processHunk(oldLines, newLines []string, startLine int) *change {
if len(oldLines) == 0 && len(newLines) == 0 {
return nil
}
return &change{
Old: strings.Join(oldLines, "\n"),
New: strings.Join(newLines, "\n"),
Line: startLine,
Length: len(oldLines),
}
}
|