1package web
2
3import (
4 "net/http"
5
6 "github.com/charmbracelet/log/v2"
7 "github.com/charmbracelet/soft-serve/git"
8 "github.com/charmbracelet/soft-serve/pkg/config"
9 "github.com/charmbracelet/soft-serve/pkg/proto"
10 "github.com/gorilla/mux"
11)
12
13// CommitData contains data for rendering individual commit view.
14type CommitData struct {
15 RepoBaseData
16 Commit *git.Commit
17 Diff *git.Diff
18 ParentIDs []string
19}
20
21func repoCommit(w http.ResponseWriter, r *http.Request) {
22 ctx := r.Context()
23 logger := log.FromContext(ctx)
24 cfg := config.FromContext(ctx)
25 repo := proto.RepositoryFromContext(ctx)
26 vars := mux.Vars(r)
27 hash := vars["hash"]
28
29 gr, err := openRepository(repo)
30 if err != nil {
31 logger.Debug("failed to open repository", "repo", repo.Name(), "err", err)
32 renderInternalServerError(w, r)
33 return
34 }
35
36 commit, err := gr.CatFileCommit(hash)
37 if err != nil {
38 logger.Debug("failed to get commit", "repo", repo.Name(), "hash", hash, "err", err)
39 renderNotFound(w, r)
40 return
41 }
42
43 diff, err := gr.Diff(commit)
44 if err != nil {
45 logger.Debug("failed to get diff", "repo", repo.Name(), "hash", hash, "err", err)
46 renderInternalServerError(w, r)
47 return
48 }
49
50 defaultBranch := getDefaultBranch(gr)
51
52 parentIDs := make([]string, commit.ParentsCount())
53 for i := 0; i < commit.ParentsCount(); i++ {
54 parentID, err := commit.ParentID(i)
55 if err == nil && parentID != nil {
56 parentIDs[i] = parentID.String()
57 }
58 }
59
60 data := CommitData{
61 RepoBaseData: RepoBaseData{
62 BaseData: BaseData{
63 ServerName: cfg.Name,
64 ActiveTab: "commits",
65 },
66 Repo: repo,
67 DefaultBranch: defaultBranch,
68 },
69 Commit: commit,
70 Diff: diff,
71 ParentIDs: parentIDs,
72 }
73
74 renderHTML(w, "commit.html", data)
75}
76
77func repoCommitPatch(w http.ResponseWriter, r *http.Request) {
78 ctx := r.Context()
79 logger := log.FromContext(ctx)
80 repo := proto.RepositoryFromContext(ctx)
81 vars := mux.Vars(r)
82 hash := vars["hash"]
83
84 gr, err := openRepository(repo)
85 if err != nil {
86 logger.Debug("failed to open repository", "repo", repo.Name(), "err", err)
87 renderInternalServerError(w, r)
88 return
89 }
90
91 _, err = gr.CatFileCommit(hash)
92 if err != nil {
93 logger.Debug("failed to get commit", "repo", repo.Name(), "hash", hash, "err", err)
94 renderNotFound(w, r)
95 return
96 }
97
98 w.Header().Set("Content-Type", "text/plain; charset=utf-8")
99 if err := gr.RawDiff(hash, git.RawDiffPatch, w); err != nil {
100 logger.Debug("failed to generate patch", "repo", repo.Name(), "hash", hash, "err", err)
101 }
102}
103
104func repoCommitDiff(w http.ResponseWriter, r *http.Request) {
105 ctx := r.Context()
106 logger := log.FromContext(ctx)
107 repo := proto.RepositoryFromContext(ctx)
108 vars := mux.Vars(r)
109 hash := vars["hash"]
110
111 gr, err := openRepository(repo)
112 if err != nil {
113 logger.Debug("failed to open repository", "repo", repo.Name(), "err", err)
114 renderInternalServerError(w, r)
115 return
116 }
117
118 _, err = gr.CatFileCommit(hash)
119 if err != nil {
120 logger.Debug("failed to get commit", "repo", repo.Name(), "hash", hash, "err", err)
121 renderNotFound(w, r)
122 return
123 }
124
125 w.Header().Set("Content-Type", "text/plain; charset=utf-8")
126 if err := gr.RawDiff(hash, git.RawDiffNormal, w); err != nil {
127 logger.Debug("failed to generate diff", "repo", repo.Name(), "hash", hash, "err", err)
128 }
129}