repos / git-pr

a self-hosted git collaboration server
git clone https://github.com/picosh/git-pr.git

commit
cc93308
parent
d231dbd
author
Eric Bower
date
2024-05-21 15:59:46 -0400 EDT
chore: cleanup web viewer
3 files changed,  +85, -10
M pr.go
M web.go
M pr.go
+16, -0
 1@@ -11,6 +11,7 @@ import (
 2 
 3 type GitPatchRequest interface {
 4 	GetRepos() ([]Repo, error)
 5+	GetRepoByID(repoID string) (*Repo, error)
 6 	SubmitPatchRequest(pubkey string, repoID string, patches io.Reader) (*PatchRequest, error)
 7 	SubmitPatch(pubkey string, prID int64, review bool, patch io.Reader) (*Patch, error)
 8 	GetPatchRequestByID(prID int64) (*PatchRequest, error)
 9@@ -31,6 +32,21 @@ func (pr PrCmd) GetRepos() ([]Repo, error) {
10 	return pr.Backend.Cfg.Repos, nil
11 }
12 
13+func (pr PrCmd) GetRepoByID(repoID string) (*Repo, error) {
14+	repos, err := pr.GetRepos()
15+	if err != nil {
16+		return nil, err
17+	}
18+
19+	for _, repo := range repos {
20+		if repo.ID == repoID {
21+			return &repo, nil
22+		}
23+	}
24+
25+	return nil, fmt.Errorf("repo not found: %s", repoID)
26+}
27+
28 func (pr PrCmd) GetPatchesByPrID(prID int64) ([]*Patch, error) {
29 	patches := []*Patch{}
30 	err := pr.Backend.DB.Select(
M util.go
+4, -0
 1@@ -11,6 +11,10 @@ import (
 2 	"github.com/charmbracelet/ssh"
 3 )
 4 
 5+func truncateSha(sha string) string {
 6+	return sha[:7]
 7+}
 8+
 9 func getAuthorizedKeys(path string) ([]ssh.PublicKey, error) {
10 	keys := []ssh.PublicKey{}
11 	f, err := os.Open(path)
M web.go
+65, -10
  1@@ -89,7 +89,7 @@ func repoListHandler(w http.ResponseWriter, r *http.Request) {
  2 		return
  3 	}
  4 
  5-	str := `<h1 class="text-2xl">Repos</h1>`
  6+	str := `<h1 class="text-2xl">repos</h1>`
  7 	repos, err := web.Pr.GetRepos()
  8 	if err != nil {
  9 		web.Pr.Backend.Logger.Error("cannot get repos", "err", err)
 10@@ -118,7 +118,7 @@ func repoListHandler(w http.ResponseWriter, r *http.Request) {
 11 	}
 12 }
 13 
 14-func prListHandler(w http.ResponseWriter, r *http.Request) {
 15+func repoHandler(w http.ResponseWriter, r *http.Request) {
 16 	repoID := r.PathValue("id")
 17 
 18 	web, err := getWebCtx(r)
 19@@ -128,14 +128,30 @@ func prListHandler(w http.ResponseWriter, r *http.Request) {
 20 		return
 21 	}
 22 
 23-	str := `<h1 class="text-2xl">Patch Requests</h1>`
 24+	repo, err := web.Pr.GetRepoByID(repoID)
 25+	if err != nil {
 26+		web.Logger.Error("fetch repo", "err", err)
 27+		w.WriteHeader(http.StatusInternalServerError)
 28+		return
 29+	}
 30+
 31+	str := fmt.Sprintf(`<h1 class="text-2xl"><a href="/">repos</a> / %s</h1>`, repo.ID)
 32+	str += `<div class="group">`
 33+	str += fmt.Sprintf(`<div><code>git clone %s</code></div>`, repo.CloneAddr)
 34+	str += fmt.Sprintf(`<div>Submit patch request: <code>git format-patch --stdout | ssh pr.pico.sh pr create %s</code></div>`, repo.ID)
 35+	str += `<div class="group"></div>`
 36+
 37 	prs, err := web.Pr.GetPatchRequestsByRepoID(repoID)
 38 	if err != nil {
 39-		web.Pr.Backend.Logger.Error("cannot get prs", "err", err)
 40+		web.Logger.Error("cannot get prs", "err", err)
 41 		w.WriteHeader(http.StatusInternalServerError)
 42 		return
 43 	}
 44 
 45+	if len(prs) == 0 {
 46+		str += "No PRs found for repo"
 47+	}
 48+
 49 	for _, curpr := range prs {
 50 		row := `
 51 <div class="group-h">
 52@@ -163,14 +179,16 @@ func prListHandler(w http.ResponseWriter, r *http.Request) {
 53 	}
 54 }
 55 
 56-func header(pr *PatchRequest, page string) string {
 57-	str := fmt.Sprintf(`<h1 class="text-2xl">%s</h1>`, pr.Name)
 58+func header(repo *Repo, pr *PatchRequest, page string) string {
 59+	str := fmt.Sprintf(`<h1 class="text-2xl"><a href="/repos/%s">%s</a> / %s</h1>`, repo.ID, repo.ID, pr.Name)
 60 	str += fmt.Sprintf("<div>[%s] %s %s</div>", pr.Status, pr.CreatedAt.Format(time.DateTime), pr.Pubkey)
 61 	if page == "pr" {
 62 		str += fmt.Sprintf(`<div><strong>summary</strong> &middot; <a href="/prs/%d/patches">patches</a></div>`, pr.ID)
 63 	} else {
 64 		str += fmt.Sprintf(`<div><a href="/prs/%d">summary</a> &middot; <strong>patches</strong></div>`, pr.ID)
 65 	}
 66+
 67+	str += fmt.Sprintf(`<div>Submit change to patch: <code>git format-patch HEAD~1 --stdout | ssh pr.pico.sh pr add %d</code></div>`, pr.ID)
 68 	return str
 69 }
 70 
 71@@ -197,9 +215,39 @@ func prHandler(w http.ResponseWriter, r *http.Request) {
 72 		return
 73 	}
 74 
 75-	str := header(pr, "pr")
 76+	repo, err := web.Pr.GetRepoByID(pr.RepoID)
 77+	if err != nil {
 78+		web.Logger.Error("cannot get repo", "err", err)
 79+		w.WriteHeader(http.StatusInternalServerError)
 80+		return
 81+	}
 82+
 83+	str := header(repo, pr, "pr")
 84 	str += fmt.Sprintf("<p>%s</p>", pr.Text)
 85 
 86+	patches, err := web.Pr.GetPatchesByPrID(int64(prID))
 87+	if err != nil {
 88+		web.Logger.Error("cannot get patches", "err", err)
 89+		w.WriteHeader(http.StatusInternalServerError)
 90+		return
 91+	}
 92+
 93+	for _, patch := range patches {
 94+		reviewTxt := ""
 95+		if patch.Review {
 96+			reviewTxt = "[review]"
 97+		}
 98+		str += fmt.Sprintf(
 99+			"<div>%s\t%s\t%s\t%s <%s>\t%s\n</div>",
100+			reviewTxt,
101+			patch.Title,
102+			truncateSha(patch.CommitSha),
103+			patch.AuthorName,
104+			patch.AuthorEmail,
105+			patch.AuthorDate.Format(time.RFC3339Nano),
106+		)
107+	}
108+
109 	w.Header().Set("content-type", "text/html")
110 	tmpl := getTemplate()
111 	err = tmpl.Execute(w, TemplateData{
112@@ -234,7 +282,14 @@ func prPatchesHandler(w http.ResponseWriter, r *http.Request) {
113 		return
114 	}
115 
116-	str := header(pr, "patches")
117+	repo, err := web.Pr.GetRepoByID(pr.RepoID)
118+	if err != nil {
119+		web.Logger.Error("cannot get repo", "err", err)
120+		w.WriteHeader(http.StatusInternalServerError)
121+		return
122+	}
123+
124+	str := header(repo, pr, "patches")
125 
126 	patches, err := web.Pr.GetPatchesByPrID(int64(prID))
127 	if err != nil {
128@@ -259,7 +314,7 @@ func prPatchesHandler(w http.ResponseWriter, r *http.Request) {
129 <div>%s</div>`
130 		str += fmt.Sprintf(
131 			row,
132-			patch.Title, rev,
133+			rev, patch.Title,
134 			diffStr,
135 		)
136 	}
137@@ -334,7 +389,7 @@ func StartWebServer() {
138 	// GODEBUG=httpmuxgo121=0
139 	http.HandleFunc("GET /prs/{id}/patches", ctxMdw(ctx, prPatchesHandler))
140 	http.HandleFunc("GET /prs/{id}", ctxMdw(ctx, prHandler))
141-	http.HandleFunc("GET /repos/{id}", ctxMdw(ctx, prListHandler))
142+	http.HandleFunc("GET /repos/{id}", ctxMdw(ctx, repoHandler))
143 	http.HandleFunc("GET /", ctxMdw(ctx, repoListHandler))
144 	http.HandleFunc("GET /syntax.css", ctxMdw(ctx, chromaStyleHandler))
145