forked from
tangled.org/core
Monorepo for Tangled — https://tangled.org
1package xrpc
2
3import (
4 "fmt"
5 "net/http"
6
7 "github.com/bluekeyes/go-gitdiff/gitdiff"
8 "tangled.org/core/knotserver/git"
9 "tangled.org/core/types"
10 xrpcerr "tangled.org/core/xrpc/errors"
11)
12
13func (x *Xrpc) RepoCompare(w http.ResponseWriter, r *http.Request) {
14 repo := r.URL.Query().Get("repo")
15 repoPath, err := x.parseRepoParam(repo)
16 if err != nil {
17 writeError(w, err.(xrpcerr.XrpcError), http.StatusBadRequest)
18 return
19 }
20
21 rev1 := r.URL.Query().Get("rev1")
22 if rev1 == "" {
23 writeError(w, xrpcerr.NewXrpcError(
24 xrpcerr.WithTag("InvalidRequest"),
25 xrpcerr.WithMessage("missing rev1 parameter"),
26 ), http.StatusBadRequest)
27 return
28 }
29
30 rev2 := r.URL.Query().Get("rev2")
31 if rev2 == "" {
32 writeError(w, xrpcerr.NewXrpcError(
33 xrpcerr.WithTag("InvalidRequest"),
34 xrpcerr.WithMessage("missing rev2 parameter"),
35 ), http.StatusBadRequest)
36 return
37 }
38
39 gr, err := git.PlainOpen(repoPath)
40 if err != nil {
41 writeError(w, xrpcerr.RepoNotFoundError, http.StatusNoContent)
42 return
43 }
44
45 commit1, err := gr.ResolveRevision(rev1)
46 if err != nil {
47 x.Logger.Error("error resolving revision 1", "msg", err.Error())
48 writeError(w, xrpcerr.NewXrpcError(
49 xrpcerr.WithTag("RevisionNotFound"),
50 xrpcerr.WithMessage(fmt.Sprintf("error resolving revision %s", rev1)),
51 ), http.StatusBadRequest)
52 return
53 }
54
55 commit2, err := gr.ResolveRevision(rev2)
56 if err != nil {
57 x.Logger.Error("error resolving revision 2", "msg", err.Error())
58 writeError(w, xrpcerr.NewXrpcError(
59 xrpcerr.WithTag("RevisionNotFound"),
60 xrpcerr.WithMessage(fmt.Sprintf("error resolving revision %s", rev2)),
61 ), http.StatusBadRequest)
62 return
63 }
64
65 rawPatch, formatPatch, err := gr.FormatPatch(commit1, commit2)
66 if err != nil {
67 x.Logger.Error("error comparing revisions", "msg", err.Error())
68 writeError(w, xrpcerr.NewXrpcError(
69 xrpcerr.WithTag("CompareError"),
70 xrpcerr.WithMessage("error comparing revisions"),
71 ), http.StatusBadRequest)
72 return
73 }
74
75 var combinedPatch []*gitdiff.File
76 var combinedPatchRaw string
77 // we need the combined patch
78 if len(formatPatch) >= 2 {
79 diffTree, err := gr.DiffTree(commit1, commit2)
80 if err != nil {
81 x.Logger.Error("error comparing revisions", "msg", err.Error())
82 } else {
83 combinedPatch = diffTree.Diff
84 combinedPatchRaw = diffTree.Patch
85 }
86 }
87
88 response := types.RepoFormatPatchResponse{
89 Rev1: commit1.Hash.String(),
90 Rev2: commit2.Hash.String(),
91 FormatPatch: formatPatch,
92 FormatPatchRaw: rawPatch,
93 CombinedPatch: combinedPatch,
94 CombinedPatchRaw: combinedPatchRaw,
95 }
96
97 writeJson(w, response)
98}