From e1357392b20ae02ac1748508cae667c09bdf09ab Mon Sep 17 00:00:00 2001 From: Anirudh Oppiliappan Date: Wed, 16 Apr 2025 14:48:38 +0300 Subject: [PATCH] knotserver: git: format-patch for ref comparisons --- knotserver/git/diff.go | 31 +++++++++++++++++++++++++++++++ knotserver/routes.go | 9 +++++++-- 2 files changed, 38 insertions(+), 2 deletions(-) diff --git a/knotserver/git/diff.go b/knotserver/git/diff.go index 3ee87b9..dffa54c 100644 --- a/knotserver/git/diff.go +++ b/knotserver/git/diff.go @@ -1,13 +1,17 @@ package git import ( + "bytes" "fmt" "log" + "os" + "os/exec" "strings" "github.com/bluekeyes/go-gitdiff/gitdiff" "github.com/go-git/go-git/v5/plumbing" "github.com/go-git/go-git/v5/plumbing/object" + "tangled.sh/tangled.sh/core/patchutil" "tangled.sh/tangled.sh/core/types" ) @@ -120,6 +124,33 @@ func (g *GitRepo) DiffTree(commit1, commit2 *object.Commit) (*types.DiffTree, er }, nil } +// FormatPatch generates a git-format-patch output between two commits, +// and returns the raw format-patch series, a parsed FormatPatch and an error. +func (g *GitRepo) FormatPatch(base, commit2 *object.Commit) (string, []patchutil.FormatPatch, error) { + var stdout bytes.Buffer + cmd := exec.Command( + "git", + "-C", + g.path, + "format-patch", + fmt.Sprintf("%s..%s", base.Hash.String(), commit2.Hash.String()), + "--stdout", + ) + cmd.Stdout = &stdout + cmd.Stderr = os.Stderr + err := cmd.Run() + if err != nil { + return "", nil, err + } + + formatPatch, err := patchutil.ExtractPatches(stdout.String()) + if err != nil { + return "", nil, err + } + + return stdout.String(), formatPatch, nil +} + func (g *GitRepo) MergeBase(commit1, commit2 *object.Commit) (*object.Commit, error) { isAncestor, err := commit1.IsAncestor(commit2) if err != nil { diff --git a/knotserver/routes.go b/knotserver/routes.go index 33408b0..9b6cd47 100644 --- a/knotserver/routes.go +++ b/knotserver/routes.go @@ -808,14 +808,19 @@ func (h *Handle) Compare(w http.ResponseWriter, r *http.Request) { return } - difftree, err := gr.DiffTree(mergeBase, commit2) + rawPatch, formatPatch, err := gr.FormatPatch(mergeBase, commit2) if err != nil { l.Error("error comparing revisions", "msg", err.Error()) writeError(w, "error comparing revisions", http.StatusBadRequest) return } - writeJSON(w, types.RepoDiffTreeResponse{difftree}) + writeJSON(w, types.RepoFormatPatchResponse{ + Rev1: commit1.Hash.String(), + Rev2: commit2.Hash.String(), + FormatPatch: formatPatch, + Patch: rawPatch, + }) return } -- 2.54.0