name:
commit.go
-rw-r--r--
3282
1package main
2
3import (
4 "errors"
5 "html/template"
6 "os"
7 "os/exec"
8 "path"
9 "strings"
10
11 "github.com/go-git/go-git/v5"
12 "github.com/go-git/go-git/v5/plumbing/object"
13)
14
15type commitPage struct {
16 RepoData repoData
17 Author string
18 AuthorEmail string
19 Date string
20 Hash string
21 Message string
22 FileChangeCount int
23 LinesAdded int
24 LinesDeleted int
25 FilesChanged []string
26 DiffContent template.HTML
27}
28
29func (c *commitPage) renderPage(t *template.Template) {
30 debug("commit %v %v", c.RepoData.Name, c.Hash)
31 err := os.MkdirAll(path.Join(args.OutputDir, c.RepoData.Name, "commit", c.Hash), 0755)
32 checkErr(err)
33 output, err := os.Create(path.Join(args.OutputDir, c.RepoData.Name, "commit", c.Hash, "index.html"))
34 checkErr(err)
35 err = t.Execute(output, c)
36 checkErr(err)
37}
38
39func renderAllCommitPages(data repoData, r *git.Repository) {
40 t, err := template.ParseFS(htmlTemplates, "template.commit.html", "template.partials.html")
41 checkErr(err)
42 ref, err := r.Head()
43 checkErr(err)
44 cIter, err := r.Log(&git.LogOptions{From: ref.Hash()})
45 checkErr(err)
46 err = cIter.ForEach(func(c *object.Commit) error {
47 parent, err := c.Parent(0)
48 if err != nil && errors.Is(err, object.ErrParentNotFound) {
49 // ok
50 } else if err != nil {
51 checkErr(err)
52 }
53 diffContent := template.HTML("")
54 filesChangedMap := make(map[string]bool)
55 filesChanged := []string{}
56 if parent != nil {
57 patch, err := parent.Patch(c)
58 // NOTE: Seems to be a bug in go-git that gives us diff patches that are wrong. Could be my
59 // usage, but something tells me no. Fixing it by shelling out for now, since we
60 // require git to be installed for `git update-server-info` anyway.
61 cmd := exec.Command("git", "diff", parent.Hash.String(), c.Hash.String())
62 cmd.Dir = path.Join(args.OutputDir, data.Name, "git")
63 var out strings.Builder
64 cmd.Stdout = &out
65 err = cmd.Run()
66 checkErr(err)
67 patchString := out.String()
68 highlighted := highlight("x.diff", &patchString)
69 diffContent = template.HTML(highlighted)
70 checkErr(err)
71 patch, err = parent.Patch(c)
72 checkErr(err)
73 for _, fp := range patch.FilePatches() {
74 from, to := fp.Files()
75 if from != nil {
76 filePath := from.Path()
77 if _, found := filesChangedMap[filePath]; !found {
78 filesChangedMap[filePath] = true
79 filesChanged = append(filesChanged, filePath)
80 }
81 }
82 if to != nil {
83 filePath := to.Path()
84 if _, found := filesChangedMap[filePath]; !found {
85 filesChangedMap[filePath] = true
86 filesChanged = append(filesChanged, filePath)
87 }
88 }
89 }
90 }
91 stats, err := c.Stats()
92 added := 0
93 deleted := 0
94 for i := 0; i < len(stats); i++ {
95 stat := stats[i]
96 added += stat.Addition
97 deleted += stat.Deletion
98 }
99 checkErr(err)
100 (&commitPage{
101 RepoData: data,
102 Author: c.Author.Name,
103 AuthorEmail: c.Author.Email,
104 Message: c.Message,
105 Date: c.Author.When.UTC().Format("2006-01-02 15:04:05"),
106 Hash: c.Hash.String(),
107 FileChangeCount: len(stats),
108 LinesAdded: added,
109 LinesDeleted: deleted,
110 FilesChanged: filesChanged,
111 DiffContent: diffContent,
112 }).renderPage(t)
113 return nil
114 })
115 checkErr(err)
116}