diff --git a/README.md b/README.md
index 06715d1..2de40a4 100644
--- a/README.md
+++ b/README.md
@@ -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.
diff --git a/gitssg.go b/gitssg.go
index ca97c80..4c4b6a7 100644
--- a/gitssg.go
+++ b/gitssg.go
@@ -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,19 +42,22 @@ type CommitFile struct {
Size int64
}
-type CommitLog struct {
- Hash string
- Date string
- Msg string
- Author string
- Files int
- Adds int
- Dels int
+type CommitInfo struct {
+ Hash string
+ ParentHash string
+ Date time.Time
+ Msg string
+ AuthorName string
+ AuthorEmail string
+ Files int
+ Adds int
+ Dels int
}
//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{
- 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),
+ commit := &CommitInfo{
+ Hash: c.Hash.String(),
+ 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)
diff --git a/templates/commit.html.tmpl b/templates/commit.html.tmpl
new file mode 100644
index 0000000..162d423
--- /dev/null
+++ b/templates/commit.html.tmpl
@@ -0,0 +1,57 @@
+
+
+
+
+
+ {{.commit.Msg}} - {{.repoInfo.Name}} - {{.repoInfo.Description}}
+
+
+
+
+
+
+
+
+
+ |
+ {{.repoInfo.Name}}{{.repoInfo.Description}} |
+
+
+ |
+
+ {{if ne .repoInfo.Url ""}}
+ git clone {{.repoInfo.Url}}
+ {{end}}
+ |
+
+
+ |
+
+ {{menu .repoInfo .relpath}}
+ |
+
+
+
+
+
commit {{.commit.Hash}}
+parent {{.commit.ParentHash}}
+Author: {{.commit.AuthorName}} <{{.commit.AuthorEmail}}>
+Date: {{timeLongFormat .commit.Date}}
+
+{{.commit.Msg}}
+Diffstat:
+
+
1 file changed, 1 insertion(+), 1 deletion(-)
+
diff --git a/LICENSE b/LICENSE
+ @@ -1,6 +1,6 @@
+ MIT/X Consortium License
+
+ -(c) 2015-2022 Hiltjo Posthuma <hiltjo@codemadness.org>
+ +(c) 2015-2024 Hiltjo Posthuma <hiltjo@codemadness.org>
+
+ Permission is hereby granted, free of charge, to any person obtaining a
+ copy of this software and associated documentation files (the "Software"),
+
+
+
+
diff --git a/templates/files.html.tmpl b/templates/files.html.tmpl
index f482a12..ef8f2b0 100644
--- a/templates/files.html.tmpl
+++ b/templates/files.html.tmpl
@@ -41,13 +41,13 @@
- {{range .files}}
+ {{- range .files}}
{{.Mode}} |
{{.Name}} |
{{if .IsBinary}}{{.Size}}B{{else}}{{.Lines}}L{{end}} |
- {{end}}
+ {{- end}}
diff --git a/templates/index.html.tmpl b/templates/index.html.tmpl
index 3c962b1..ca11e40 100644
--- a/templates/index.html.tmpl
+++ b/templates/index.html.tmpl
@@ -28,7 +28,7 @@
{{.Name}} |
{{.Description}} |
{{.Owner}} |
- {{.LastCommit}} |
+ {{timeShortFormat .LastCommit}} |
{{- end}}
diff --git a/templates/log.html.tmpl b/templates/log.html.tmpl
index fa48b06..a2e02bc 100644
--- a/templates/log.html.tmpl
+++ b/templates/log.html.tmpl
@@ -44,11 +44,11 @@
- {{- range .loglines}}
+ {{- range .commits}}
- {{.Date}} |
- {{.Msg}} |
- {{.Author}} |
+ {{timeShortFormat .Date}} |
+ {{firstLine .Msg}} |
+ {{.AuthorName}} |
{{.Files}} |
+{{.Adds}} |
-{{.Dels}} |