webui_commits.go

  1package web
  2
  3import (
  4	"math"
  5	"net/http"
  6	"strconv"
  7
  8	"github.com/charmbracelet/log/v2"
  9	"github.com/charmbracelet/soft-serve/git"
 10	"github.com/charmbracelet/soft-serve/pkg/config"
 11	"github.com/charmbracelet/soft-serve/pkg/proto"
 12	"github.com/gorilla/mux"
 13)
 14
 15// CommitsData contains data for rendering commit history.
 16type CommitsData struct {
 17	RepoBaseData
 18	PaginationData
 19	Ref     string
 20	Commits git.Commits
 21}
 22
 23// repoCommits handles commit history view.
 24func repoCommits(w http.ResponseWriter, r *http.Request) {
 25	ctx := r.Context()
 26	logger := log.FromContext(ctx)
 27	cfg := config.FromContext(ctx)
 28	repo := proto.RepositoryFromContext(ctx)
 29	if repo == nil {
 30		renderNotFound(w, r)
 31		return
 32	}
 33	vars := mux.Vars(r)
 34	ref := vars["ref"]
 35
 36	gr, err := openRepository(repo)
 37	if err != nil {
 38		logger.Debug("failed to open repository", "repo", repo.Name(), "err", err)
 39		renderInternalServerError(w, r)
 40		return
 41	}
 42
 43	refObj, _, err := resolveAndBuildRef(gr, ref)
 44	if err != nil {
 45		logger.Debug("failed to resolve ref or commit", "repo", repo.Name(), "ref", ref, "err", err)
 46		renderNotFound(w, r)
 47		return
 48	}
 49
 50	page := 1
 51	if pageStr := r.URL.Query().Get("page"); pageStr != "" {
 52		if p, err := strconv.Atoi(pageStr); err == nil && p > 0 {
 53			page = p
 54		}
 55	}
 56
 57	totalCommits, err := gr.CountCommits(refObj)
 58	if err != nil {
 59		logger.Debug("failed to count commits", "repo", repo.Name(), "ref", ref, "err", err)
 60		renderNotFound(w, r)
 61		return
 62	}
 63
 64	totalPages := int(math.Ceil(float64(totalCommits) / float64(defaultCommitsPerPage)))
 65	if totalPages < 1 {
 66		totalPages = 1
 67	}
 68
 69	if page > totalPages {
 70		page = totalPages
 71	}
 72	if page < 1 {
 73		page = 1
 74	}
 75
 76	commits, err := gr.CommitsByPage(refObj, page, defaultCommitsPerPage)
 77	if err != nil {
 78		logger.Debug("failed to get commits", "repo", repo.Name(), "ref", ref, "err", err)
 79		renderNotFound(w, r)
 80		return
 81	}
 82
 83	defaultBranch := getDefaultBranch(gr)
 84
 85	repoDisplayName := repo.ProjectName()
 86	if repoDisplayName == "" {
 87		repoDisplayName = repo.Name()
 88	}
 89
 90	data := CommitsData{
 91		RepoBaseData: RepoBaseData{
 92			BaseData: BaseData{
 93				ServerName: cfg.Name,
 94				ActiveTab:  "commits",
 95				Title:      "Commits in " + ref + " | " + repoDisplayName,
 96			},
 97			Repo:          repo,
 98			DefaultBranch: defaultBranch,
 99		},
100		PaginationData: PaginationData{
101			Page:        page,
102			TotalPages:  totalPages,
103			HasPrevPage: page > 1,
104			HasNextPage: page < totalPages,
105		},
106		Ref:     ref,
107		Commits: commits,
108	}
109
110	renderHTML(w, "commits.html", data)
111}