google-labs-jules[bot]
Final deployment for HF with landing page
93d826e
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),
}
}