gshr
git static host repo -- generates static html for repos
git clone https://git.vogt.world/gshr.git
Log | Files | README.md | LICENSE
← Commit log
commit
message
Rough commit page rendering
author
Ben Vogt <[email protected]>
date
2023-04-04 00:15:55
stats
6 file(s) changed, 176 insertions(+), 23 deletions(-)
files
commit.template.html
file.template.html
files.template.html
gshr.css
log.template.html
main.go
  1diff --git a/commit.template.html b/commit.template.html
  2new file mode 100644
  3index 0000000..589c3b8
  4--- /dev/null
  5+++ b/commit.template.html
  6@@ -0,0 +1,85 @@
  7+<!DOCTYPE html>
  8+<html lang="en">
  9+
 10+<head>
 11+  <meta charset="utf-8">
 12+  <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
 13+  <meta name="viewport" content="width=device-width, initial-scale=1">
 14+  <meta http-equiv="X-UA-Compatible" content="IE=edge">
 15+  <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
 16+  <title>gshr</title>
 17+  <link rel="stylesheet" href="{{ .BaseURL }}gshr.css" type="text/css">
 18+  <meta name="description"
 19+        content="git static host repo">
 20+  <meta property="og:site_name" content="gshr">
 21+  <meta property="og:type" content="article">
 22+  <meta property="article:author" content="gshr">
 23+</head>
 24+
 25+<body>
 26+  <div class="content">
 27+    <div class="metadata">
 28+      <table>
 29+        <tbody>
 30+          <tr>
 31+            <td>
 32+              <h1>www</h1>
 33+              <span class="desc">
 34+                personal website hosted at https:://www.vogt.world/
 35+              </span>
 36+            </td>
 37+          </tr>
 38+          <tr>
 39+            <td>
 40+              git clone
 41+              <a href="[email protected]:./www.gitc">[email protected]:./www.git</a>
 42+            </td>
 43+          </tr>
 44+          <tr>
 45+            <td>
 46+              <a href="{{ .BaseURL }}log.html">Log</a>
 47+              |
 48+              <a href="{{ .BaseURL }}files.html">Files</a>
 49+            </td>
 50+          </tr>
 51+        </tbody>
 52+      </table>
 53+    </div>
 54+    <div class="commit-detail">
 55+      <table>
 56+        <tbody>
 57+          <tr>
 58+            <td><b>commit: </b></td>
 59+            <td><a href="{{ .BaseURL }}commit/{{ .Hash }}/">{{ .Hash }}</a></td>
 60+          </tr>
 61+          <tr>
 62+            <td><b>author: </b></td>
 63+            <td>{{ .Author }} &lt;{{ .AuthorEmail }}&gt;</td>
 64+          </tr>
 65+          <tr>
 66+            <td><b>date: </b></td>
 67+            <td> {{ .Date }}</td>
 68+          </tr>
 69+          <tr>
 70+            <td><b>message: </b></td>
 71+            <td> {{ .Message }}</td>
 72+          </tr>
 73+        </tbody>
 74+      </table>
 75+      <table>
 76+        <tbody>
 77+          <tr>
 78+            <td>
 79+              {{ .FileChangeCount }} file(s) changed,
 80+              {{ .LinesAdded }} insertions(+),
 81+              {{ .LinesDeleted }} deletions(-)
 82+            </td>
 83+          </tr>
 84+        </tbody>
 85+      </table>
 86+      <hr />
 87+    </div>
 88+  </div>
 89+</body>
 90+
 91+</html>
 92\ No newline at end of file
 93diff --git a/file.template.html b/file.template.html
 94index 5cc1d66..bebe396 100644
 95--- a/file.template.html
 96+++ b/file.template.html
 97@@ -37,9 +37,9 @@
 98           </tr>
 99           <tr>
100             <td>
101-              <a href="/log.html">Log</a>
102+              <a href="{{ .BaseURL }}log.html">Log</a>
103               |
104-              <a href="/files.html">Files</a>
105+              <a href="{{ .BaseURL }}files.html">Files</a>
106             </td>
107           </tr>
108         </tbody>
109diff --git a/files.template.html b/files.template.html
110index 14183cc..eff7d8e 100644
111--- a/files.template.html
112+++ b/files.template.html
113@@ -37,9 +37,9 @@
114           </tr>
115           <tr>
116             <td>
117-              <a href="/log.html">Log</a>
118+              <a href="{{ .BaseURL }}log.html">Log</a>
119               |
120-              <a href="/files.html">Files</a>
121+              <a href="{{ .BaseURL }}files.html">Files</a>
122             </td>
123           </tr>
124         </tbody>
125@@ -58,7 +58,7 @@
126           {{ range .Files }}
127           <tr>
128             <td>{{ .Mode }}</td>
129-            <td><a href="files/{{ .Name }}/index.html">{{ .Name }}</a></td>
130+            <td><a href="{{ .BaseURL }}files/{{ .Name }}/index.html">{{ .Name }}</a></td>
131             <td>{{ .Size }}</td>
132           </tr>
133           {{ end }}
134diff --git a/gshr.css b/gshr.css
135index d6629c5..ff70099 100644
136--- a/gshr.css
137+++ b/gshr.css
138@@ -1,6 +1,6 @@
139 :root {
140   /* Fonts */
141-  --mono-font: San Francisco Mono, Monaco, "Consolas", "Lucida Console", monospace;
142+  --mono-font: monospace;
143   --sans-font: -apple-system, BlinkMacSystemFont, "avenir next", avenir,
144     helvetica, "helvetica neue", ubuntu, roboto, noto, "segoe ui", arial,
145     sans-serif;
146@@ -210,7 +210,7 @@ div.content div.file {
147 
148 div.content pre {
149   overflow-x: auto;
150-  padding: 1em;
151+  padding: 0.4em;
152   border: solid 1px gainsboro;
153   border-radius: 4px;
154 }
155@@ -252,6 +252,7 @@ div.content div.log {
156 }
157 
158 div.content div.log table,
159+div.content div.commit-detail table,
160 div.content div.files table {
161   vertical-align: top;
162   white-space: nowrap;
163diff --git a/log.template.html b/log.template.html
164index fc325d5..12af107 100644
165--- a/log.template.html
166+++ b/log.template.html
167@@ -37,9 +37,9 @@
168           </tr>
169           <tr>
170             <td>
171-              <a href="/log.html">Log</a>
172+              <a href="{{ .BaseURL }}log.html">Log</a>
173               |
174-              <a href="/files.html">Files</a>
175+              <a href="{{ .BaseURL }}files.html">Files</a>
176             </td>
177           </tr>
178         </tbody>
179@@ -58,14 +58,16 @@
180           </tr>
181         </thead>
182         <tbody>
183-          {{ range .Commits }}
184+          {{ range $c := .Commits }}
185           <tr>
186-            <td>{{ .Date }}</td>
187-            <td class="commit"><a href="commit/{{ .Hash }}">{{ .Message }}</a></td>
188-            <td>{{ .Author }}</td>
189-            <td align="right">{{ .FileChangeCount }}</td>
190-            <td align="right">+{{ .LinesAdded }}</td>
191-            <td align="right">-{{ .LinesDeleted }}</td>
192+            <td>{{ $c.Date }}</td>
193+            <td class="commit">
194+              <a href="{{ .BaseURL }}commit/{{ $c.Hash }}">{{ $c.Message }}</a>
195+            </td>
196+            <td>{{ $c.Author }}</td>
197+            <td align="right">{{ $c.FileChangeCount }}</td>
198+            <td align="right">+{{ $c.LinesAdded }}</td>
199+            <td align="right">-{{ $c.LinesDeleted }}</td>
200           </tr>
201           {{ end }}
202         </tbody>
203diff --git a/main.go b/main.go
204index 71c387e..1c22143 100644
205--- a/main.go
206+++ b/main.go
207@@ -30,6 +30,9 @@ var filesTemplateHtml string
208 //go:embed log.template.html
209 var logTemplateHtml string
210 
211+//go:embed commit.template.html
212+var commitTemplateHtml string
213+
214 var (
215 	config Config
216 )
217@@ -117,6 +120,7 @@ func main() {
218 	debug("base-url = %v", config.BaseURL)
219 	r := CloneAndInfo()
220 	RenderLogPage(r)
221+	RenderAllCommitPages(r)
222 	RenderAllFilesPage()
223 	RenderSingleFilePages()
224 }
225@@ -171,6 +175,7 @@ func (f *TrackedFile) Render(t *template.Template) {
226 }
227 
228 type Commit struct {
229+	BaseURL         string
230 	Author          string
231 	Date            string
232 	Hash            string
233@@ -193,10 +198,11 @@ func (mi *LogPage) Render(t *template.Template) {
234 }
235 
236 type TrackedFileMetaData struct {
237-	Mode   string
238-	Name   string
239-	Size   string
240-	Origin string
241+	BaseURL string
242+	Mode    string
243+	Name    string
244+	Size    string
245+	Origin  string
246 }
247 
248 type FilesIndex struct {
249@@ -211,6 +217,27 @@ func (fi *FilesIndex) Render(t *template.Template) {
250 	checkErr(err)
251 }
252 
253+type CommitDetail struct {
254+	BaseURL         string
255+	Author          string
256+	AuthorEmail     string
257+	Date            string
258+	Hash            string
259+	Message         string
260+	FileChangeCount int
261+	LinesAdded      int
262+	LinesDeleted    int
263+}
264+
265+func (c *CommitDetail) Render(t *template.Template) {
266+	err := os.MkdirAll(path.Join(config.OutputDir, "commit", c.Hash), 0755)
267+	checkErr(err)
268+	output, err := os.Create(path.Join(config.OutputDir, "commit", c.Hash, "index.html"))
269+	checkErr(err)
270+	err = t.Execute(output, c)
271+	checkErr(err)
272+}
273+
274 func CloneAndInfo() *git.Repository {
275 	r, err := git.PlainClone(config.CloneDir, false, &git.CloneOptions{
276 		URL: config.Repo,
277@@ -219,6 +246,40 @@ func CloneAndInfo() *git.Repository {
278 	return r
279 }
280 
281+func RenderAllCommitPages(r *git.Repository) {
282+	t, err := template.New("commit").Parse(commitTemplateHtml)
283+	checkErr(err)
284+	ref, err := r.Head()
285+	checkErr(err)
286+	cIter, err := r.Log(&git.LogOptions{From: ref.Hash()})
287+	checkErr(err)
288+	err = cIter.ForEach(func(c *object.Commit) error {
289+		stats, err := c.Stats()
290+		added := 0
291+		deleted := 0
292+		for i := 0; i < len(stats); i++ {
293+			stat := stats[i]
294+			added += stat.Addition
295+			deleted += stat.Deletion
296+		}
297+		checkErr(err)
298+		commitDetail := CommitDetail{
299+			BaseURL:         config.BaseURL,
300+			Author:          c.Author.Name,
301+			AuthorEmail:     c.Author.Email,
302+			Message:         c.Message,
303+			Date:            c.Author.When.UTC().Format("2006-01-02 15:04:05"),
304+			Hash:            c.Hash.String(),
305+			FileChangeCount: len(stats),
306+			LinesAdded:      added,
307+			LinesDeleted:    deleted,
308+		}
309+		commitDetail.Render(t)
310+		return nil
311+	})
312+	checkErr(err)
313+}
314+
315 func RenderLogPage(r *git.Repository) {
316 	t, err := template.New("log").Parse(logTemplateHtml)
317 	checkErr(err)
318@@ -239,6 +300,7 @@ func RenderLogPage(r *git.Repository) {
319 		}
320 		checkErr(err)
321 		commits = append(commits, Commit{
322+			BaseURL:         config.BaseURL,
323 			Author:          c.Author.Name,
324 			Message:         c.Message,
325 			Date:            c.Author.When.UTC().Format("2006-01-02 15:04:05"),
326@@ -273,10 +335,11 @@ func RenderAllFilesPage() {
327 			Name, _ := strings.CutPrefix(filename, config.CloneDir)
328 			Name, _ = strings.CutPrefix(Name, "/")
329 			tf := TrackedFileMetaData{
330-				Origin: filename,
331-				Name:   Name,
332-				Mode:   info.Mode().String(),
333-				Size:   fmt.Sprintf("%v", info.Size()),
334+				BaseURL: config.BaseURL,
335+				Origin:  filename,
336+				Name:    Name,
337+				Mode:    info.Mode().String(),
338+				Size:    fmt.Sprintf("%v", info.Size()),
339 			}
340 			trackedFiles = append(trackedFiles, tf)
341 		}