- commit
- 134e2ae
- parent
- fe38cd8
- author
- Eric Bower
- date
- 2023-08-07 13:47:05 +0000 UTC
copy changes
6 files changed,
+148,
-141
+4,
-0
1@@ -9,3 +9,7 @@ repos:
2 refs:
3 - main
4 desc: infra for pico services
5+ - path: /home/erock/dev/app-ui
6+ refs:
7+ - main
8+ desc: aptible's paas web application
+1,
-1
1@@ -12,7 +12,7 @@
2 <a href="{{.Repo.LogURL}}">log</a>
3 </div>
4
5-<div class="my">
6+<div class="mt-lg">
7 <div class="text-lg">{{.Repo.Desc}}</div>
8 <pre style="margin: 0;">git clone {{.Repo.CloneURL}}</pre>
9 </div>
+9,
-3
1@@ -8,10 +8,16 @@
2 <div>
3 {{range .Data.Log}}
4 <div class="box">
5- <div>
6- <a href="{{.URL}}">{{.SummaryStr}}</a>
7+ <div class="flex justify-between items-center">
8+ <div>
9+ <a href="{{.URL}}">{{.SummaryStr}}</a>
10+ </div>
11+ <div>
12+ {{.ShortID}}
13+ </div>
14 </div>
15- <div>
16+
17+ <div class="flex items-center">
18 <span>{{.AuthorStr}}</span>
19 <span> committed </span>
20 <span>{{.WhenStr}}</span>
+6,
-6
1@@ -7,17 +7,17 @@
2
3 <div>
4 {{range .Data.Tree}}
5- <div class="flex justify-between">
6+ <div class="flex justify-between items-center gap my-sm border-b">
7 <div class="flex-1">
8 <a href="{{.URL}}">{{.Path}}</a>
9 </div>
10
11- <div class="flex">
12- <div>
13- <a href="{{.CommitURL}}">{{.When}}</a>
14+ <div class="flex items-center gap">
15+ <div class="flex-1">
16+ <a href="{{.CommitURL}}" title="{{.Summary}}">{{.When}}</a>
17 </div>
18- <div class="mono font-bold">
19- L{{.NumLines}}
20+ <div class="tree-size">
21+ {{if .IsTextFile}}{{.NumLines}} L{{else}}{{.Size}}{{end}}
22 </div>
23 </div>
24 </div>
M
main.go
+101,
-64
1@@ -9,9 +9,11 @@ import (
2 "sort"
3 "strings"
4
5+ "github.com/dustin/go-humanize"
6 git "github.com/gogs/git-module"
7 "github.com/mergestat/timediff"
8 "github.com/picosh/pico/pastes"
9+ "github.com/picosh/pico/shared"
10 "github.com/spf13/viper"
11 )
12
13@@ -38,35 +40,39 @@ type RepoData struct {
14 RefsURL string
15 CloneURL string
16 MaxCommits int
17- RevName string
18+ RevName string
19+ Readme string
20 }
21
22 type CommitData struct {
23 SummaryStr string
24- URL string
25- WhenStr string
26- AuthorStr string
27+ URL string
28+ WhenStr string
29+ AuthorStr string
30+ ShortID string
31 *git.Commit
32 }
33
34 type TreeItem struct {
35- NumLines int
36- URL string
37- Path string
38- Entry *git.TreeEntry
39- CommitURL string
40- Desc string
41- When string
42+ IsTextFile bool
43+ Size string
44+ NumLines int
45+ URL string
46+ Path string
47+ Entry *git.TreeEntry
48+ CommitURL string
49+ Summary string
50+ When string
51 }
52
53 type PageData struct {
54- Repo *RepoData
55- Log []*CommitData
56- Tree []*TreeItem
57- Readme template.HTML
58- Rev *git.Reference
59- RevName string
60- Refs []*RefInfo
61+ Repo *RepoData
62+ Log []*CommitData
63+ Tree []*TreeItem
64+ Readme template.HTML
65+ Rev *git.Reference
66+ RevName string
67+ Refs []*RefInfo
68 }
69
70 type CommitPageData struct {
71@@ -107,6 +113,35 @@ type DiffRenderFile struct {
72 NumDeletions int
73 }
74
75+type FileData struct {
76+ Contents template.HTML
77+ Name string
78+}
79+
80+type RefInfo struct {
81+ Refspec string
82+ URL template.URL
83+}
84+
85+type BranchOutput struct {
86+ Readme string
87+ LastCommit *git.Commit
88+}
89+
90+type RepoConfig struct {
91+ Path string `mapstructure:"path"`
92+ Refs []string `mapstructure:"refs"`
93+ Desc string `mapstructure:"desc"`
94+ MaxCommits int `mapstructure:"max_commits"`
95+ Readme string `mapstructure:"readme"`
96+}
97+
98+type Config struct {
99+ Repos []*RepoConfig `mapstructure:"repos"`
100+ URL string `mapstructure:"url"`
101+ Cache map[string]bool
102+}
103+
104 func diffFileType(_type git.DiffFileType) string {
105 if _type == git.DiffFileAdd {
106 return "A"
107@@ -127,6 +162,10 @@ func bail(err error) {
108 }
109 }
110
111+func toPretty(b int64) string {
112+ return humanize.Bytes(uint64(b))
113+}
114+
115 func commitURL(repo string, commitID string) string {
116 return fmt.Sprintf("/%s/commits/%s.html", repo, commitID)
117 }
118@@ -135,6 +174,15 @@ func repoName(root string) string {
119 _, file := filepath.Split(root)
120 return file
121 }
122+
123+func readmeFile(repo *RepoData) string {
124+ if repo.Readme == "" {
125+ return "readme.md"
126+ }
127+
128+ return strings.ToLower(repo.Readme)
129+}
130+
131 func findDefaultBranch(config *RepoConfig, refs []*git.Reference) *git.Reference {
132 branches := config.Refs
133 if len(branches) == 0 {
134@@ -165,6 +213,7 @@ func walkTree(tree *git.Tree, branch string, curpath string, aggregate []*TreeIt
135
136 if entry.IsBlob() {
137 aggregate = append(aggregate, &TreeItem{
138+ Size: toPretty(entry.Size()),
139 Path: fname,
140 Entry: entry,
141 URL: filepath.Join("/", "tree", branch, "item", fname),
142@@ -188,12 +237,13 @@ func writeHtml(data *WriteData) {
143
144 outdir := viper.GetString("outdir")
145 dir := filepath.Join(outdir, data.RepoName, data.Subdir)
146- fmt.Println(dir)
147- fmt.Println(data.Name)
148 err = os.MkdirAll(dir, os.ModePerm)
149 bail(err)
150
151- w, err := os.OpenFile(filepath.Join(dir, data.Name), os.O_WRONLY|os.O_CREATE, 0755)
152+ fp := filepath.Join(dir, data.Name)
153+ fmt.Printf("writing (%s)\n", fp)
154+
155+ w, err := os.OpenFile(fp, os.O_WRONLY|os.O_CREATE, 0755)
156 bail(err)
157
158 err = ts.Execute(w, data)
159@@ -213,11 +263,13 @@ func writeIndex(data *IndexPage) {
160
161 outdir := viper.GetString("outdir")
162 dir := filepath.Join(outdir)
163- fmt.Println(dir)
164 err = os.MkdirAll(dir, os.ModePerm)
165 bail(err)
166
167- w, err := os.OpenFile(filepath.Join(dir, "index.html"), os.O_WRONLY|os.O_CREATE, 0755)
168+ fp := filepath.Join(dir, "index.html")
169+ fmt.Printf("writing (%s)\n", fp)
170+
171+ w, err := os.OpenFile(fp, os.O_WRONLY|os.O_CREATE, 0755)
172 bail(err)
173
174 err = ts.Execute(w, data)
175@@ -264,30 +316,36 @@ func writeRefs(data *PageData) {
176 })
177 }
178
179-type FileData struct {
180- Contents template.HTML
181-}
182-
183 func writeHTMLTreeFiles(data *PageData) string {
184 readme := ""
185 for _, file := range data.Tree {
186 b, err := file.Entry.Blob().Bytes()
187 bail(err)
188- file.NumLines = len(strings.Split(string(b), "\n"))
189+ str := string(b)
190+
191+ file.IsTextFile = shared.IsTextFile(str)
192+
193+ if file.IsTextFile {
194+ file.NumLines = len(strings.Split(str, "\n"))
195+ }
196
197 d := filepath.Dir(file.Path)
198 contents, err := pastes.ParseText(file.Entry.Name(), string(b))
199 bail(err)
200
201 nameLower := strings.ToLower(file.Entry.Name())
202- if nameLower == "readme.md" {
203+ summary := readmeFile(data.Repo)
204+ if nameLower == summary {
205 readme = contents
206 }
207
208 writeHtml(&WriteData{
209 Name: fmt.Sprintf("%s.html", file.Entry.Name()),
210 Template: "./html/file.page.tmpl",
211- Data: &FileData{Contents: template.HTML(contents)},
212+ Data: &FileData{
213+ Contents: template.HTML(contents),
214+ Name: file.Entry.Name(),
215+ },
216 RepoName: data.Repo.Name,
217 Subdir: filepath.Join("tree", data.RevName, "item", d),
218 Repo: data.Repo,
219@@ -381,11 +439,6 @@ func (c *Config) writeLogDiffs(repo *git.Repository, pageData *PageData) {
220 }
221 }
222
223-type RefInfo struct {
224- Refspec string
225- URL template.URL
226-}
227-
228 func (c *Config) writeRepo(config *RepoConfig) *BranchOutput {
229 repo, err := git.Open(config.Path)
230 bail(err)
231@@ -410,7 +463,7 @@ func (c *Config) writeRepo(config *RepoConfig) *BranchOutput {
232 LogURL: fmt.Sprintf("/%s/logs/%s/index.html", name, revName),
233 RefsURL: fmt.Sprintf("/%s/refs.html", name),
234 CloneURL: fmt.Sprintf("https://%s/%s.git", c.URL, name),
235- RevName: revName,
236+ RevName: revName,
237 }
238
239 refInfoMap := map[string]*RefInfo{}
240@@ -436,7 +489,7 @@ func (c *Config) writeRepo(config *RepoConfig) *BranchOutput {
241 LogURL: fmt.Sprintf("/%s/logs/%s/index.html", name, revn),
242 RefsURL: fmt.Sprintf("/%s/refs.html", name),
243 CloneURL: fmt.Sprintf("https://%s/%s.git", c.URL, name),
244- RevName: revn,
245+ RevName: revn,
246 }
247
248 data := &PageData{
249@@ -479,22 +532,17 @@ func (c *Config) writeRepo(config *RepoConfig) *BranchOutput {
250 })
251
252 data := &PageData{
253- Rev: rev,
254- RevName: revName,
255- Repo: repoData,
256- Readme: template.HTML(mainOutput.Readme),
257- Refs: refInfoList,
258+ Rev: rev,
259+ RevName: revName,
260+ Repo: repoData,
261+ Readme: template.HTML(mainOutput.Readme),
262+ Refs: refInfoList,
263 }
264 writeRefs(data)
265 writeRootSummary(data)
266 return mainOutput
267 }
268
269-type BranchOutput struct {
270- Readme string
271- LastCommit *git.Commit
272-}
273-
274 func (c *Config) writeBranch(repo *git.Repository, pageData *PageData) *BranchOutput {
275 output := &BranchOutput{}
276 pageSize := pageData.Repo.MaxCommits
277@@ -512,11 +560,12 @@ func (c *Config) writeBranch(repo *git.Repository, pageData *PageData) *BranchOu
278 }
279
280 logs = append(logs, &CommitData{
281- URL: commitURL(pageData.Repo.Name, commit.ID.String()),
282+ URL: commitURL(pageData.Repo.Name, commit.ID.String()),
283+ ShortID: commit.ID.String()[:7],
284 SummaryStr: commit.Summary(),
285- AuthorStr: commit.Author.Name,
286- WhenStr: timediff.TimeDiff(commit.Author.When),
287- Commit: commit,
288+ AuthorStr: commit.Author.Name,
289+ WhenStr: timediff.TimeDiff(commit.Author.When),
290+ Commit: commit,
291 })
292 }
293
294@@ -537,7 +586,7 @@ func (c *Config) writeBranch(repo *git.Repository, pageData *PageData) *BranchOu
295 lc = lastCommits[0]
296 }
297 entry.CommitURL = commitURL(pageData.Repo.Name, lc.ID.String())
298- entry.Desc = lc.Summary()
299+ entry.Summary = lc.Summary()
300 entry.When = timediff.TimeDiff(lc.Author.When)
301 entry.URL = filepath.Join(
302 "/",
303@@ -562,18 +611,6 @@ func (c *Config) writeBranch(repo *git.Repository, pageData *PageData) *BranchOu
304 return output
305 }
306
307-type RepoConfig struct {
308- Path string `mapstructure:"path"`
309- Refs []string `mapstructure:"refs"`
310- Desc string `mapstructure:"desc"`
311- MaxCommits int `mapstructure:"max_commits"`
312-}
313-type Config struct {
314- Repos []*RepoConfig `mapstructure:"repos"`
315- URL string `mapstructure:"url"`
316- Cache map[string]bool
317-}
318-
319 func main() {
320 viper.SetDefault("outdir", "./public")
321 viper.SetConfigName("config")
+27,
-67
1@@ -115,32 +115,6 @@ pre {
2 background-color: var(--pre) !important;
3 }
4
5-.my {
6- margin: 1rem 0;
7-}
8-
9-.mt {
10- margin-top: 1rem;
11-}
12-
13-.my-sm {
14- margin: 5px 0;
15-}
16-
17-.mono {
18- font-family: ui-monospace, SFMono-Regular, Consolas, "Liberation Mono", Menlo,
19- monospace;
20-}
21-
22-.box {
23- font-size: 0.8rem;
24- border-radius: 5px;
25- padding: 1rem;
26- margin: 1rem 0;
27- overflow-x: auto;
28- background-color: var(--pre) !important;
29-}
30-
31 small {
32 font-size: 0.8rem;
33 }
34@@ -263,6 +237,19 @@ figure {
35 margin: 0;
36 }
37
38+.mono {
39+ font-family: ui-monospace, SFMono-Regular, Consolas, "Liberation Mono", Menlo,
40+ monospace;
41+}
42+
43+.box {
44+ border-radius: 5px;
45+ padding: 1rem;
46+ margin: 1rem 0;
47+ overflow-x: auto;
48+ background-color: var(--pre) !important;
49+}
50+
51 .color-green {
52 color: var(--success);
53 }
54@@ -271,10 +258,6 @@ figure {
55 color: var(--error);
56 }
57
58-.post-date {
59- width: 130px;
60-}
61-
62 .text-grey {
63 color: var(--grey);
64 }
65@@ -315,10 +298,6 @@ figure {
66 font-style: italic;
67 }
68
69-.inline {
70- display: inline;
71-}
72-
73 .flex {
74 display: flex;
75 }
76@@ -335,16 +314,8 @@ figure {
77 margin-top: 0.5rem;
78 }
79
80-.mb {
81- margin-bottom: 0.5rem;
82-}
83-
84-.mr {
85- margin-right: 0.5rem;
86-}
87-
88-.ml {
89- margin-left: 0.5rem;
90+.mt-lg {
91+ margin-top: 1.35rem;
92 }
93
94 .my {
95@@ -357,6 +328,11 @@ figure {
96 margin-bottom: 1rem;
97 }
98
99+.my-sm {
100+ margin-top: 5px;
101+ margin-bottom: 5px;
102+}
103+
104 .mx {
105 margin-left: 0.5rem;
106 margin-right: 0.5rem;
107@@ -375,23 +351,19 @@ figure {
108 flex: 1;
109 }
110
111-.layout-aside {
112- max-width: 50rem;
113+.gap {
114+ gap: 1rem;
115 }
116
117-.layout-aside aside {
118- width: 200px;
119+.border-b {
120+ border-bottom: 1px solid #666;
121 }
122
123-.layout-aside img {
124- border-radius: 5px;
125+.tree-size {
126+ width: 60px;
127 }
128
129-#readme {
130- display: none;
131-}
132-
133-@media only screen and (max-width: 600px) {
134+@media only screen and (max-width: 900px) {
135 body {
136 padding: 1rem;
137 }
138@@ -399,16 +371,4 @@ figure {
139 header {
140 margin: 0;
141 }
142-
143- .layout-aside main {
144- flex-direction: column;
145- }
146-
147- aside {
148- display: none;
149- }
150-
151- #readme {
152- display: block;
153- }
154 }