shroomgit

generate static pages of git repos
git clone https://git.davidvoz.net/shroomgit.git
index
logs
tree
license

shgit.go
1package main
2
3import (
4 "fmt"
5 "os"
6 "os/exec"
7 "path/filepath"
8 "strconv"
9 "strings"
10)
11
12func main() {
13 // TODO error handling here for invalid arguments
14
15 repo := os.Args[1]
16 output := "."
17 if len(os.Args) == 3 {
18 output = os.Args[2]
19 }
20
21 gitPath := filepath.Join(repo, ".git")
22 _, err := os.Stat(gitPath)
23 if err != nil {
24 fmt.Println("ERROR no .git found")
25 os.Exit(1)
26 }
27
28 cmd, err := exec.Command(
29 "git",
30 "-C",
31 repo,
32 "rev-list",
33 "--count",
34 "HEAD",
35 ).Output()
36 if err != nil {
37 panic(err)
38 }
39 numofCommitsStr := strings.TrimSpace(string(cmd))
40 numofCommits, _ := strconv.Atoi(numofCommitsStr)
41
42 // shared.go
43 topPart := genTopPart(repo, 0)
44
45 // this file
46 indexPage(topPart, repo, output, numofCommits, numofCommitsStr)
47
48 // logs.go
49 logPage(topPart, repo, output, numofCommits)
50 logTest(repo, output, numofCommits)
51
52 // tree.go
53 treeRepo(topPart, repo, output)
54}
55
56func indexPage(topPart string, repo string, output string, numofCommits int, numofCommitsStr string) {
57 outputFile := filepath.Join(output, "index.html")
58 file, _ := os.Create(outputFile)
59 defer file.Close()
60 file.WriteString(topPart)
61
62 file.WriteString("<b>Recent Commits</b>\n")
63
64 indexPageCommitTable(numofCommits, file, repo, output)
65
66 file.WriteString("<br><b>Head Branch</b>\n")
67
68 cmd, _ := exec.Command(
69 "git",
70 "-C",
71 repo,
72 "rev-parse",
73 "--abbrev-ref",
74 "HEAD",
75 ).Output()
76 headBranchName := strings.TrimSpace(string(cmd))
77
78 file.WriteString("<table><tr><td style=\"padding-right:9px\">")
79 file.WriteString(headBranchName + ", " + numofCommitsStr)
80 if numofCommits > 1 {
81 file.WriteString(" commits")
82 } else {
83 file.WriteString(" commit")
84 }
85 file.WriteString("</td>")
86
87 // TODO add first author
88
89 file.WriteString("</tr></table><br>")
90 possibleFilePaths := []string{"README", "README.md", "readme.md"}
91 for _, f := range possibleFilePaths {
92 path := filepath.Join(repo, f)
93 if _, err := os.Stat(path); err == nil {
94 writePerFile(file, path)
95 break
96 }
97 }
98
99 file.WriteString("\n</body>")
100}
101
102func indexPageCommitTable(numofCommits int, file *os.File, repo string, path string) {
103 notFile, _ := os.Open(path)
104 defer notFile.Close()
105 file.WriteString("<table>\n")
106
107 // TODO find out how to have a range (0 -> 4 or numofCommits)
108 for i := range numofCommits {
109 file.WriteString("<tr>")
110
111 cmd, err := exec.Command(
112 "git",
113 "-C", repo,
114 "log", "-1",
115 fmt.Sprintf("--skip=%d", i),
116 "--pretty=format:%ai%n%an%n%s%n%H",
117 ).Output()
118 if err != nil {
119 panic(err)
120 }
121
122 commitInfo := strings.Split(string(cmd), "\n")
123 timeofCommit := commitInfo[0]
124 authorofCommit := commitInfo[1]
125 commitMessage := commitInfo[2]
126 commitHash := commitInfo[3]
127
128 file.WriteString("<td valign=\"top\">")
129 dateofCommit := strings.SplitN(timeofCommit, " ", 2)[0]
130 file.WriteString(dateofCommit)
131 file.WriteString("</td>\n")
132
133 maxLen := 45
134 if len(commitMessage) > maxLen {
135 commitMessage = commitMessage[:maxLen] + "..."
136 }
137
138 file.WriteString("<td valign=\"top\">")
139 file.WriteString("<a href=\"logs/")
140 file.WriteString(commitHash)
141 file.WriteString(".html\">" + commitMessage + "</a>")
142 file.WriteString("</td>\n")
143
144 file.WriteString("<td valign=\"top\">")
145 file.WriteString(authorofCommit)
146 file.WriteString("</td>\n</tr>")
147
148 // index.html will only be showing the 5 latest or less commits
149 if i == 4 {
150 break
151 }
152 }
153
154 file.WriteString("</table>")
155}