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
|
- [ ] Add a subcommand to dump the embedded templates so they can be
|
||||||
modified.
|
modified.
|
||||||
- [ ] Take binary files into account.
|
- [ ] 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.
|
- [X] Allow to anchor lines.
|
||||||
- [ ] Check if the templates exist on a location and use them if
|
- [ ] Check if the templates exist on a location and use them if
|
||||||
so. Allow to change that location through CLI flags or env vars.
|
so. Allow to change that location through CLI flags or env vars.
|
||||||
|
|
80
gitssg.go
80
gitssg.go
|
@ -9,7 +9,6 @@ import (
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/alecthomas/kong"
|
"github.com/alecthomas/kong"
|
||||||
"github.com/go-git/go-git/v5"
|
"github.com/go-git/go-git/v5"
|
||||||
|
@ -20,7 +19,7 @@ type RepoDir struct {
|
||||||
Name string
|
Name string
|
||||||
Description string
|
Description string
|
||||||
Owner string
|
Owner string
|
||||||
LastCommit time.Time
|
LastCommit string
|
||||||
}
|
}
|
||||||
|
|
||||||
type RepoInfo struct {
|
type RepoInfo struct {
|
||||||
|
@ -37,11 +36,24 @@ type CommitFile struct {
|
||||||
Path string
|
Path string
|
||||||
Name string
|
Name string
|
||||||
Lines int
|
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
|
//go:embed templates
|
||||||
var embedTmpl embed.FS
|
var embedTmpl embed.FS
|
||||||
var funcMap = template.FuncMap{"inc": func(i int) int { return i + 1 }}
|
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
|
// ToDo: add a map function to generate the menu
|
||||||
|
|
||||||
|
@ -128,7 +140,7 @@ func generateIndex(args []string) error {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("cannot get commit %q for repository %q: %w", head.Hash(), dirname, err)
|
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)
|
repoDirs = append(repoDirs, repoDir)
|
||||||
}
|
}
|
||||||
|
@ -229,8 +241,10 @@ func generateRepo(path string) error {
|
||||||
}
|
}
|
||||||
data["isBinary"] = isBinary
|
data["isBinary"] = isBinary
|
||||||
|
|
||||||
|
var lines []string
|
||||||
if !isBinary {
|
if !isBinary {
|
||||||
lines, err := o.Lines()
|
var err error
|
||||||
|
lines, err = o.Lines()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("cannot get lines for %q: %w", o.Name, err)
|
return fmt.Errorf("cannot get lines for %q: %w", o.Name, err)
|
||||||
}
|
}
|
||||||
|
@ -251,6 +265,9 @@ func generateRepo(path string) error {
|
||||||
Mode: o.Mode.String(), // ToDo: correctly calculate the mode string
|
Mode: o.Mode.String(), // ToDo: correctly calculate the mode string
|
||||||
Path: filepath.Join("file", fmt.Sprintf("%s.html", o.Name)),
|
Path: filepath.Join("file", fmt.Sprintf("%s.html", o.Name)),
|
||||||
Name: o.Name,
|
Name: o.Name,
|
||||||
|
Lines: len(lines),
|
||||||
|
IsBinary: isBinary,
|
||||||
|
Size: o.Size,
|
||||||
}
|
}
|
||||||
files = append(files, file)
|
files = append(files, file)
|
||||||
|
|
||||||
|
@ -260,17 +277,66 @@ func generateRepo(path string) error {
|
||||||
return fmt.Errorf("error while processing tree: %w", iErr)
|
return fmt.Errorf("error while processing tree: %w", iErr)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// generate the files index file
|
||||||
// ToDo: bundle execute and write into a function
|
// ToDo: bundle execute and write into a function
|
||||||
data := map[string]any{"repoInfo": repoInfo, "files": files}
|
filesData := map[string]any{"repoInfo": repoInfo, "files": files}
|
||||||
contents, err := executeTemplate("files", data)
|
filesContents, err := executeTemplate("files", filesData)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("cannot execute files template for repository %q: %w", repoInfo.Name, err)
|
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)
|
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
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -14,11 +14,15 @@
|
||||||
<table>
|
<table>
|
||||||
<tr>
|
<tr>
|
||||||
<td><a href="../"><img src="logo.png" alt="" width="32" height="32" /></a></td>
|
<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>
|
||||||
<tr class="url">
|
<tr class="url">
|
||||||
<td></td>
|
<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>
|
||||||
<tr>
|
<tr>
|
||||||
<td></td>
|
<td></td>
|
||||||
|
@ -45,7 +49,7 @@
|
||||||
<tr>
|
<tr>
|
||||||
<td>{{.Mode}}</td>
|
<td>{{.Mode}}</td>
|
||||||
<td><a href="{{.Path}}">{{.Name}}</a></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>
|
</tr>
|
||||||
{{end}}
|
{{end}}
|
||||||
</tbody>
|
</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