webui_commit.go

  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 + " | " + repoDisplayName + "@" + shortHash,
 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}