|
|
@ -38,12 +38,15 @@ func main() {
|
|
38
|
38
|
}
|
|
39
|
39
|
|
|
40
|
40
|
type FancyRepo struct {
|
|
41
|
|
repo *git.Repository
|
|
42
|
|
commit *FancyCommit
|
|
|
41
|
repo *git.Repository
|
|
|
42
|
commit *FancyCommit
|
|
|
43
|
commitCount int
|
|
|
44
|
branches []*git.Branch
|
|
|
45
|
contributors []*git.Signature
|
|
43
|
46
|
}
|
|
44
|
47
|
|
|
45
|
48
|
func NewFancyRepo(repo *git.Repository) *FancyRepo {
|
|
46
|
|
return &FancyRepo{repo: repo}
|
|
|
49
|
return &FancyRepo{repo: repo, commitCount: -1}
|
|
47
|
50
|
}
|
|
48
|
51
|
|
|
49
|
52
|
func (fr *FancyRepo) Commit() (*FancyCommit, error) {
|
|
|
@ -63,6 +66,81 @@ func (fr *FancyRepo) Commit() (*FancyCommit, error) {
|
|
63
|
66
|
return fr.commit, nil
|
|
64
|
67
|
}
|
|
65
|
68
|
|
|
|
69
|
func (fr *FancyRepo) CommitCount() (int, error) {
|
|
|
70
|
if fr.commitCount < 0 {
|
|
|
71
|
head, err := fr.repo.Head()
|
|
|
72
|
if err != nil {
|
|
|
73
|
return -1, err
|
|
|
74
|
}
|
|
|
75
|
|
|
|
76
|
commit, err := fr.repo.LookupCommit(head.Target())
|
|
|
77
|
if err != nil {
|
|
|
78
|
return -1, err
|
|
|
79
|
}
|
|
|
80
|
|
|
|
81
|
c := 1
|
|
|
82
|
for {
|
|
|
83
|
commit = commit.Parent(0)
|
|
|
84
|
if commit == nil {
|
|
|
85
|
break
|
|
|
86
|
}
|
|
|
87
|
c += 1
|
|
|
88
|
}
|
|
|
89
|
fr.commitCount = c
|
|
|
90
|
}
|
|
|
91
|
return fr.commitCount, nil
|
|
|
92
|
}
|
|
|
93
|
|
|
|
94
|
func (fr *FancyRepo) Contributors() ([]*git.Signature, error) {
|
|
|
95
|
if fr.contributors == nil {
|
|
|
96
|
head, err := fr.repo.Head()
|
|
|
97
|
if err != nil {
|
|
|
98
|
return nil, err
|
|
|
99
|
}
|
|
|
100
|
|
|
|
101
|
commit, err := fr.repo.LookupCommit(head.Target())
|
|
|
102
|
if err != nil {
|
|
|
103
|
return nil, err
|
|
|
104
|
}
|
|
|
105
|
|
|
|
106
|
authors := make(map[string]*git.Signature)
|
|
|
107
|
authors[commit.Author().Name] = commit.Author()
|
|
|
108
|
for {
|
|
|
109
|
commit = commit.Parent(0)
|
|
|
110
|
if commit == nil {
|
|
|
111
|
break
|
|
|
112
|
}
|
|
|
113
|
authors[commit.Author().Name] = commit.Author()
|
|
|
114
|
}
|
|
|
115
|
for _, author := range authors {
|
|
|
116
|
fr.contributors = append(fr.contributors, author)
|
|
|
117
|
}
|
|
|
118
|
}
|
|
|
119
|
return fr.contributors, nil
|
|
|
120
|
}
|
|
|
121
|
|
|
|
122
|
func (fr *FancyRepo) Branches() ([]*git.Branch, error) {
|
|
|
123
|
if fr.branches == nil {
|
|
|
124
|
it, err := fr.repo.NewBranchIterator(git.BranchRemote)
|
|
|
125
|
if err != nil {
|
|
|
126
|
return nil, err
|
|
|
127
|
}
|
|
|
128
|
|
|
|
129
|
err = it.ForEach(func(b *git.Branch, bt git.BranchType) error {
|
|
|
130
|
fr.branches = append(fr.branches, b)
|
|
|
131
|
return nil
|
|
|
132
|
})
|
|
|
133
|
if err != nil {
|
|
|
134
|
return nil, err
|
|
|
135
|
}
|
|
|
136
|
}
|
|
|
137
|
return fr.branches, nil
|
|
|
138
|
}
|
|
|
139
|
|
|
|
140
|
func (fr *FancyRepo) Tags() ([]string, error) {
|
|
|
141
|
return fr.repo.Tags.List()
|
|
|
142
|
}
|
|
|
143
|
|
|
66
|
144
|
type FancyCommit struct {
|
|
67
|
145
|
commit *git.Commit
|
|
68
|
146
|
files []*FancyFile
|
|
|
@ -212,6 +290,13 @@ var repoTmpl = template.Must(template.New("").Parse(`<!doctype html>
|
|
212
|
290
|
</head>
|
|
213
|
291
|
|
|
214
|
292
|
<body>
|
|
|
293
|
<section id="repo" class="repo-info">
|
|
|
294
|
<a id="commits" class="repo-stat" href="#"><span class="icon">⏲</span><span class="count">{{ .Repo.CommitCount }}</span> commits</a>
|
|
|
295
|
<a id="branches" class="repo-stat" href="#"><span class="icon">⛗</span><span class="count">{{ len .Repo.Branches }}</span> branches</a>
|
|
|
296
|
<a id="tags" class="repo-stat" href="#"><span class="icon">🔖</span><span class="count">{{ len .Repo.Tags }}</span> tags</a>
|
|
|
297
|
<a id="contributors" class="repo-stat" href="#"><span class="icon">👥</span><span class="count">{{ len .Repo.Contributors }}</span> contributors</a>
|
|
|
298
|
</section>
|
|
|
299
|
|
|
215
|
300
|
<section id="commit" class="commit-info">
|
|
216
|
301
|
<div class="commit-author">{{ .Repo.Commit.Author }}</div>
|
|
217
|
302
|
<div class="commit-summary" title="{{ .Repo.Commit.Description }}">{{ .Repo.Commit.Summary }}</div>
|
|
|
@ -248,6 +333,38 @@ body {
|
|
248
|
333
|
font-family: Arial, sans-serif;
|
|
249
|
334
|
}
|
|
250
|
335
|
|
|
|
336
|
#repo {
|
|
|
337
|
display: flex;
|
|
|
338
|
justify-content: center;
|
|
|
339
|
width: 70vw;
|
|
|
340
|
border: 1px solid #ddd;
|
|
|
341
|
padding: 0.75em;
|
|
|
342
|
margin-bottom: 1em
|
|
|
343
|
}
|
|
|
344
|
|
|
|
345
|
#repo .repo-stat {
|
|
|
346
|
margin-right: 1em;
|
|
|
347
|
|
|
|
348
|
color: black;
|
|
|
349
|
text-decoration: none;
|
|
|
350
|
}
|
|
|
351
|
|
|
|
352
|
#repo .repo-stat:hover {
|
|
|
353
|
color: #ad56a0;
|
|
|
354
|
}
|
|
|
355
|
|
|
|
356
|
#repo .repo-stat:hover .icon {
|
|
|
357
|
color: black;
|
|
|
358
|
}
|
|
|
359
|
|
|
|
360
|
#repo .repo-stat .count {
|
|
|
361
|
font-weight: 600;
|
|
|
362
|
}
|
|
|
363
|
|
|
|
364
|
#repo .icon {
|
|
|
365
|
padding-right: 0.2em;
|
|
|
366
|
}
|
|
|
367
|
|
|
251
|
368
|
#commit {
|
|
252
|
369
|
display: flex;
|
|
253
|
370
|
justify-content: space-between;
|
|
|
@ -287,7 +404,7 @@ body {
|
|
287
|
404
|
}
|
|
288
|
405
|
|
|
289
|
406
|
#files .file-name {
|
|
290
|
|
color: #00445a;
|
|
|
407
|
color: #ad56a0;
|
|
291
|
408
|
}
|
|
292
|
409
|
|
|
293
|
410
|
.file-type-blob:before {
|