- commit
- 3700715
- parent
- e51bb05
- author
- Eric Bower
- date
- 2023-08-06 03:40:43 +0000 UTC
looking good
6 files changed,
+141,
-77
M
go.mod
+1,
-0
1@@ -4,6 +4,7 @@ go 1.18
2
3 require (
4 github.com/gogs/git-module v1.6.0
5+ github.com/mergestat/timediff v0.0.3
6 github.com/picosh/pico v1.1.6
7 github.com/spf13/viper v1.12.0
8 )
M
go.sum
+2,
-0
1@@ -213,6 +213,8 @@ github.com/matryer/is v1.4.0 h1:sosSmIWwkYITGrxZ25ULNDeKiMNzFSr4V/eqBQP0PeE=
2 github.com/mattn/go-runewidth v0.0.10/go.mod h1:RAqKPSqVFrSLVXbA8x7dzmKdmGzieGRCM46jaSJTDAk=
3 github.com/mcuadros/go-version v0.0.0-20190308113854-92cdf37c5b75 h1:Pijfgr7ZuvX7QIQiEwLdRVr3RoMG+i0SbBO1Qu+7yVk=
4 github.com/mcuadros/go-version v0.0.0-20190308113854-92cdf37c5b75/go.mod h1:76rfSfYPWj01Z85hUf/ituArm797mNKcvINh1OlsZKo=
5+github.com/mergestat/timediff v0.0.3 h1:ucCNh4/ZrTPjFZ081PccNbhx9spymCJkFxSzgVuPU+Y=
6+github.com/mergestat/timediff v0.0.3/go.mod h1:yvMUaRu2oetc+9IbPLYBJviz6sA7xz8OXMDfhBl7YSI=
7 github.com/microcosm-cc/bluemonday v1.0.21 h1:dNH3e4PSyE4vNX+KlRGHT5KrSvjeUkoNPwEORjffHJg=
8 github.com/microcosm-cc/bluemonday v1.0.21/go.mod h1:ytNkv4RrDrLJ2pqlsSI46O6IVXmZOBBD4SaJyDwwTkM=
9 github.com/minio/md5-simd v1.1.2 h1:Gdi1DZK69+ZVMoNHRXJyNcxrMA4dSxoYHZSQbirFg34=
+11,
-11
1@@ -5,17 +5,17 @@
2 {{template "header" .}}
3
4 <dl>
5- <dt>commit</dt>
6- <dd><a href="{{.Data.CommitURL}}">{{.Data.Commit.ID}}</a></dd>
7+ <dt>commit</dt>
8+ <dd><a href="{{.Data.CommitURL}}">{{.Data.CommitID}}</a></dd>
9
10- <dt>parent</dt>
11- <dd><a href="{{.Data.ParentURL}}">{{.Data.Parent}}</a></dd>
12+ <dt>parent</dt>
13+ <dd><a href="{{.Data.ParentURL}}">{{.Data.Parent}}</a></dd>
14
15- <dt>author</dt>
16- <dd>{{.Data.Commit.Author.Name}}</dd>
17+ <dt>author</dt>
18+ <dd>{{.Data.Commit.Author.Name}}</dd>
19
20- <dt>date</dt>
21- <dd>{{.Data.Commit.Author.When}}</dd>
22+ <dt>date</dt>
23+ <dd>{{.Data.Commit.Author.When}}</dd>
24 </dl>
25
26 <pre>{{.Data.Commit.Message}}</pre>
27@@ -31,15 +31,15 @@
28 {{range .Data.Diff.Files}}
29 <div>
30 <span>{{.FileType}}</span>
31- <span>{{.Name}}</span>
32+ <a href="#diff-{{.Name}}">{{.Name}}</a>
33 </div>
34 {{end}}
35 </div>
36 </div>
37
38 {{range .Data.Diff.Files}}
39- <div class="flex justify-between mono">
40- <span>{{.FileType}} {{.OldName}} => {{.Name}}</span>
41+ <div id="diff-{{.Name}}" class="flex justify-between mono">
42+ <span>{{.FileType}} {{if eq .FileType "R"}}{{.OldName}} => {{end}}{{.Name}}</span>
43 <div>
44 <span class="color-green">+{{.NumAdditions}}</span>,
45 <span class="color-red">-{{.NumDeletions}}</span>
+13,
-6
1@@ -3,10 +3,17 @@
2 {{define "title"}}index{{end}}
3
4 {{define "content"}}
5- <h1>repos</h1>
6- {{range .RepoList}}
7- <div>
8- <a href="{{.URL}}">{{.Name}}</a>
9- </div>
10- {{end}}
11+ <h1 class="text-xl">repos</h1>
12+ <div>
13+ {{range .RepoList}}
14+ <div class="my box">
15+ <div class="flex justify-between items-center">
16+ <div><a class="text-lg" href="{{.URL}}">{{.Name}}</a></div>
17+ <div class="text-sm">{{.LastCommit.Author.When}}</div>
18+ </div>
19+
20+ <div class="my">{{.Desc}}</div>
21+ </div>
22+ {{end}}
23+ </div>
24 {{end}}
+20,
-12
1@@ -5,16 +5,24 @@
2 {{define "content"}}
3 {{template "header" .}}
4
5- <div>
6- {{range .Data.Tree}}
7- <div class="flex justify-between mt">
8- <div class="text-md">
9- <a href="{{.URL}}">{{.Path}}</a>
10- </div>
11- <div class="mono">
12- <span>lines: {{.NumLines}}</span>
13- </div>
14- </div>
15- {{end}}
16- </div>
17+ <table>
18+ <tbody>
19+ {{range .Data.Tree}}
20+ <tr>
21+ <td>
22+ <a href="{{.URL}}">{{.Path}}</a>
23+ </td>
24+ <td>
25+ <a href="{{.CommitURL}}">{{.Desc}}</a>
26+ </td>
27+ <td>
28+ {{.When}}
29+ </td>
30+ <td class="mono font-bold">
31+ L{{.NumLines}}
32+ </td>
33+ </tr>
34+ {{end}}
35+ </tbody>
36+ </table>
37 {{end}}
M
main.go
+94,
-48
1@@ -6,9 +6,11 @@ import (
2 html "html/template"
3 "os"
4 "path/filepath"
5+ "sort"
6 "strings"
7
8 git "github.com/gogs/git-module"
9+ "github.com/mergestat/timediff"
10 "github.com/picosh/pico/pastes"
11 "github.com/spf13/viper"
12 )
13@@ -16,8 +18,10 @@ import (
14 var defaultBranches = []string{"main", "master"}
15
16 type RepoItemData struct {
17- URL string
18- Name string
19+ URL string
20+ Name string
21+ Desc string
22+ LastCommit *git.Commit
23 }
24
25 type IndexPage struct {
26@@ -32,6 +36,7 @@ type RepoData struct {
27 LogURL string
28 RefsURL string
29 CloneURL string
30+ MaxCommits int
31 }
32
33 type CommitData struct {
34@@ -44,6 +49,9 @@ type TreeItem struct {
35 URL string
36 Path string
37 Entry *git.TreeEntry
38+ CommitURL string
39+ Desc string
40+ When string
41 }
42
43 type PageData struct {
44@@ -59,6 +67,7 @@ type PageData struct {
45
46 type CommitPageData struct {
47 CommitMsg template.HTML
48+ CommitID string
49 Commit *CommitData
50 Diff *DiffRender
51 Repo *RepoData
52@@ -114,7 +123,7 @@ func bail(err error) {
53 }
54 }
55
56-func CommitURL(repo string, commitID string) string {
57+func commitURL(repo string, commitID string) string {
58 return fmt.Sprintf("/%s/commits/%s.html", repo, commitID)
59 }
60
61@@ -283,14 +292,15 @@ func writeHTMLTreeFiles(data *PageData) string {
62 return readme
63 }
64
65-func writeLogDiffs(project string, repo *git.Repository, data *PageData, cache map[string]bool) {
66- for _, commit := range data.Log {
67+func (c *Config) writeLogDiffs(repo *git.Repository, pageData *PageData) {
68+ project := pageData.Repo.Name
69+ for _, commit := range pageData.Log {
70 commitID := commit.ID.String()
71
72- if cache[commitID] {
73+ if c.Cache[commitID] {
74 continue
75 } else {
76- cache[commitID] = true
77+ c.Cache[commitID] = true
78 }
79
80 ancestors, err := commit.Ancestors()
81@@ -302,7 +312,7 @@ func writeLogDiffs(project string, repo *git.Repository, data *PageData, cache m
82 pt := ancestors[0]
83 parent = &CommitData{
84 Commit: pt,
85- URL: CommitURL(project, pt.ID.String()),
86+ URL: commitURL(project, pt.ID.String()),
87 }
88 }
89 parentID := parent.ID.String()
90@@ -347,30 +357,30 @@ func writeLogDiffs(project string, repo *git.Repository, data *PageData, cache m
91
92 commitData := &CommitPageData{
93 Commit: commit,
94+ CommitID: commit.ID.String()[:7],
95 Diff: rnd,
96- Repo: data.Repo,
97- Parent: parentID,
98- CommitURL: CommitURL(project, commitID),
99- ParentURL: CommitURL(project, parentID),
100+ Repo: pageData.Repo,
101+ Parent: parentID[:7],
102+ CommitURL: commitURL(project, commitID),
103+ ParentURL: commitURL(project, parentID),
104 }
105
106 writeHtml(&WriteData{
107 Name: fmt.Sprintf("%s.html", commitID),
108 Template: "./html/commit.page.tmpl",
109 Data: commitData,
110- RepoName: data.Repo.Name,
111+ RepoName: pageData.Repo.Name,
112 Subdir: "commits",
113- Repo: data.Repo,
114+ Repo: pageData.Repo,
115 })
116 }
117 }
118
119-func writeRepo(config *RepoConfig) {
120+func (c *Config) writeRepo(config *RepoConfig) *BranchOutput {
121 repo, err := git.Open(config.Path)
122 bail(err)
123
124 name := repoName(config.Path)
125- desc := config.Desc
126
127 heads, err := repo.ShowRef(git.ShowRefOptions{Heads: true, Tags: false})
128 bail(err)
129@@ -383,19 +393,19 @@ func writeRepo(config *RepoConfig) {
130
131 repoData := &RepoData{
132 Name: name,
133- Desc: desc,
134+ Desc: config.Desc,
135+ MaxCommits: config.MaxCommits,
136 SummaryURL: fmt.Sprintf("/%s/index.html", name),
137 TreeURL: fmt.Sprintf("/%s/tree/%s/index.html", name, revName),
138 LogURL: fmt.Sprintf("/%s/logs/%s/index.html", name, revName),
139 RefsURL: fmt.Sprintf("/%s/refs.html", name),
140- CloneURL: fmt.Sprintf("/%s.git", name),
141+ CloneURL: fmt.Sprintf("https://%s/%s.git", c.URL, name),
142 }
143
144 tags, _ := repo.ShowRef(git.ShowRefOptions{Heads: false, Tags: true})
145
146- cache := make(map[string]bool)
147-
148- readme := ""
149+ var mainOutput *BranchOutput
150+ claimed := false
151 for _, revn := range config.Refs {
152 for _, head := range heads {
153 _, headName := filepath.Split(head.Refspec)
154@@ -410,9 +420,10 @@ func writeRepo(config *RepoConfig) {
155 Repo: repoData,
156 }
157
158- branchReadme := writeBranch(repo, data, cache)
159- if readme == "" {
160- readme = branchReadme
161+ branchOutput := c.writeBranch(repo, data)
162+ if !claimed {
163+ mainOutput = branchOutput
164+ claimed = true
165 }
166 }
167 }
168@@ -423,20 +434,36 @@ func writeRepo(config *RepoConfig) {
169 Rev: rev,
170 RevName: revName,
171 Repo: repoData,
172- Readme: template.HTML(readme),
173+ Readme: template.HTML(mainOutput.Readme),
174 }
175 writeRefs(data)
176 writeRootSummary(data)
177+ return mainOutput
178+}
179+
180+type BranchOutput struct {
181+ Readme string
182+ LastCommit *git.Commit
183 }
184
185-func writeBranch(repo *git.Repository, pageData *PageData, cache map[string]bool) string {
186- commits, err := repo.CommitsByPage(pageData.Rev.ID, 0, 100)
187+func (c *Config) writeBranch(repo *git.Repository, pageData *PageData) *BranchOutput {
188+ output := &BranchOutput{}
189+ pageSize := pageData.Repo.MaxCommits
190+ if pageSize == 0 {
191+ pageSize = 5000
192+ }
193+
194+ commits, err := repo.CommitsByPage(pageData.Rev.ID, 0, pageSize)
195 bail(err)
196
197 logs := []*CommitData{}
198- for _, commit := range commits {
199+ for i, commit := range commits {
200+ if i == 0 {
201+ output.LastCommit = commit
202+ }
203+
204 logs = append(logs, &CommitData{
205- URL: CommitURL(pageData.Repo.Name, commit.ID.String()),
206+ URL: commitURL(pageData.Repo.Name, commit.ID.String()),
207 Commit: commit,
208 })
209 }
210@@ -447,6 +474,19 @@ func writeBranch(repo *git.Repository, pageData *PageData, cache map[string]bool
211 treeEntries := walkTree(tree, pageData.RevName, "", entries)
212 for _, entry := range treeEntries {
213 entry.Path = strings.TrimPrefix(entry.Path, "/")
214+
215+ lastCommits, err := repo.RevList([]string{pageData.Rev.Refspec}, git.RevListOptions{
216+ Path: entry.Path,
217+ })
218+ bail(err)
219+
220+ var lc *git.Commit
221+ if (len(lastCommits) > 0) {
222+ lc = lastCommits[0]
223+ }
224+ entry.CommitURL = commitURL(pageData.Repo.Name, lc.ID.String())
225+ entry.Desc = lc.Summary()
226+ entry.When = timediff.TimeDiff(lc.Author.When)
227 entry.URL = filepath.Join(
228 "/",
229 pageData.Repo.Name,
230@@ -462,25 +502,24 @@ func writeBranch(repo *git.Repository, pageData *PageData, cache map[string]bool
231
232 writeLog(pageData)
233 readme := writeHTMLTreeFiles(pageData)
234- writeLogDiffs(pageData.Repo.Name, repo, pageData, cache)
235+ c.writeLogDiffs(repo, pageData)
236
237- for _, def := range defaultBranches {
238- if def == pageData.RevName {
239- writeTree(pageData)
240- }
241- }
242+ writeTree(pageData)
243
244- return readme
245+ output.Readme = readme
246+ return output
247 }
248
249 type RepoConfig struct {
250- Path string `mapstructure:"path"`
251- Refs []string `mapstructure:"refs"`
252- Desc string `mapstructure:"desc"`
253+ Path string `mapstructure:"path"`
254+ Refs []string `mapstructure:"refs"`
255+ Desc string `mapstructure:"desc"`
256+ MaxCommits int `mapstructure:"max_commits"`
257 }
258 type Config struct {
259 Repos []*RepoConfig `mapstructure:"repos"`
260 URL string `mapstructure:"url"`
261+ Cache map[string]bool
262 }
263
264 func main() {
265@@ -492,23 +531,30 @@ func main() {
266 bail(err)
267
268 var config Config
269- if err := viper.Unmarshal(&config); err != nil {
270- fmt.Println(err)
271- return
272- }
273+ err = viper.Unmarshal(&config)
274+ bail(err)
275+
276+ config.Cache = make(map[string]bool)
277+
278 repoList := []*RepoItemData{}
279 for _, r := range config.Repos {
280+ mainOutput := config.writeRepo(r)
281 name := repoName(r.Path)
282 url := filepath.Join("/", name, "index.html")
283 repoList = append(repoList, &RepoItemData{
284- URL: url,
285- Name: name,
286+ URL: url,
287+ Name: name,
288+ Desc: r.Desc,
289+ LastCommit: mainOutput.LastCommit,
290 })
291 }
292+ sort.Slice(repoList, func(i, j int) bool {
293+ first := repoList[i].LastCommit.Author.When
294+ second := repoList[j].LastCommit.Author.When
295+ return first.After(second)
296+ })
297+
298 writeIndex(&IndexPage{
299 RepoList: repoList,
300 })
301- for _, r := range config.Repos {
302- writeRepo(r)
303- }
304 }