I'm tired, is late, log works
This commit is contained in:
parent
809ab91837
commit
35ee56294b
4 changed files with 152 additions and 18 deletions
|
@ -21,7 +21,8 @@ Project heavily inspired by the amazing
|
|||
- [ ] Add a subcommand to dump the embedded templates so they can be
|
||||
modified.
|
||||
- [ ] Take binary files into account.
|
||||
- [ ] Limit the output for large diffs.
|
||||
- [ ] Limit the output for large diffs. Add a "X commits remaining"
|
||||
message if necessary.
|
||||
- [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.
|
||||
|
|
94
gitssg.go
94
gitssg.go
|
@ -9,7 +9,6 @@ import (
|
|||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/alecthomas/kong"
|
||||
"github.com/go-git/go-git/v5"
|
||||
|
@ -20,7 +19,7 @@ type RepoDir struct {
|
|||
Name string
|
||||
Description string
|
||||
Owner string
|
||||
LastCommit time.Time
|
||||
LastCommit string
|
||||
}
|
||||
|
||||
type RepoInfo struct {
|
||||
|
@ -33,15 +32,28 @@ type RepoInfo struct {
|
|||
}
|
||||
|
||||
type CommitFile struct {
|
||||
Mode string
|
||||
Path string
|
||||
Name string
|
||||
Lines int
|
||||
Mode string
|
||||
Path string
|
||||
Name string
|
||||
Lines int
|
||||
IsBinary bool
|
||||
Size int64
|
||||
}
|
||||
|
||||
type CommitLog struct {
|
||||
Hash string
|
||||
Date string
|
||||
Msg string
|
||||
Author string
|
||||
Files int
|
||||
Adds int
|
||||
Dels int
|
||||
}
|
||||
|
||||
//go:embed templates
|
||||
var embedTmpl embed.FS
|
||||
var funcMap = template.FuncMap{"inc": func(i int) int { return i + 1 }}
|
||||
var timeFormat = "2006-01-02 15:04"
|
||||
|
||||
// ToDo: add a map function to generate the menu
|
||||
|
||||
|
@ -128,7 +140,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
|
||||
repoDir.LastCommit = c.Author.When.Format(timeFormat)
|
||||
|
||||
repoDirs = append(repoDirs, repoDir)
|
||||
}
|
||||
|
@ -229,8 +241,10 @@ func generateRepo(path string) error {
|
|||
}
|
||||
data["isBinary"] = isBinary
|
||||
|
||||
var lines []string
|
||||
if !isBinary {
|
||||
lines, err := o.Lines()
|
||||
var err error
|
||||
lines, err = o.Lines()
|
||||
if err != nil {
|
||||
return fmt.Errorf("cannot get lines for %q: %w", o.Name, err)
|
||||
}
|
||||
|
@ -248,9 +262,12 @@ func generateRepo(path string) error {
|
|||
}
|
||||
|
||||
file := &CommitFile{
|
||||
Mode: o.Mode.String(), // ToDo: correctly calculate the mode string
|
||||
Path: filepath.Join("file", fmt.Sprintf("%s.html", o.Name)),
|
||||
Name: o.Name,
|
||||
Mode: o.Mode.String(), // ToDo: correctly calculate the mode string
|
||||
Path: filepath.Join("file", fmt.Sprintf("%s.html", o.Name)),
|
||||
Name: o.Name,
|
||||
Lines: len(lines),
|
||||
IsBinary: isBinary,
|
||||
Size: o.Size,
|
||||
}
|
||||
files = append(files, file)
|
||||
|
||||
|
@ -260,17 +277,66 @@ func generateRepo(path string) error {
|
|||
return fmt.Errorf("error while processing tree: %w", iErr)
|
||||
}
|
||||
|
||||
// generate the files index file
|
||||
// ToDo: bundle execute and write into a function
|
||||
data := map[string]any{"repoInfo": repoInfo, "files": files}
|
||||
contents, err := executeTemplate("files", data)
|
||||
filesData := map[string]any{"repoInfo": repoInfo, "files": files}
|
||||
filesContents, err := executeTemplate("files", filesData)
|
||||
if err != nil {
|
||||
return fmt.Errorf("cannot execute files template for repository %q: %w", repoInfo.Name, err)
|
||||
}
|
||||
|
||||
if err := os.WriteFile(filepath.Join(repoInfo.Name, "files.html"), contents, 0755); err != nil {
|
||||
if err := os.WriteFile(filepath.Join(repoInfo.Name, "files.html"), filesContents, 0755); err != nil {
|
||||
return fmt.Errorf("cannot write files contents to \"files.html\": %w", err)
|
||||
}
|
||||
|
||||
// generate the log file
|
||||
cIter, err := repo.Log(&git.LogOptions{All: true})
|
||||
if err != nil {
|
||||
return fmt.Errorf("cannot get git log for repository: %w", err)
|
||||
}
|
||||
|
||||
loglines := []*CommitLog{}
|
||||
ciErr := cIter.ForEach(func(c *object.Commit) error {
|
||||
slog.Debug("Processing log commit", "hash", c.Hash)
|
||||
|
||||
// ToDo: is this the best way to get the number of files?
|
||||
fstats, err := c.Stats()
|
||||
if err != nil {
|
||||
return fmt.Errorf("cannot get commit stats %s: %w", c.Hash, err)
|
||||
}
|
||||
|
||||
commitLog := &CommitLog{
|
||||
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,
|
||||
Files: len(fstats),
|
||||
}
|
||||
|
||||
// ToDo: are there not global commit stats?
|
||||
for _, fstat := range fstats {
|
||||
commitLog.Adds += fstat.Addition
|
||||
commitLog.Dels += fstat.Deletion
|
||||
}
|
||||
|
||||
loglines = append(loglines, commitLog)
|
||||
|
||||
return nil
|
||||
})
|
||||
if ciErr != nil {
|
||||
return fmt.Errorf("error while processing log: %w", iErr)
|
||||
}
|
||||
|
||||
logData := map[string]any{"repoInfo": repoInfo, "loglines": loglines}
|
||||
logContents, err := executeTemplate("log", logData)
|
||||
if err != nil {
|
||||
return fmt.Errorf("cannot execute logs template for repository %q: %w", repoInfo.Name, err)
|
||||
}
|
||||
|
||||
if err := os.WriteFile(filepath.Join(repoInfo.Name, "log.html"), logContents, 0755); err != nil {
|
||||
return fmt.Errorf("cannot write log contents to \"log.html\": %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
|
|
|
@ -14,11 +14,15 @@
|
|||
<table>
|
||||
<tr>
|
||||
<td><a href="../"><img src="logo.png" alt="" width="32" height="32" /></a></td>
|
||||
<td><h1>stagit</h1><span class="desc">static git page generator</span></td>
|
||||
<td><h1>{{.repoInfo.Name}}</h1><span class="desc">{{.repoInfo.Description}}</span></td>
|
||||
</tr>
|
||||
<tr class="url">
|
||||
<td></td>
|
||||
<td>git clone <a href="git://git.codemadness.org/stagit">git://git.codemadness.org/stagit</a></td>
|
||||
<td>
|
||||
{{if ne .repoInfo.Url ""}}
|
||||
git clone <a href="{{.repoInfo.Url}}">{{.repoInfo.Url}}</a>
|
||||
{{end}}
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td></td>
|
||||
|
@ -45,7 +49,7 @@
|
|||
<tr>
|
||||
<td>{{.Mode}}</td>
|
||||
<td><a href="{{.Path}}">{{.Name}}</a></td>
|
||||
<td class="num" align="right">{{.Lines}}L</td>
|
||||
<td class="num" align="right">{{if .IsBinary}}{{.Size}}B{{else}}{{.Lines}}L{{end}}</td>
|
||||
</tr>
|
||||
{{end}}
|
||||
</tbody>
|
||||
|
|
63
templates/log.html.tmpl
Normal file
63
templates/log.html.tmpl
Normal file
|
@ -0,0 +1,63 @@
|
|||
<!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>Log - {{.repoInfo.Name}} - {{.repoInfo.Description}}</title>
|
||||
<link rel="icon" type="image/png" href="favicon.png" />
|
||||
<link rel="alternate" type="application/atom+xml" title="frontends Atom Feed" href="atom.xml" />
|
||||
<link rel="alternate" type="application/atom+xml" title="frontends Atom Feed (tags)" href="tags.xml" />
|
||||
<link rel="stylesheet" type="text/css" href="style.css" />
|
||||
</head>
|
||||
<body>
|
||||
<table>
|
||||
<tr>
|
||||
<td><a href="../"><img src="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>
|
||||
<a href="log.html">Log</a>
|
||||
| <a href="files.html">Files</a>
|
||||
| <a href="refs.html">Refs</a>
|
||||
| <a href="file/README.html">README</a>
|
||||
| <a href="file/LICENSE.html">LICENSE</a>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<hr/>
|
||||
<div id="content">
|
||||
<table id="log">
|
||||
<thead>
|
||||
<tr>
|
||||
<td><b>Date</b></td>
|
||||
<td><b>Commit message</b></td>
|
||||
<td><b>Author</b></td>
|
||||
<td class="num" align="right"><b>Files</b></td>
|
||||
<td class="num" align="right"><b>+</b></td>
|
||||
<td class="num" align="right"><b>-</b></td>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{{- range .loglines}}
|
||||
<tr>
|
||||
<td>{{.Date}}</td>
|
||||
<td><a href="commit/{{.Hash}}.html">{{.Msg}}</a></td>
|
||||
<td>{{.Author}}</td>
|
||||
<td class="num" align="right">{{.Files}}</td>
|
||||
<td class="num" align="right">+{{.Adds}}</td>
|
||||
<td class="num" align="right">-{{.Dels}}</td>
|
||||
</tr>
|
||||
{{- end}}
|
||||
</tbody></table></div>
|
||||
</body>
|
||||
</html>
|
Loading…
Reference in a new issue