commit
message
Rough multi-repo using toml config
author
Ben Vogt <[email protected]>
date
2023-04-04 23:17:46
stats
12 file(s) changed,
291 insertions(+),
158 deletions(-)
files
Makefile
commit.go
config.go
file.go
files.go
go.mod
go.sum
gshr.toml
index.go
log.go
main.go
templates/index.html
1diff --git a/Makefile b/Makefile
2index 030420c..87a4dec 100644
3--- a/Makefile
4+++ b/Makefile
5@@ -24,9 +24,7 @@ target/gshr-${OS}-${ARCH}-${ENVIRONMENT}.bin: Makefile target $(wildcard *.go)
6
7 dev: Makefile target target/output target/cloning target/gshr-${OS}-${ARCH}-${ENVIRONMENT}.bin
8 ./target/gshr-${OS}-${ARCH}-${ENVIRONMENT}.bin \
9- --desc="git static host repo -- generates static html for repos" \
10- --repo=/Users/bvogt/dev/src/ben/gshr \
11- --git-url="[email protected]:vogtb/gshr.git" \
12+ --config=$(PWD)/gshr.toml \
13 --output=$(PWD)/target/output \
14 --clone=$(PWD)/target/cloning \
15 && \
16diff --git a/commit.go b/commit.go
17index da1354e..365d6e3 100644
18--- a/commit.go
19+++ b/commit.go
20@@ -28,15 +28,15 @@ type CommitPage struct {
21 }
22
23 func (c *CommitPage) Render(t *template.Template) {
24- err := os.MkdirAll(path.Join(config.OutputDir, "commit", c.Hash), 0755)
25+ err := os.MkdirAll(path.Join(args.OutputDir, c.RepoData.Name, "commit", c.Hash), 0755)
26 checkErr(err)
27- output, err := os.Create(path.Join(config.OutputDir, "commit", c.Hash, "index.html"))
28+ output, err := os.Create(path.Join(args.OutputDir, c.RepoData.Name, "commit", c.Hash, "index.html"))
29 checkErr(err)
30 err = t.Execute(output, c)
31 checkErr(err)
32 }
33
34-func RenderAllCommitPages(r *git.Repository) {
35+func RenderAllCommitPages(data RepoData, r *git.Repository) {
36 t, err := template.ParseFS(htmlTemplates, "templates/commit.html", "templates/partials.html")
37 checkErr(err)
38 ref, err := r.Head()
39@@ -89,7 +89,7 @@ func RenderAllCommitPages(r *git.Repository) {
40 }
41 checkErr(err)
42 (&CommitPage{
43- RepoData: config.RepoData,
44+ RepoData: data,
45 Author: c.Author.Name,
46 AuthorEmail: c.Author.Email,
47 Message: c.Message,
48diff --git a/config.go b/config.go
49index fb73fb4..5f76096 100644
50--- a/config.go
51+++ b/config.go
52@@ -1,104 +1,41 @@
53 package main
54
55+import (
56+ "github.com/BurntSushi/toml"
57+)
58+
59 type Config struct {
60- DebugOn bool
61- Repo string
62- OutputDir string
63- CloneDir string
64- RepoData RepoData
65- AllowedLicenseFiles map[string]bool
66- AllowedReadMeFiles map[string]bool
67- TextExtensions map[string]bool
68- PlainFiles map[string]bool
69+ Repos []Repo
70+ BaseURL string
71+}
72+
73+type Repo struct {
74+ Name string
75+ Description string
76+ Path string
77+ GitURL string
78+}
79+
80+func ParseConfiguration(data string) Config {
81+ conf := Config{}
82+ _, err := toml.Decode(data, &conf)
83+ checkErr(err)
84+ return conf
85+}
86+
87+type CmdArgs struct {
88+ DebugOn bool
89+ ConfigFile string
90+ OutputDir string
91+ CloneDir string
92 }
93
94-func DefaultConfig() Config {
95- return Config{
96- DebugOn: true,
97- Repo: "",
98- OutputDir: "",
99- CloneDir: "",
100- RepoData: RepoData{
101- Name: "",
102- GitURL: "",
103- Description: "",
104- BaseURL: "/",
105- ReadMePath: "",
106- LicenseFilePath: "",
107- },
108- TextExtensions: map[string]bool{
109- ".c": true,
110- ".cc": true,
111- ".conf": true,
112- ".config": true,
113- ".cpp": true,
114- ".cs": true,
115- ".css": true,
116- ".csv": true,
117- ".Dockerfile": true,
118- ".gitignore": true,
119- ".gitmodules": true,
120- ".go": true,
121- ".h": true,
122- ".htm": true,
123- ".html": true,
124- ".iml": true,
125- ".js": true,
126- ".json": true,
127- ".jsx": true,
128- ".less": true,
129- ".lock": true,
130- ".log": true,
131- ".Makefile": true,
132- ".md": true,
133- ".mod": true,
134- ".php": true,
135- ".py": true,
136- ".rb": true,
137- ".rs": true,
138- ".scss": true,
139- ".sql": true,
140- ".sum": true,
141- ".svg": true,
142- ".toml": true,
143- ".ts": true,
144- ".tsv": true,
145- ".tsx": true,
146- ".txt": true,
147- ".xml": true,
148- ".yaml": true,
149- ".yml": true,
150- },
151- PlainFiles: map[string]bool{
152- "Dockerfile": true,
153- "license-mit": true,
154- "LICENSE-MIT": true,
155- "license": true,
156- "LICENSE": true,
157- "Makefile": true,
158- "readme": true,
159- "Readme": true,
160- "ReadMe": true,
161- "README": true,
162- },
163- AllowedLicenseFiles: map[string]bool{
164- "license-mit": true,
165- "LICENSE-MIT": true,
166- "license.md": true,
167- "LICENSE.md": true,
168- "license.txt": true,
169- "LICENSE.txt": true,
170- "LICENSE": true,
171- },
172- AllowedReadMeFiles: map[string]bool{
173- "readme.md": true,
174- "Readme.md": true,
175- "ReadMe.md": true,
176- "README.md": true,
177- "readme.txt": true,
178- "README.txt": true,
179- "README": true,
180- },
181+func DefaultCmdArgs() CmdArgs {
182+ return CmdArgs{
183+ DebugOn: true,
184+ ConfigFile: "",
185+ OutputDir: "",
186+ CloneDir: "",
187 }
188 }
189
190diff --git a/file.go b/file.go
191index a31b6e8..0cf7e18 100644
192--- a/file.go
193+++ b/file.go
194@@ -41,28 +41,28 @@ func (f *FilePage) Render(t *template.Template) {
195 checkErr(err)
196 }
197
198-func RenderSingleFilePages() {
199+func RenderSingleFilePages(data RepoData) {
200 t, err := template.ParseFS(htmlTemplates, "templates/file.html", "templates/partials.html")
201 checkErr(err)
202- err = filepath.Walk(config.CloneDir, func(filename string, info fs.FileInfo, err error) error {
203+ err = filepath.Walk(path.Join(args.CloneDir, data.Name), func(filename string, info fs.FileInfo, err error) error {
204 if info.IsDir() && info.Name() == ".git" {
205 return filepath.SkipDir
206 }
207
208 if !info.IsDir() {
209 ext := filepath.Ext(filename)
210- _, canRenderExtension := config.TextExtensions[ext]
211- _, canRenderByFullName := config.PlainFiles[filepath.Base(filename)]
212- partialPath, _ := strings.CutPrefix(filename, config.CloneDir)
213- outputName := path.Join(config.OutputDir, "files", partialPath, "index.html")
214- debug("reading = %v", partialPath)
215+ _, canRenderExtension := settings.TextExtensions[ext]
216+ _, canRenderByFullName := settings.PlainFiles[filepath.Base(filename)]
217+ partialPath, _ := strings.CutPrefix(filename, path.Join(args.CloneDir, data.Name))
218+ outputName := path.Join(args.OutputDir, "files", partialPath, "index.html")
219+ debug("reading %v %v", data.Name, partialPath)
220 (&FilePage{
221- RepoData: config.RepoData,
222+ RepoData: data,
223 Extension: ext,
224 CanRender: canRenderExtension || canRenderByFullName,
225 Origin: filename,
226 Destination: outputName,
227- DestinationDir: path.Join(config.OutputDir, "files", partialPath),
228+ DestinationDir: path.Join(args.OutputDir, data.Name, "files", partialPath),
229 }).Render(t)
230 }
231 return nil
232diff --git a/files.go b/files.go
233index 57ee8dc..a5373dc 100644
234--- a/files.go
235+++ b/files.go
236@@ -22,18 +22,18 @@ type FilesPage struct {
237 Files []FileOverview
238 }
239
240-func (fi *FilesPage) Render(t *template.Template) {
241- output, err := os.Create(path.Join(config.OutputDir, "files.html"))
242+func (f *FilesPage) Render(t *template.Template) {
243+ output, err := os.Create(path.Join(args.OutputDir, f.RepoData.Name, "files.html"))
244 checkErr(err)
245- err = t.Execute(output, fi)
246+ err = t.Execute(output, f)
247 checkErr(err)
248 }
249
250-func RenderAllFilesPage() {
251+func RenderAllFilesPage(data RepoData) {
252 t, err := template.ParseFS(htmlTemplates, "templates/files.html", "templates/partials.html")
253 checkErr(err)
254 files := make([]FileOverview, 0)
255- err = filepath.Walk(config.CloneDir, func(filename string, info fs.FileInfo, err error) error {
256+ err = filepath.Walk(path.Join(args.CloneDir, data.Name), func(filename string, info fs.FileInfo, err error) error {
257 if info.IsDir() && info.Name() == ".git" {
258 return filepath.SkipDir
259 }
260@@ -41,7 +41,7 @@ func RenderAllFilesPage() {
261 if !info.IsDir() {
262 info, err := os.Stat(filename)
263 checkErr(err)
264- Name, _ := strings.CutPrefix(filename, config.CloneDir)
265+ Name, _ := strings.CutPrefix(filename, path.Join(args.CloneDir, data.Name))
266 Name, _ = strings.CutPrefix(Name, "/")
267 tf := FileOverview{
268 Origin: filename,
269@@ -55,7 +55,7 @@ func RenderAllFilesPage() {
270 })
271 checkErr(err)
272 index := FilesPage{
273- RepoData: config.RepoData,
274+ RepoData: data,
275 Files: files,
276 }
277 index.Render(t)
278diff --git a/go.mod b/go.mod
279index 8f34af0..716b88c 100644
280--- a/go.mod
281+++ b/go.mod
282@@ -7,6 +7,8 @@ require (
283 github.com/go-git/go-git/v5 v5.6.1
284 )
285
286+require github.com/BurntSushi/toml v1.2.1 // indirect
287+
288 require (
289 github.com/Microsoft/go-winio v0.5.2 // indirect
290 github.com/ProtonMail/go-crypto v0.0.0-20230217124315-7d5c6f04bbb8 // indirect
291@@ -19,6 +21,7 @@ require (
292 github.com/imdario/mergo v0.3.13 // indirect
293 github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 // indirect
294 github.com/kevinburke/ssh_config v1.2.0 // indirect
295+ github.com/pelletier/go-toml/v2 v2.0.7
296 github.com/pjbgf/sha1cd v0.3.0 // indirect
297 github.com/sergi/go-diff v1.3.1 // indirect
298 github.com/skeema/knownhosts v1.1.0 // indirect
299diff --git a/go.sum b/go.sum
300index a3a1f90..f62a225 100644
301--- a/go.sum
302+++ b/go.sum
303@@ -1,3 +1,5 @@
304+github.com/BurntSushi/toml v1.2.1 h1:9F2/+DoOYIOksmaJFPw1tGFy1eDnIJXg+UHjuD8lTak=
305+github.com/BurntSushi/toml v1.2.1/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ=
306 github.com/Microsoft/go-winio v0.5.2 h1:a9IhgEQBCUEk6QCdml9CiJGhAws+YwffDHEMp1VMrpA=
307 github.com/Microsoft/go-winio v0.5.2/go.mod h1:WpS1mjBmmwHBEWmogvA2mj8546UReBk4v8QkMxJ6pZY=
308 github.com/ProtonMail/go-crypto v0.0.0-20230217124315-7d5c6f04bbb8 h1:wPbRQzjjwFc0ih8puEVAOFGELsn1zoIIYdxvML7mDxA=
309@@ -52,6 +54,8 @@ github.com/matryer/is v1.2.0 h1:92UTHpy8CDwaJ08GqLDzhhuixiBUUD1p3AU6PHddz4A=
310 github.com/matryer/is v1.2.0/go.mod h1:2fLPjFQM9rhQ15aVEtbuwhJinnOqrmgXPNdZsdwlWXA=
311 github.com/mmcloughlin/avo v0.5.0/go.mod h1:ChHFdoV7ql95Wi7vuq2YT1bwCJqiWdZrQ1im3VujLYM=
312 github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
313+github.com/pelletier/go-toml/v2 v2.0.7 h1:muncTPStnKRos5dpVKULv2FVd4bMOhNePj9CjgDb8Us=
314+github.com/pelletier/go-toml/v2 v2.0.7/go.mod h1:eumQOmlWiOPt5WriQQqoM5y18pDHwha2N+QD+EUNTek=
315 github.com/pjbgf/sha1cd v0.3.0 h1:4D5XXmUUBUl/xQ6IjCkEAbqXskkq/4O7LmGn0AqMDs4=
316 github.com/pjbgf/sha1cd v0.3.0/go.mod h1:nZ1rrWOcGJ5uZgEEVL1VUM9iRQiZvWdbZjkKyFzPPsI=
317 github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
318@@ -65,10 +69,15 @@ github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic
319 github.com/skeema/knownhosts v1.1.0 h1:Wvr9V0MxhjRbl3f9nMnKnFfiWTJmtECJ9Njkea3ysW0=
320 github.com/skeema/knownhosts v1.1.0/go.mod h1:sKFq3RD6/TKZkSWn8boUbDC7Qkgcv+8XXijpFO6roag=
321 github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
322+github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
323+github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
324 github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
325 github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
326-github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
327 github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
328+github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
329+github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
330+github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk=
331+github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
332 github.com/xanzy/ssh-agent v0.3.3 h1:+/15pJfg/RsTxqYcX6fHqOXZwwMP+2VyYWJeWM2qQFM=
333 github.com/xanzy/ssh-agent v0.3.3/go.mod h1:6dzNDKs0J9rVPHPhaGCukekBHKqfl+L3KghI1Bc68Uw=
334 github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
335@@ -144,6 +153,7 @@ gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
336 gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
337 gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
338 gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
339-gopkg.in/yaml.v3 v3.0.0 h1:hjy8E9ON/egN1tAYqKb61G10WtihqetD4sz2H+8nIeA=
340 gopkg.in/yaml.v3 v3.0.0/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
341+gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
342+gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
343 rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4=
344diff --git a/gshr.toml b/gshr.toml
345new file mode 100644
346index 0000000..748275a
347--- /dev/null
348+++ b/gshr.toml
349@@ -0,0 +1,7 @@
350+base_url = "/"
351+
352+[[repos]]
353+name = "gshr"
354+description = "git static host repo -- generates static html for repos"
355+path = "/Users/bvogt/dev/src/ben/gshr"
356+git_url = "[email protected]:vogtb/gshr.git"
357diff --git a/index.go b/index.go
358new file mode 100644
359index 0000000..a696b52
360--- /dev/null
361+++ b/index.go
362@@ -0,0 +1,28 @@
363+package main
364+
365+import (
366+ "html/template"
367+ "os"
368+ "path"
369+)
370+
371+type IndexPage struct {
372+ BaseURL string
373+ Repos []RepoData
374+}
375+
376+func (l *IndexPage) Render(t *template.Template) {
377+ output, err := os.Create(path.Join(args.OutputDir, "index.html"))
378+ checkErr(err)
379+ err = t.Execute(output, l)
380+ checkErr(err)
381+}
382+
383+func RenderIndexPage(repos []RepoData) {
384+ t, err := template.ParseFS(htmlTemplates, "templates/index.html", "templates/partials.html")
385+ checkErr(err)
386+ (&IndexPage{
387+ BaseURL: config.BaseURL,
388+ Repos: repos,
389+ }).Render(t)
390+}
391diff --git a/log.go b/log.go
392index 79675c8..4c7f849 100644
393--- a/log.go
394+++ b/log.go
395@@ -26,14 +26,14 @@ type LogPage struct {
396 Commits []LogPageCommit
397 }
398
399-func (mi *LogPage) Render(t *template.Template) {
400- output, err := os.Create(path.Join(config.OutputDir, "log.html"))
401+func (l *LogPage) Render(t *template.Template) {
402+ output, err := os.Create(path.Join(args.OutputDir, l.RepoData.Name, "log.html"))
403 checkErr(err)
404- err = t.Execute(output, mi)
405+ err = t.Execute(output, l)
406 checkErr(err)
407 }
408
409-func RenderLogPage(r *git.Repository) {
410+func RenderLogPage(data RepoData, r *git.Repository) {
411 t, err := template.ParseFS(htmlTemplates, "templates/log.html", "templates/partials.html")
412 checkErr(err)
413 commits := make([]LogPageCommit, 0)
414@@ -64,7 +64,7 @@ func RenderLogPage(r *git.Repository) {
415 })
416 checkErr(err)
417 (&LogPage{
418- RepoData: config.RepoData,
419+ RepoData: data,
420 Commits: commits,
421 }).Render(t)
422 }
423diff --git a/main.go b/main.go
424index ac1bef3..ea0e1ec 100644
425--- a/main.go
426+++ b/main.go
427@@ -4,7 +4,6 @@ import (
428 "bytes"
429 "embed"
430 _ "embed"
431- "errors"
432 "flag"
433 "fmt"
434 "math/rand"
435@@ -20,54 +19,67 @@ import (
436 //go:embed templates/*
437 var htmlTemplates embed.FS
438
439+var args CmdArgs
440+
441 var config Config
442
443+var settings Settings
444+
445 func main() {
446 var r *git.Repository = &git.Repository{}
447 Init()
448- CloneAndInfo(r)
449- RenderLogPage(r)
450- RenderAllCommitPages(r)
451- RenderAllFilesPage()
452- RenderSingleFilePages()
453+ allRepoData := []RepoData{}
454+ for _, repo := range config.Repos {
455+ data := CloneAndGetData(repo, r)
456+ allRepoData = append(allRepoData, data)
457+ RenderLogPage(data, r)
458+ RenderAllCommitPages(data, r)
459+ RenderAllFilesPage(data)
460+ RenderSingleFilePages(data)
461+ }
462+ RenderIndexPage(allRepoData)
463 }
464
465 func Init() {
466- config = DefaultConfig()
467- flag.StringVar(&config.Repo, "repo", "", "Repo to use.")
468- flag.BoolVar(&config.DebugOn, "debug", true, "Run in debug mode.")
469- flag.StringVar(&config.OutputDir, "output", "", "Dir of output.")
470- flag.StringVar(&config.CloneDir, "clone", "", "Dir to clone into. Default is /tmp/${rand}")
471- flag.StringVar(&config.RepoData.BaseURL, "base-url", "/", "Base URL for serving.")
472- flag.StringVar(&config.RepoData.GitURL, "git-url", "", "Show where repo is hosted.")
473- flag.StringVar(&config.RepoData.Description, "desc", "<no description>", "Description to show.")
474+ args = DefaultCmdArgs()
475+ settings = DefaultSettings()
476+ flag.StringVar(&args.ConfigFile, "config", "", "Config file.")
477+ flag.BoolVar(&args.DebugOn, "debug", true, "Run in debug mode.")
478+ flag.StringVar(&args.OutputDir, "output", "", "Dir of output.")
479+ flag.StringVar(&args.CloneDir, "clone", "", "Dir to clone into. Default is /tmp/${rand}")
480 flag.Parse()
481
482- if config.Repo == "" {
483- checkErr(errors.New("--repo flag is required"))
484- }
485-
486- if config.CloneDir == "" {
487- config.CloneDir = fmt.Sprintf("/tmp/gshr-temp-clone-%v", rand.Uint32())
488+ if args.CloneDir == "" {
489+ args.CloneDir = fmt.Sprintf("/tmp/gshr-temp-clone-%v", rand.Uint32())
490 }
491
492- config.RepoData.BaseURL = path.Join(config.RepoData.BaseURL, "/")
493- config.RepoData.Name = path.Clean(path.Base(config.Repo))
494-
495- debug("repo = %v", config.Repo)
496- debug("output = %v", config.OutputDir)
497- debug("clone = %v", config.CloneDir)
498- debug("base-url = %v", config.RepoData.BaseURL)
499+ debug("config = %v", args.ConfigFile)
500+ debug("output = %v", args.OutputDir)
501+ debug("clone = %v", args.CloneDir)
502+ configFileByes, err := os.ReadFile(args.ConfigFile)
503+ checkErr(err)
504+ config = ParseConfiguration(string(configFileByes))
505 }
506
507-func CloneAndInfo(r *git.Repository) {
508- repo, err := git.PlainClone(config.CloneDir, false, &git.CloneOptions{
509- URL: config.Repo,
510+func CloneAndGetData(repo Repo, r *git.Repository) RepoData {
511+ err := os.MkdirAll(path.Join(args.CloneDir, repo.Name), 0755)
512+ checkErr(err)
513+ err = os.MkdirAll(path.Join(args.OutputDir, repo.Name), 0755)
514+ checkErr(err)
515+ repoRef, err := git.PlainClone(path.Join(args.CloneDir, repo.Name), false, &git.CloneOptions{
516+ URL: repo.Path,
517 })
518 checkErr(err)
519- config.RepoData.ReadMePath = findFileInRoot(config.AllowedReadMeFiles)
520- config.RepoData.LicenseFilePath = findFileInRoot(config.AllowedLicenseFiles)
521- *r = *repo
522+ data := RepoData{
523+ Name: repo.Name,
524+ GitURL: repo.GitURL,
525+ Description: repo.Description,
526+ BaseURL: config.BaseURL,
527+ ReadMePath: findFileInRoot(repo.Name, settings.AllowedReadMeFiles),
528+ LicenseFilePath: findFileInRoot(repo.Name, settings.AllowedLicenseFiles),
529+ }
530+ *r = *repoRef
531+ return data
532 }
533
534 func checkErr(err error) {
535@@ -78,7 +90,7 @@ func checkErr(err error) {
536 }
537
538 func debug(format string, a ...any) {
539- if config.DebugOn {
540+ if args.DebugOn {
541 fmt.Printf(format, a...)
542 fmt.Print("\n")
543 }
544@@ -105,8 +117,8 @@ func highlight(pathOrExtension string, data *string) string {
545 return buf.String()
546 }
547
548-func findFileInRoot(oneOfThese map[string]bool) string {
549- dir, err := os.ReadDir(config.CloneDir)
550+func findFileInRoot(name string, oneOfThese map[string]bool) string {
551+ dir, err := os.ReadDir(path.Join(args.CloneDir, name))
552 checkErr(err)
553 for _, e := range dir {
554 name := e.Name()
555@@ -116,3 +128,88 @@ func findFileInRoot(oneOfThese map[string]bool) string {
556 }
557 return ""
558 }
559+
560+type Settings struct {
561+ TextExtensions map[string]bool
562+ PlainFiles map[string]bool
563+ AllowedLicenseFiles map[string]bool
564+ AllowedReadMeFiles map[string]bool
565+}
566+
567+func DefaultSettings() Settings {
568+ return Settings{
569+ TextExtensions: map[string]bool{
570+ ".c": true,
571+ ".cc": true,
572+ ".conf": true,
573+ ".config": true,
574+ ".cpp": true,
575+ ".cs": true,
576+ ".css": true,
577+ ".csv": true,
578+ ".Dockerfile": true,
579+ ".gitignore": true,
580+ ".gitmodules": true,
581+ ".go": true,
582+ ".h": true,
583+ ".htm": true,
584+ ".html": true,
585+ ".iml": true,
586+ ".js": true,
587+ ".json": true,
588+ ".jsx": true,
589+ ".less": true,
590+ ".lock": true,
591+ ".log": true,
592+ ".Makefile": true,
593+ ".md": true,
594+ ".mod": true,
595+ ".php": true,
596+ ".py": true,
597+ ".rb": true,
598+ ".rs": true,
599+ ".scss": true,
600+ ".sql": true,
601+ ".sum": true,
602+ ".svg": true,
603+ ".toml": true,
604+ ".ts": true,
605+ ".tsv": true,
606+ ".tsx": true,
607+ ".txt": true,
608+ ".xml": true,
609+ ".yaml": true,
610+ ".yml": true,
611+ },
612+ PlainFiles: map[string]bool{
613+ "Dockerfile": true,
614+ "license-mit": true,
615+ "LICENSE-MIT": true,
616+ "license": true,
617+ "LICENSE": true,
618+ "Makefile": true,
619+ "readme": true,
620+ "Readme": true,
621+ "ReadMe": true,
622+ "README": true,
623+ },
624+ AllowedLicenseFiles: map[string]bool{
625+ "license-mit": true,
626+ "LICENSE-MIT": true,
627+ "license.md": true,
628+ "LICENSE.md": true,
629+ "license.txt": true,
630+ "LICENSE.txt": true,
631+ "LICENSE": true,
632+ },
633+ AllowedReadMeFiles: map[string]bool{
634+ "readme.md": true,
635+ "Readme.md": true,
636+ "ReadMe.md": true,
637+ "README.md": true,
638+ "readme.txt": true,
639+ "README.txt": true,
640+ "README": true,
641+ },
642+ }
643+}
644diff --git a/templates/index.html b/templates/index.html
645new file mode 100644
646index 0000000..71bb554
647--- /dev/null
648+++ b/templates/index.html
649@@ -0,0 +1,39 @@
650+<!DOCTYPE html>
651+<html lang="en">
652+
653+<head>
654+ {{ template "head" .RepoData }}
655+</head>
656+
657+<body>
658+ <div class="content">
659+ <div class="index">
660+ <div class="metadata">
661+ <table>
662+ <tbody>
663+ <tr>
664+ <td>
665+ <h1>whatever</h1>
666+ <span class="desc">
667+ ???
668+ </span>
669+ </td>
670+ </tr>
671+ <tr>
672+ <td>
673+ <a href="/whatever">link?</a>
674+ </td>
675+ </tr>
676+ <tr>
677+ <td>
678+ etc.....
679+ </td>
680+ </tr>
681+ </tbody>
682+ </table>
683+ </div>
684+ </div>
685+ </div>
686+</body>
687+
688+</html>
689\ No newline at end of file