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