summaryrefslogtreecommitdiffhomepage
path: root/internal/diff
diff options
context:
space:
mode:
authorGarrett Mitchell Ladley <[email protected]>2025-04-26 21:42:22 -0400
committerKujtim Hoxha <[email protected]>2025-04-27 13:56:57 +0200
commitd93694a97961ba33d952535f71f4afa2ea924bb9 (patch)
tree4933cc909875401de0aa5d172bdac25243e1546a /internal/diff
parent8a4d4152ce450fda5c7b2894ed59f615ca8f09da (diff)
downloadopencode-d93694a97961ba33d952535f71f4afa2ea924bb9.tar.gz
opencode-d93694a97961ba33d952535f71f4afa2ea924bb9.zip
feat: simpler diff implementation
Diffstat (limited to 'internal/diff')
-rw-r--r--internal/diff/diff.go118
1 files changed, 14 insertions, 104 deletions
diff --git a/internal/diff/diff.go b/internal/diff/diff.go
index 3daa0c200..a2edb7e74 100644
--- a/internal/diff/diff.go
+++ b/internal/diff/diff.go
@@ -4,23 +4,18 @@ import (
"bytes"
"fmt"
"io"
- "os"
- "path/filepath"
"regexp"
"strconv"
"strings"
- "time"
"github.com/alecthomas/chroma/v2"
"github.com/alecthomas/chroma/v2/formatters"
"github.com/alecthomas/chroma/v2/lexers"
"github.com/alecthomas/chroma/v2/styles"
+ "github.com/aymanbagabas/go-udiff"
"github.com/charmbracelet/lipgloss"
"github.com/charmbracelet/x/ansi"
- "github.com/go-git/go-git/v5"
- "github.com/go-git/go-git/v5/plumbing/object"
"github.com/opencode-ai/opencode/internal/config"
- "github.com/opencode-ai/opencode/internal/logging"
"github.com/sergi/go-diff/diffmatchpatch"
)
@@ -942,106 +937,21 @@ func GenerateDiff(beforeContent, afterContent, fileName string) (string, int, in
cwd := config.WorkingDirectory()
fileName = strings.TrimPrefix(fileName, cwd)
fileName = strings.TrimPrefix(fileName, "/")
- // Create temporary directory for git operations
- tempDir, err := os.MkdirTemp("", fmt.Sprintf("git-diff-%d", time.Now().UnixNano()))
- if err != nil {
- logging.Error("Failed to create temp directory for git diff", "error", err)
- return "", 0, 0
- }
- defer os.RemoveAll(tempDir)
-
- // Initialize git repo
- repo, err := git.PlainInit(tempDir, false)
- if err != nil {
- logging.Error("Failed to initialize git repository", "error", err)
- return "", 0, 0
- }
-
- wt, err := repo.Worktree()
- if err != nil {
- logging.Error("Failed to get git worktree", "error", err)
- return "", 0, 0
- }
-
- // Write the "before" content and commit it
- fullPath := filepath.Join(tempDir, fileName)
- if err = os.MkdirAll(filepath.Dir(fullPath), 0o755); err != nil {
- logging.Error("Failed to create directory for file", "error", err)
- return "", 0, 0
- }
- if err = os.WriteFile(fullPath, []byte(beforeContent), 0o644); err != nil {
- logging.Error("Failed to write before content to file", "error", err)
- return "", 0, 0
- }
-
- _, err = wt.Add(fileName)
- if err != nil {
- logging.Error("Failed to add file to git", "error", err)
- return "", 0, 0
- }
-
- beforeCommit, err := wt.Commit("Before", &git.CommitOptions{
- Author: &object.Signature{
- Name: "OpenCode",
- Email: "[email protected]",
- When: time.Now(),
- },
- })
- if err != nil {
- logging.Error("Failed to commit before content", "error", err)
- return "", 0, 0
- }
-
- // Write the "after" content and commit it
- if err = os.WriteFile(fullPath, []byte(afterContent), 0o644); err != nil {
- logging.Error("Failed to write after content to file", "error", err)
- return "", 0, 0
- }
-
- _, err = wt.Add(fileName)
- if err != nil {
- logging.Error("Failed to add file to git", "error", err)
- return "", 0, 0
- }
-
- afterCommit, err := wt.Commit("After", &git.CommitOptions{
- Author: &object.Signature{
- Name: "OpenCode",
- Email: "[email protected]",
- When: time.Now(),
- },
- })
- if err != nil {
- logging.Error("Failed to commit after content", "error", err)
- return "", 0, 0
- }
- // Get the diff between the two commits
- beforeCommitObj, err := repo.CommitObject(beforeCommit)
- if err != nil {
- logging.Error("Failed to get before commit object", "error", err)
- return "", 0, 0
- }
-
- afterCommitObj, err := repo.CommitObject(afterCommit)
- if err != nil {
- logging.Error("Failed to get after commit object", "error", err)
- return "", 0, 0
- }
-
- patch, err := beforeCommitObj.Patch(afterCommitObj)
- if err != nil {
- logging.Error("Failed to create git diff patch", "error", err)
- return "", 0, 0
- }
+ var (
+ unified = udiff.Unified("a/"+fileName, "b/"+fileName, beforeContent, afterContent)
+ additions = 0
+ removals = 0
+ )
- // Count additions and removals
- additions := 0
- removals := 0
- for _, fileStat := range patch.Stats() {
- additions += fileStat.Addition
- removals += fileStat.Deletion
+ lines := strings.Split(unified, "\n")
+ for _, line := range lines {
+ if strings.HasPrefix(line, "+") && !strings.HasPrefix(line, "+++") {
+ additions++
+ } else if strings.HasPrefix(line, "-") && !strings.HasPrefix(line, "---") {
+ removals++
+ }
}
- return patch.String(), additions, removals
+ return unified, additions, removals
}