Commit template is halfway through

This commit is contained in:
Miguel de la Cruz 2024-06-30 12:09:40 +02:00
parent 5cd7dd9dbb
commit 2282cdecfd
6 changed files with 117 additions and 35 deletions

View file

@ -9,7 +9,7 @@ Project heavily inspired by the amazing
- [X] Embed templates mechanism.
- [ ] Embed style.css
- [ ] Correctly manage relative links.
- [X] Correctly manage relative links.
- [ ] Add a base url to avoid relative links if provided.
- [X] Generate the index html file for the `index` subcommand.
- [X] Generate the log html file for a repository.
@ -23,6 +23,8 @@ Project heavily inspired by the amazing
- [ ] Take binary files into account.
- [ ] Limit the output for large diffs. Add a "X commits remaining"
message if necessary.
- [ ] Generate files in temporal directory and replace the final one
when everything is ready.
- [X] Allow to anchor lines.
- [ ] Check if the templates exist on a location and use them if
so. Allow to change that location through CLI flags or env vars.

View file

@ -9,6 +9,7 @@ import (
"os"
"path/filepath"
"strings"
"time"
"github.com/alecthomas/kong"
"github.com/go-git/go-git/v5"
@ -19,7 +20,7 @@ type RepoDir struct {
Name string
Description string
Owner string
LastCommit string
LastCommit time.Time
}
// ToDo: replace has* with the filename, as it can be bare or .md
@ -41,11 +42,13 @@ type CommitFile struct {
Size int64
}
type CommitLog struct {
type CommitInfo struct {
Hash string
Date string
ParentHash string
Date time.Time
Msg string
Author string
AuthorName string
AuthorEmail string
Files int
Adds int
Dels int
@ -53,7 +56,8 @@ type CommitLog struct {
//go:embed templates
var embedTmpl embed.FS
var timeFormat = "2006-01-02 15:04"
var timeShortFormatStr = "2006-01-02 15:04"
var timeLongFormatStr = time.RFC1123
var funcMap = template.FuncMap{
"inc": func(i int) int {
return i + 1
@ -77,10 +81,17 @@ var funcMap = template.FuncMap{
return template.HTML(menu)
},
"firstLine": func(msg string) string {
return strings.Split(msg, "\n")[0]
},
"timeShortFormat": func(t time.Time) string {
return t.Format(timeShortFormatStr)
},
"timeLongFormat": func(t time.Time) string {
return t.Format(timeLongFormatStr)
},
}
// ToDo: add a map function to generate the menu
func executeTemplate(name string, data any) ([]byte, error) {
path := filepath.Join("templates", fmt.Sprintf("%s.html.tmpl", name))
b, err := embedTmpl.ReadFile(path)
@ -181,7 +192,7 @@ func generateIndex(args []string) error {
if err != nil {
return fmt.Errorf("cannot get commit %q for repository %q: %w", head.Hash(), dirname, err)
}
repoDir.LastCommit = c.Author.When.Format(timeFormat)
repoDir.LastCommit = c.Author.When
repoDirs = append(repoDirs, repoDir)
}
@ -212,7 +223,7 @@ func generateRepo(path string) error {
return fmt.Errorf("cannot delete directory for %q: %w", repoInfo.Name, err)
}
}
if err := os.Mkdir(repoInfo.Name, 0755); err != nil {
if err := os.MkdirAll(filepath.Join(repoInfo.Name, "commit"), 0755); err != nil {
return fmt.Errorf("cannot create directory for %q: %w", repoInfo.Name, err)
}
@ -323,9 +334,9 @@ func generateRepo(path string) error {
return fmt.Errorf("cannot get git log for repository: %w", err)
}
loglines := []*CommitLog{}
commits := []*CommitInfo{}
ciErr := cIter.ForEach(func(c *object.Commit) error {
slog.Debug("Processing log commit", "hash", c.Hash)
slog.Debug("Processing commit", "hash", c.Hash)
// ToDo: is this the best way to get the number of files?
fstats, err := c.Stats()
@ -333,29 +344,41 @@ func generateRepo(path string) error {
return fmt.Errorf("cannot get commit stats %s: %w", c.Hash, err)
}
commitLog := &CommitLog{
commit := &CommitInfo{
Hash: c.Hash.String(),
Date: c.Author.When.Format(timeFormat), // ToDo: author when vs commiter when?
Msg: strings.Split(c.Message, "\n")[0],
Author: c.Author.Name,
Date: c.Author.When, // ToDo: author when vs commiter when?
Msg: c.Message,
AuthorName: c.Author.Name,
AuthorEmail: c.Author.Email,
Files: len(fstats),
}
if parent, _ := c.Parent(0); parent != nil {
commit.ParentHash = parent.Hash.String()
}
// ToDo: are there not global commit stats?
for _, fstat := range fstats {
commitLog.Adds += fstat.Addition
commitLog.Dels += fstat.Deletion
commit.Adds += fstat.Addition
commit.Dels += fstat.Deletion
}
loglines = append(loglines, commitLog)
commits = append(commits, commit)
// generate commit file
data := map[string]any{"repoInfo": repoInfo, "commit": commit, "relpath": "../"}
dstpath := filepath.Join(repoInfo.Name, "commit", fmt.Sprintf("%s.html", commit.Hash))
if err := executeTemplateToFile("commit", data, dstpath); err != nil {
return fmt.Errorf("cannot execute template %q to file %q: %w", "commit", dstpath, err)
}
return nil
})
if ciErr != nil {
return fmt.Errorf("error while processing log: %w", iErr)
return fmt.Errorf("error while processing log: %w", ciErr)
}
logData := map[string]any{"repoInfo": repoInfo, "loglines": loglines, "relpath": ""}
logData := map[string]any{"repoInfo": repoInfo, "commits": commits, "relpath": ""}
logDstpath := filepath.Join(repoInfo.Name, "log.html")
if err := executeTemplateToFile("log", logData, logDstpath); err != nil {
return fmt.Errorf("cannot execute template %q to file %q: %w", "file", logDstpath, err)

View file

@ -0,0 +1,57 @@
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>{{.commit.Msg}} - {{.repoInfo.Name}} - {{.repoInfo.Description}}
</title>
<link rel="icon" type="image/png" href="{{.relpath}}favicon.png" />
<link rel="alternate" type="application/atom+xml" title="stagit Atom Feed" href="{{.relpath}}atom.xml" />
<link rel="alternate" type="application/atom+xml" title="stagit Atom Feed (tags)" href="{{.relpath}}tags.xml" />
<link rel="stylesheet" type="text/css" href="{{.relpath}}style.css" />
</head>
<body>
<table>
<tr>
<td><a href="{{.relpath}}../"><img src="{{.relpath}}logo.png" alt="" width="32" height="32" /></a></td>
<td><h1>{{.repoInfo.Name}}</h1><span class="desc">{{.repoInfo.Description}}</span></td>
</tr>
<tr class="url">
<td></td>
<td>
{{if ne .repoInfo.Url ""}}
git clone <a href="{{.repoInfo.Url}}">{{.repoInfo.Url}}</a>
{{end}}
</td>
</tr>
<tr>
<td></td>
<td>
{{menu .repoInfo .relpath}}
</td>
</tr>
</table>
<hr/>
<div id="content">
<pre><b>commit</b> <a href="{{.relpath}}commit/{{.commit.Hash}}.html">{{.commit.Hash}}</a>
<b>parent</b> <a href="{{.relpath}}commit/{{.commit.ParentHash}}.html">{{.commit.ParentHash}}</a>
<b>Author:</b> {{.commit.AuthorName}} &lt;<a href="mailto:{{.commit.AuthorEmail}}">{{.commit.AuthorEmail}}</a>&gt;
<b>Date:</b> {{timeLongFormat .commit.Date}}
{{.commit.Msg}}
<b>Diffstat:</b>
<table><tr><td class="M">M</td><td><a href="#h0">LICENSE</a></td><td> | </td><td class="num">2</td><td><span class="i">+</span><span class="d">-</span></td></tr></table></pre>
<pre>1 file changed, 1 insertion(+), 1 deletion(-)
<hr/><b>diff --git a/<a id="h0" href="../file/LICENSE.html">LICENSE</a> b/<a href="../file/LICENSE.html">LICENSE</a></b>
<a href="#h0-0" id="h0-0" class="h">@@ -1,6 +1,6 @@
</a> MIT/X Consortium License
<a href="#h0-0-2" id="h0-0-2" class="d">-(c) 2015-2022 Hiltjo Posthuma &lt;hiltjo@codemadness.org&gt;
</a><a href="#h0-0-3" id="h0-0-3" class="i">+(c) 2015-2024 Hiltjo Posthuma &lt;hiltjo@codemadness.org&gt;
</a>
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the &quot;Software&quot;),
</pre>
</div>
</body>
</html>

View file

@ -41,13 +41,13 @@
</tr>
</thead>
<tbody>
{{range .files}}
{{- range .files}}
<tr>
<td>{{.Mode}}</td>
<td><a href="{{.Path}}">{{.Name}}</a></td>
<td class="num" align="right">{{if .IsBinary}}{{.Size}}B{{else}}{{.Lines}}L{{end}}</td>
</tr>
{{end}}
{{- end}}
</tbody>
</table>
</div>

View file

@ -28,7 +28,7 @@
<td><a href="{{.Name}}/log.html">{{.Name}}</a></td>
<td>{{.Description}}</td>
<td>{{.Owner}}</td>
<td>{{.LastCommit}}</td>
<td>{{timeShortFormat .LastCommit}}</td>
</tr>
{{- end}}
</tbody>

View file

@ -44,11 +44,11 @@
</tr>
</thead>
<tbody>
{{- range .loglines}}
{{- range .commits}}
<tr>
<td>{{.Date}}</td>
<td><a href="commit/{{.Hash}}.html">{{.Msg}}</a></td>
<td>{{.Author}}</td>
<td>{{timeShortFormat .Date}}</td>
<td><a href="commit/{{.Hash}}.html">{{firstLine .Msg}}</a></td>
<td>{{.AuthorName}}</td>
<td class="num" align="right">{{.Files}}</td>
<td class="num" align="right">+{{.Adds}}</td>
<td class="num" align="right">-{{.Dels}}</td>