repos / git-pr

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

commit
2b627eb
parent
700dd4e
author
Eric Bower
date
2024-10-22 21:18:09 -0400 EDT
style: pr detail
2 files changed,  +76, -18
M web.go
M tmpl/patchset.html
+32, -13
 1@@ -6,23 +6,33 @@
 2         Patchset <code>ps-{{.Patchset.ID}}</code>
 3       </h2>
 4 
 5-      {{range .Patches}}
 6-        <div class="group">
 7+      {{range $patch := .Patches}}
 8+        <div class="box group">
 9           <div>
10             <h3 class="text-lg transform-none m-0 p-0 mb">
11-              {{if .Review}}<code class="pill-review">REVIEW</code>{{end}}
12-              <a href="#{{.Url}}">{{.Title}}</a>
13+              {{if $patch.Review}}<code class="pill-review">REVIEW</code>{{end}}
14+              <a href="#{{$patch.Url}}">{{$patch.Title}}</a>
15             </h3>
16 
17-            <div class="group-h text-sm">
18-              <code class="pill{{if .Review}}-review{{end}}">{{.AuthorName}} &lt;{{.AuthorEmail}}&gt;</code>
19-              <date>{{.FormattedAuthorDate}}</date>
20+            <div class="group-h text-sm justify-between">
21+              <div class="flex-1">
22+                <code class="pill{{if $patch.Review}}-review{{end}}">{{$patch.AuthorName}} &lt;{{$patch.AuthorEmail}}&gt;</code>
23+              </div>
24+              <date>{{$patch.FormattedAuthorDate}}</date>
25             </div>
26           </div>
27 
28-          {{if .Body}}<pre class="m-0">{{.Body}}</pre>{{end}}
29+          {{if $patch.Body}}<pre class="m-0">{{$patch.Body}}</pre>{{end}}
30 
31-          {{if .BodyAppendix}}<pre class="m-0">{{.BodyAppendix}}</pre>{{end}}
32+          {{range $patch.PatchFiles}}
33+            <div class="flex justify-between">
34+              <a class="flex-1" href="#patch-{{$patch.ID}}-{{.NewName}}">{{.NewName}}</a>
35+              <div class="flex gap">
36+                <code class="pill-success">+{{.Adds}}</code>
37+                <code class="pill-admin">-{{.Dels}}</code>
38+              </div>
39+            </div>
40+          {{end}}
41         </div>
42       {{else}}
43         <div class="box">
44@@ -32,10 +42,19 @@
45     </div>
46 
47     <div class="flex-1">
48-      {{range .Patches}}
49-        <div id="{{.Url}}">
50-          <h3 class="text-lg transform-none"><a href="#{{.Url}}">{{.Title}}</a></h3>
51-          <div>{{.DiffStr}}</div>
52+      {{range $patch := .Patches}}
53+        <div id="{{$patch.Url}}">
54+          <h3 class="text-lg transform-none"><a href="#{{$patch.Url}}">{{$patch.Title}}</a></h3>
55+          {{range $patch.PatchFiles}}
56+            <div class="group-h" id="patch-{{$patch.ID}}-{{.NewName}}">
57+              <a href="#patch-{{$patch.ID}}-{{.NewName}}">{{.NewName}}</a>
58+              <div class="flex gap">
59+                <code class="pill-success">+{{.Adds}}</code>
60+                <code class="pill-admin">-{{.Dels}}</code>
61+              </div>
62+            </div>
63+            <div>{{.DiffText}}</div>
64+          {{end}}
65         </div>
66       {{else}}
67         <div class="box">
M web.go
+44, -5
 1@@ -23,6 +23,7 @@ import (
 2 	formatterHtml "github.com/alecthomas/chroma/v2/formatters/html"
 3 	"github.com/alecthomas/chroma/v2/lexers"
 4 	"github.com/alecthomas/chroma/v2/styles"
 5+	"github.com/bluekeyes/go-gitdiff/gitdiff"
 6 	"github.com/gorilla/feeds"
 7 )
 8 
 9@@ -415,10 +416,18 @@ type PrData struct {
10 	Status string
11 }
12 
13+type PatchFile struct {
14+	*gitdiff.File
15+	Adds     int64
16+	Dels     int64
17+	DiffText template.HTML
18+}
19+
20 type PatchData struct {
21 	*Patch
22+	PatchFiles          []*PatchFile
23+	PatchHeader         *gitdiff.PatchHeader
24 	Url                 template.URL
25-	DiffStr             template.HTML
26 	Review              bool
27 	FormattedAuthorDate string
28 }
29@@ -566,23 +575,54 @@ func createPrDetail(page string) http.HandlerFunc {
30 			}
31 
32 			for _, patch := range patches {
33-				timestamp := patch.AuthorDate.Format(web.Backend.Cfg.TimeFormat)
34-				diffStr, err := parseText(web.Formatter, web.Theme, patch.RawText)
35+				diffFiles, preamble, err := ParsePatch(patch.RawText)
36+				if err != nil {
37+					web.Logger.Error("cannot parse patch", "err", err)
38+					w.WriteHeader(http.StatusUnprocessableEntity)
39+					return
40+				}
41+				header, err := gitdiff.ParsePatchHeader(preamble)
42 				if err != nil {
43 					web.Logger.Error("cannot parse patch", "err", err)
44 					w.WriteHeader(http.StatusUnprocessableEntity)
45 					return
46 				}
47 
48+				patchFiles := []*PatchFile{}
49+				for _, file := range diffFiles {
50+					var adds int64 = 0
51+					var dels int64 = 0
52+					for _, frag := range file.TextFragments {
53+						adds += frag.LinesAdded
54+						dels += frag.LinesDeleted
55+					}
56+
57+					diffStr, err := parseText(web.Formatter, web.Theme, file.String())
58+					if err != nil {
59+						web.Logger.Error("cannot parse patch", "err", err)
60+						w.WriteHeader(http.StatusUnprocessableEntity)
61+						return
62+					}
63+
64+					patchFiles = append(patchFiles, &PatchFile{
65+						File:     file,
66+						Adds:     adds,
67+						Dels:     dels,
68+						DiffText: template.HTML(diffStr),
69+					})
70+				}
71+
72 				// highlight review
73 				isReview := false
74 
75+				timestamp := patch.AuthorDate.Format(web.Backend.Cfg.TimeFormat)
76 				patchesData = append(patchesData, PatchData{
77 					Patch:               patch,
78 					Url:                 template.URL(fmt.Sprintf("patch-%d", patch.ID)),
79-					DiffStr:             template.HTML(diffStr),
80 					Review:              isReview,
81 					FormattedAuthorDate: timestamp,
82+					PatchFiles:          patchFiles,
83+					PatchHeader:         header,
84 				})
85 			}
86 		}
87@@ -646,7 +686,6 @@ func createPrDetail(page string) http.HandlerFunc {
88 			})
89 		}
90 
91-		fmt.Println("PSSPSPSPS", ps)
92 		err = tmpl.Execute(w, PrDetailData{
93 			Page: "pr",
94 			Repo: LinkData{