diff options
Diffstat (limited to 'internal/git/diff.go')
| -rw-r--r-- | internal/git/diff.go | 264 |
1 files changed, 0 insertions, 264 deletions
diff --git a/internal/git/diff.go b/internal/git/diff.go deleted file mode 100644 index 2ab139642..000000000 --- a/internal/git/diff.go +++ /dev/null @@ -1,264 +0,0 @@ -package git - -import ( - "bytes" - "fmt" - "os" - "os/exec" - "path/filepath" - "strings" - "time" - - "github.com/go-git/go-git/v5" - "github.com/go-git/go-git/v5/plumbing/object" -) - -type DiffStats struct { - Additions int - Removals int -} - -func GenerateGitDiff(filePath string, contentBefore string, contentAfter string) (string, error) { - tempDir, err := os.MkdirTemp("", "git-diff-temp") - if err != nil { - return "", fmt.Errorf("failed to create temp dir: %w", err) - } - defer os.RemoveAll(tempDir) - - repo, err := git.PlainInit(tempDir, false) - if err != nil { - return "", fmt.Errorf("failed to initialize git repo: %w", err) - } - - wt, err := repo.Worktree() - if err != nil { - return "", fmt.Errorf("failed to get worktree: %w", err) - } - - fullPath := filepath.Join(tempDir, filePath) - if err = os.MkdirAll(filepath.Dir(fullPath), 0o755); err != nil { - return "", fmt.Errorf("failed to create directories: %w", err) - } - if err = os.WriteFile(fullPath, []byte(contentBefore), 0o644); err != nil { - return "", fmt.Errorf("failed to write 'before' content: %w", err) - } - - _, err = wt.Add(filePath) - if err != nil { - return "", fmt.Errorf("failed to add file to git: %w", err) - } - - beforeCommit, err := wt.Commit("Before", &git.CommitOptions{ - Author: &object.Signature{ - Name: "OpenCode", - Email: "[email protected]", - When: time.Now(), - }, - }) - if err != nil { - return "", fmt.Errorf("failed to commit 'before' version: %w", err) - } - - if err = os.WriteFile(fullPath, []byte(contentAfter), 0o644); err != nil { - return "", fmt.Errorf("failed to write 'after' content: %w", err) - } - - _, err = wt.Add(filePath) - if err != nil { - return "", fmt.Errorf("failed to add updated file to git: %w", err) - } - - afterCommit, err := wt.Commit("After", &git.CommitOptions{ - Author: &object.Signature{ - Name: "OpenCode", - Email: "[email protected]", - When: time.Now(), - }, - }) - if err != nil { - return "", fmt.Errorf("failed to commit 'after' version: %w", err) - } - - beforeCommitObj, err := repo.CommitObject(beforeCommit) - if err != nil { - return "", fmt.Errorf("failed to get 'before' commit: %w", err) - } - - afterCommitObj, err := repo.CommitObject(afterCommit) - if err != nil { - return "", fmt.Errorf("failed to get 'after' commit: %w", err) - } - - patch, err := beforeCommitObj.Patch(afterCommitObj) - if err != nil { - return "", fmt.Errorf("failed to generate patch: %w", err) - } - - return patch.String(), nil -} - -func GenerateGitDiffWithStats(filePath string, contentBefore string, contentAfter string) (string, DiffStats, error) { - tempDir, err := os.MkdirTemp("", "git-diff-temp") - if err != nil { - return "", DiffStats{}, fmt.Errorf("failed to create temp dir: %w", err) - } - defer os.RemoveAll(tempDir) - - repo, err := git.PlainInit(tempDir, false) - if err != nil { - return "", DiffStats{}, fmt.Errorf("failed to initialize git repo: %w", err) - } - - wt, err := repo.Worktree() - if err != nil { - return "", DiffStats{}, fmt.Errorf("failed to get worktree: %w", err) - } - - fullPath := filepath.Join(tempDir, filePath) - if err = os.MkdirAll(filepath.Dir(fullPath), 0o755); err != nil { - return "", DiffStats{}, fmt.Errorf("failed to create directories: %w", err) - } - if err = os.WriteFile(fullPath, []byte(contentBefore), 0o644); err != nil { - return "", DiffStats{}, fmt.Errorf("failed to write 'before' content: %w", err) - } - - _, err = wt.Add(filePath) - if err != nil { - return "", DiffStats{}, fmt.Errorf("failed to add file to git: %w", err) - } - - beforeCommit, err := wt.Commit("Before", &git.CommitOptions{ - Author: &object.Signature{ - Name: "OpenCode", - Email: "[email protected]", - When: time.Now(), - }, - }) - if err != nil { - return "", DiffStats{}, fmt.Errorf("failed to commit 'before' version: %w", err) - } - - if err = os.WriteFile(fullPath, []byte(contentAfter), 0o644); err != nil { - return "", DiffStats{}, fmt.Errorf("failed to write 'after' content: %w", err) - } - - _, err = wt.Add(filePath) - if err != nil { - return "", DiffStats{}, fmt.Errorf("failed to add updated file to git: %w", err) - } - - afterCommit, err := wt.Commit("After", &git.CommitOptions{ - Author: &object.Signature{ - Name: "OpenCode", - Email: "[email protected]", - When: time.Now(), - }, - }) - if err != nil { - return "", DiffStats{}, fmt.Errorf("failed to commit 'after' version: %w", err) - } - - beforeCommitObj, err := repo.CommitObject(beforeCommit) - if err != nil { - return "", DiffStats{}, fmt.Errorf("failed to get 'before' commit: %w", err) - } - - afterCommitObj, err := repo.CommitObject(afterCommit) - if err != nil { - return "", DiffStats{}, fmt.Errorf("failed to get 'after' commit: %w", err) - } - - patch, err := beforeCommitObj.Patch(afterCommitObj) - if err != nil { - return "", DiffStats{}, fmt.Errorf("failed to generate patch: %w", err) - } - - stats := DiffStats{} - for _, fileStat := range patch.Stats() { - stats.Additions += fileStat.Addition - stats.Removals += fileStat.Deletion - } - - return patch.String(), stats, nil -} - -func FormatDiff(diffText string, width int) (string, error) { - if isSplitDiffsAvailable() { - return formatWithSplitDiffs(diffText, width) - } - - return formatSimple(diffText), nil -} - -func isSplitDiffsAvailable() bool { - _, err := exec.LookPath("node") - return err == nil -} - -func formatWithSplitDiffs(diffText string, width int) (string, error) { - args := []string{ - "--color", - } - - var diffCmd *exec.Cmd - - if _, err := exec.LookPath("git-split-diffs-opencode"); err == nil { - fullArgs := append([]string{"git-split-diffs-opencode"}, args...) - diffCmd = exec.Command(fullArgs[0], fullArgs[1:]...) - } else { - npxArgs := append([]string{"git-split-diffs-opencode"}, args...) - diffCmd = exec.Command("npx", npxArgs...) - } - - diffCmd.Env = append(os.Environ(), fmt.Sprintf("DIFF_COLUMNS=%d", width)) - - diffCmd.Stdin = strings.NewReader(diffText) - - var out bytes.Buffer - diffCmd.Stdout = &out - - var stderr bytes.Buffer - diffCmd.Stderr = &stderr - - if err := diffCmd.Run(); err != nil { - return "", fmt.Errorf("git-split-diffs-opencode error: %w, stderr: %s", err, stderr.String()) - } - - return out.String(), nil -} - -func formatSimple(diffText string) string { - lines := strings.Split(diffText, "\n") - var result strings.Builder - - for _, line := range lines { - if len(line) == 0 { - result.WriteString("\n") - continue - } - - switch line[0] { - case '+': - result.WriteString("\033[32m" + line + "\033[0m\n") - case '-': - result.WriteString("\033[31m" + line + "\033[0m\n") - case '@': - result.WriteString("\033[36m" + line + "\033[0m\n") - case 'd': - if strings.HasPrefix(line, "diff --git") { - result.WriteString("\033[1m" + line + "\033[0m\n") - } else { - result.WriteString(line + "\n") - } - default: - result.WriteString(line + "\n") - } - } - - if !strings.HasSuffix(diffText, "\n") { - output := result.String() - return output[:len(output)-1] - } - - return result.String() -} |
