diff --git a/README.md b/README.md
index 5545309..9b1132a 100644
--- a/README.md
+++ b/README.md
@@ -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.
diff --git a/gitssg.go b/gitssg.go
index 8d1c000..7380b68 100644
--- a/gitssg.go
+++ b/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
}
diff --git a/templates/files.html.tmpl b/templates/files.html.tmpl
index 123bfe0..1477a15 100644
--- a/templates/files.html.tmpl
+++ b/templates/files.html.tmpl
@@ -14,11 +14,15 @@
|
- stagitstatic git page generator |
+ {{.repoInfo.Name}}{{.repoInfo.Description}} |
|
- git clone git://git.codemadness.org/stagit |
+
+ {{if ne .repoInfo.Url ""}}
+ git clone {{.repoInfo.Url}}
+ {{end}}
+ |
|
@@ -45,7 +49,7 @@
{{.Mode}} |
{{.Name}} |
- {{.Lines}}L |
+ {{if .IsBinary}}{{.Size}}B{{else}}{{.Lines}}L{{end}} |
{{end}}
diff --git a/templates/log.html.tmpl b/templates/log.html.tmpl
new file mode 100644
index 0000000..26e4666
--- /dev/null
+++ b/templates/log.html.tmpl
@@ -0,0 +1,63 @@
+
+
+
+
+
+ Log - {{.repoInfo.Name}} - {{.repoInfo.Description}}
+
+
+
+
+
+
+
+
+
+
+
+
+ Date |
+ Commit message |
+ Author |
+ Files |
+ + |
+ - |
+
+
+
+ {{- range .loglines}}
+
+ {{.Date}} |
+ {{.Msg}} |
+ {{.Author}} |
+ {{.Files}} |
+ +{{.Adds}} |
+ -{{.Dels}} |
+
+ {{- end}}
+
+
+