1diff --git a/pkg/git/git.go b/pkg/git/git.go
2index 80c0e4613fdd261329634bf48bd58069ff827f6b..7ef23f74b726b769ed7f197bd3ec25b30c2363a7 100644
3--- a/pkg/git/git.go
4+++ b/pkg/git/git.go
5@@ -6,6 +6,7 @@ "fmt"
6 "io"
7
8 "github.com/go-git/go-git/v5"
9+ "github.com/go-git/go-git/v5/plumbing"
10 "github.com/go-git/go-git/v5/plumbing/object"
11 )
12
13@@ -54,6 +55,7 @@ repo, err := git.PlainOpen(g.path)
14 if err != nil {
15 return nil, err
16 }
17+
18 ref, err := repo.Head()
19 if err != nil {
20 return nil, errors.Join(MissingHeadErr, err)
21@@ -81,3 +83,49 @@ }
22
23 return commits, nil
24 }
25+
26+func (g *GitRepository) Tags() ([]*object.Tag, error) {
27+ repo, err := git.PlainOpen(g.path)
28+ if err != nil {
29+ return nil, err
30+ }
31+
32+ ti, err := repo.TagObjects()
33+ if err != nil {
34+ return nil, err
35+ }
36+
37+ tags := []*object.Tag{}
38+ err = ti.ForEach(func(t *object.Tag) error {
39+ tags = append(tags, t)
40+ return nil
41+ })
42+ if err != nil {
43+ return nil, err
44+ }
45+
46+ return tags, nil
47+}
48+
49+func (g *GitRepository) Branches() ([]*plumbing.Reference, error) {
50+ repo, err := git.PlainOpen(g.path)
51+ if err != nil {
52+ return nil, err
53+ }
54+
55+ bs, err := repo.Branches()
56+ if err != nil {
57+ return nil, err
58+ }
59+
60+ branches := []*plumbing.Reference{}
61+ err = bs.ForEach(func(ref *plumbing.Reference) error {
62+ branches = append(branches, ref)
63+ return nil
64+ })
65+ if err != nil {
66+ return nil, err
67+ }
68+
69+ return branches, nil
70+}
71diff --git a/pkg/handler/git/handler.go b/pkg/handler/git/handler.go
72index ebfb37f298597e7aee5afa1ca9026e44fe9b364e..d090f2269b5c0057caf828048fe161028afcfacc 100644
73--- a/pkg/handler/git/handler.go
74+++ b/pkg/handler/git/handler.go
75@@ -6,6 +6,7 @@ "net/http"
76
77 "git.gabrielgio.me/cerrado/pkg/service"
78 "git.gabrielgio.me/cerrado/templates"
79+ "github.com/go-git/go-git/v5/plumbing"
80 "github.com/go-git/go-git/v5/plumbing/object"
81 "github.com/gorilla/mux"
82 )
83@@ -18,6 +19,8 @@
84 gitService interface {
85 ListRepositories() ([]*service.Repository, error)
86 ListCommits(string) ([]*object.Commit, error)
87+ ListTags(string) ([]*object.Tag, error)
88+ ListBranches(string) ([]*plumbing.Reference, error)
89 }
90 )
91
92@@ -58,9 +61,25 @@ }
93
94 func (g *GitHandler) Refs(w http.ResponseWriter, r *http.Request) {
95 name := mux.Vars(r)["name"]
96+
97+ tags, err := g.gitService.ListTags(name)
98+ if err != nil {
99+ slog.Error("Error loading tags", "error", err)
100+ return
101+ }
102+
103+ branches, err := g.gitService.ListBranches(name)
104+ if err != nil {
105+ slog.Error("Error loading branches", "error", err)
106+ return
107+ }
108+
109 gitList := &templates.GitItemPage{
110- Name: name,
111- GitItemBase: &templates.GitItemRefsPage{},
112+ Name: name,
113+ GitItemBase: &templates.GitItemRefsPage{
114+ Tags: tags,
115+ Branches: branches,
116+ },
117 }
118 templates.WritePageTemplate(w, gitList)
119 }
120diff --git a/pkg/service/git.go b/pkg/service/git.go
121index 614770fa55884c145409031ec3e31fee1c9f6a07..57b9b6e7327aa0901955e95bc0c2958d9185d408 100644
122--- a/pkg/service/git.go
123+++ b/pkg/service/git.go
124@@ -5,6 +5,7 @@ "path"
125
126 "git.gabrielgio.me/cerrado/pkg/config"
127 "git.gabrielgio.me/cerrado/pkg/git"
128+ "github.com/go-git/go-git/v5/plumbing"
129 "github.com/go-git/go-git/v5/plumbing/object"
130 )
131
132@@ -65,3 +66,19 @@
133 repo := git.NewGitRepository(r.Path)
134 return repo.Commits()
135 }
136+
137+func (g *GitService) ListTags(name string) ([]*object.Tag, error) {
138+ // TODO: handle nil
139+ r := g.configRepo.GetByName(name)
140+
141+ repo := git.NewGitRepository(r.Path)
142+ return repo.Tags()
143+}
144+
145+func (g *GitService) ListBranches(name string) ([]*plumbing.Reference, error) {
146+ // TODO: handle nil
147+ r := g.configRepo.GetByName(name)
148+
149+ repo := git.NewGitRepository(r.Path)
150+ return repo.Branches()
151+}
152diff --git a/scss/main.scss b/scss/main.scss
153index 9f17dadab978cf2bef7863c4ff6a292d87e107a8..bb7d7f08ab56d7d605e119b1a4bf85817ed8a76f 100644
154--- a/scss/main.scss
155+++ b/scss/main.scss
156@@ -80,15 +80,10 @@
157 .logs pre::first-line {
158 font-weight: bold;
159 }
160-
161-@include media-breakpoint-down(sm) {
162- // add extra spacing then list is seen on vertical
163- .logs>div>div:first-child {
164- margin-bottom: 15px;
165- }
166- .logs>div>div:last-child {
167- margin-top: 15px;
168- }
169+.logs>div>div:first-child {
170+ margin-bottom: 15px;
171+}
172+.logs>div>div:last-child {
173+ margin-top: 15px;
174 }
175
176-
177diff --git a/templates/gititemlog.qtpl b/templates/gititemlog.qtpl
178index a39fb777497d50df7bec71fa6d2465b3a1b56570..436c1d274193ee35357d087d94ce89d99ff30d7a 100644
179--- a/templates/gititemlog.qtpl
180+++ b/templates/gititemlog.qtpl
181@@ -12,14 +12,14 @@ {% func (g *GitItemLogPage) GitContent() %}
182 <div class="logs">
183 {% for _, c := range g.Commits %}
184 <div class="row">
185- <div class="col-sm-2">
186+ <div class="col-xxl-2">
187 {%s TimeFormat(c.Committer.When) %}
188 </div>
189- <div class="col-sm-7">
190+ <div class="col-xxl-7">
191 <pre>{%s c.Message %}</pre>
192 </div>
193- <div class="col-sm-3">
194- {%s c.Committer.Name %}
195+ <div class="col-xxl-3">
196+ <small>{%s c.Committer.Name %}</small>
197 </div>
198 </div>
199 {% endfor %}
200diff --git a/templates/gititemlog.qtpl.go b/templates/gititemlog.qtpl.go
201index cc5652d56de5724d82b1ec87ed045e9722c6dfc5..e63c8712559c77e4efff48789b7ab17c4bd4ce41 100644
202--- a/templates/gititemlog.qtpl.go
203+++ b/templates/gititemlog.qtpl.go
204@@ -69,26 +69,26 @@ for _, c := range g.Commits {
205 //line gititemlog.qtpl:13
206 qw422016.N().S(`
207 <div class="row">
208- <div class="col-sm-2">
209+ <div class="col-xxl-2">
210 `)
211 //line gititemlog.qtpl:16
212 qw422016.E().S(TimeFormat(c.Committer.When))
213 //line gititemlog.qtpl:16
214 qw422016.N().S(`
215 </div>
216- <div class="col-sm-7">
217+ <div class="col-xxl-7">
218 <pre>`)
219 //line gititemlog.qtpl:19
220 qw422016.E().S(c.Message)
221 //line gititemlog.qtpl:19
222 qw422016.N().S(`</pre>
223 </div>
224- <div class="col-sm-3">
225- `)
226+ <div class="col-xxl-3">
227+ <small>`)
228 //line gititemlog.qtpl:22
229 qw422016.E().S(c.Committer.Name)
230 //line gititemlog.qtpl:22
231- qw422016.N().S(`
232+ qw422016.N().S(`</small>
233 </div>
234 </div>
235 `)
236diff --git a/templates/gititemrefs.qtpl b/templates/gititemrefs.qtpl
237index 5fed393c6d715def0febba111bf84b0792dc1fa5..9c588630a087401485881be712c413e026664f07 100644
238--- a/templates/gititemrefs.qtpl
239+++ b/templates/gititemrefs.qtpl
240@@ -1,10 +1,46 @@
241+{% import "github.com/go-git/go-git/v5/plumbing" %}
242+{% import "github.com/go-git/go-git/v5/plumbing/object" %}
243+
244 {% code
245 type GitItemRefsPage struct {
246+ Tags []*object.Tag
247+ Branches []*plumbing.Reference
248 }
249 %}
250
251 {% func (g *GitItemRefsPage) Nav(name string) %}{%= GitItemNav(name ,Refs) %}{% endfunc %}
252
253 {% func (g *GitItemRefsPage) GitContent() %}
254-<h4>Refs</h4>
255+<div class="row">
256+ <div class="col-xxl">
257+ <h4>Tags</h4>
258+ <div class="logs">
259+ {% for _, t := range g.Tags %}
260+ <div class="row">
261+ <div class="col-xxl-2">
262+ {%s TimeFormat(t.Tagger.When) %}
263+ </div>
264+ <div class="col-xxl-7">
265+ <pre>{%s t.Message %}</pre>
266+ </div>
267+ <div class="col-xxl-3">
268+ <small>{%s t.Tagger.Name %}</small>
269+ </div>
270+ </div>
271+ {% endfor %}
272+ </div>
273+ </div>
274+ <div class="col-xxl">
275+ <h4>Branches</h4>
276+ <div class="logs">
277+ {% for _, b := range g.Branches %}
278+ <div class="row">
279+ <div class="col-xxl">
280+ {%s b.String() %}
281+ </div>
282+ </div>
283+ {% endfor %}
284+ </div>
285+ </div>
286+</div>
287 {% endfunc %}
288diff --git a/templates/gititemrefs.qtpl.go b/templates/gititemrefs.qtpl.go
289index 5294bf9fc28d8cbc2b1e1999729412e9dc6e0c9b..f2d2b6fcec5540caa852103cb2513ce0bcb6b518 100644
290--- a/templates/gititemrefs.qtpl.go
291+++ b/templates/gititemrefs.qtpl.go
292@@ -5,86 +5,157 @@ //line gititemrefs.qtpl:1
293 package templates
294
295 //line gititemrefs.qtpl:1
296+import "github.com/go-git/go-git/v5/plumbing"
297+
298+//line gititemrefs.qtpl:2
299+import "github.com/go-git/go-git/v5/plumbing/object"
300+
301+//line gititemrefs.qtpl:4
302 import (
303 qtio422016 "io"
304
305 qt422016 "github.com/valyala/quicktemplate"
306 )
307
308-//line gititemrefs.qtpl:1
309+//line gititemrefs.qtpl:4
310 var (
311 _ = qtio422016.Copy
312 _ = qt422016.AcquireByteBuffer
313 )
314
315-//line gititemrefs.qtpl:2
316+//line gititemrefs.qtpl:5
317 type GitItemRefsPage struct {
318+ Tags []*object.Tag
319+ Branches []*plumbing.Reference
320 }
321
322-//line gititemrefs.qtpl:6
323+//line gititemrefs.qtpl:11
324 func (g *GitItemRefsPage) StreamNav(qw422016 *qt422016.Writer, name string) {
325-//line gititemrefs.qtpl:6
326+//line gititemrefs.qtpl:11
327 StreamGitItemNav(qw422016, name, Refs)
328-//line gititemrefs.qtpl:6
329+//line gititemrefs.qtpl:11
330 }
331
332-//line gititemrefs.qtpl:6
333+//line gititemrefs.qtpl:11
334 func (g *GitItemRefsPage) WriteNav(qq422016 qtio422016.Writer, name string) {
335-//line gititemrefs.qtpl:6
336+//line gititemrefs.qtpl:11
337 qw422016 := qt422016.AcquireWriter(qq422016)
338-//line gititemrefs.qtpl:6
339+//line gititemrefs.qtpl:11
340 g.StreamNav(qw422016, name)
341-//line gititemrefs.qtpl:6
342+//line gititemrefs.qtpl:11
343 qt422016.ReleaseWriter(qw422016)
344-//line gititemrefs.qtpl:6
345+//line gititemrefs.qtpl:11
346 }
347
348-//line gititemrefs.qtpl:6
349+//line gititemrefs.qtpl:11
350 func (g *GitItemRefsPage) Nav(name string) string {
351-//line gititemrefs.qtpl:6
352+//line gititemrefs.qtpl:11
353 qb422016 := qt422016.AcquireByteBuffer()
354-//line gititemrefs.qtpl:6
355+//line gititemrefs.qtpl:11
356 g.WriteNav(qb422016, name)
357-//line gititemrefs.qtpl:6
358+//line gititemrefs.qtpl:11
359 qs422016 := string(qb422016.B)
360-//line gititemrefs.qtpl:6
361+//line gititemrefs.qtpl:11
362 qt422016.ReleaseByteBuffer(qb422016)
363-//line gititemrefs.qtpl:6
364+//line gititemrefs.qtpl:11
365 return qs422016
366-//line gititemrefs.qtpl:6
367+//line gititemrefs.qtpl:11
368 }
369
370-//line gititemrefs.qtpl:8
371+//line gititemrefs.qtpl:13
372 func (g *GitItemRefsPage) StreamGitContent(qw422016 *qt422016.Writer) {
373-//line gititemrefs.qtpl:8
374+//line gititemrefs.qtpl:13
375+ qw422016.N().S(`
376+<div class="row">
377+ <div class="col-xxl">
378+ <h4>Tags</h4>
379+ <div class="logs">
380+ `)
381+//line gititemrefs.qtpl:18
382+ for _, t := range g.Tags {
383+//line gititemrefs.qtpl:18
384+ qw422016.N().S(`
385+ <div class="row">
386+ <div class="col-xxl-2">
387+ `)
388+//line gititemrefs.qtpl:21
389+ qw422016.E().S(TimeFormat(t.Tagger.When))
390+//line gititemrefs.qtpl:21
391+ qw422016.N().S(`
392+ </div>
393+ <div class="col-xxl-7">
394+ <pre>`)
395+//line gititemrefs.qtpl:24
396+ qw422016.E().S(t.Message)
397+//line gititemrefs.qtpl:24
398+ qw422016.N().S(`</pre>
399+ </div>
400+ <div class="col-xxl-3">
401+ <small>`)
402+//line gititemrefs.qtpl:27
403+ qw422016.E().S(t.Tagger.Name)
404+//line gititemrefs.qtpl:27
405+ qw422016.N().S(`</small>
406+ </div>
407+ </div>
408+ `)
409+//line gititemrefs.qtpl:30
410+ }
411+//line gititemrefs.qtpl:30
412 qw422016.N().S(`
413-<h4>Refs</h4>
414+ </div>
415+ </div>
416+ <div class="col-xxl">
417+ <h4>Branches</h4>
418+ <div class="logs">
419+ `)
420+//line gititemrefs.qtpl:36
421+ for _, b := range g.Branches {
422+//line gititemrefs.qtpl:36
423+ qw422016.N().S(`
424+ <div class="row">
425+ <div class="col-xxl">
426+ `)
427+//line gititemrefs.qtpl:39
428+ qw422016.E().S(b.String())
429+//line gititemrefs.qtpl:39
430+ qw422016.N().S(`
431+ </div>
432+ </div>
433+ `)
434+//line gititemrefs.qtpl:42
435+ }
436+//line gititemrefs.qtpl:42
437+ qw422016.N().S(`
438+ </div>
439+ </div>
440+</div>
441 `)
442-//line gititemrefs.qtpl:10
443+//line gititemrefs.qtpl:46
444 }
445
446-//line gititemrefs.qtpl:10
447+//line gititemrefs.qtpl:46
448 func (g *GitItemRefsPage) WriteGitContent(qq422016 qtio422016.Writer) {
449-//line gititemrefs.qtpl:10
450+//line gititemrefs.qtpl:46
451 qw422016 := qt422016.AcquireWriter(qq422016)
452-//line gititemrefs.qtpl:10
453+//line gititemrefs.qtpl:46
454 g.StreamGitContent(qw422016)
455-//line gititemrefs.qtpl:10
456+//line gititemrefs.qtpl:46
457 qt422016.ReleaseWriter(qw422016)
458-//line gititemrefs.qtpl:10
459+//line gititemrefs.qtpl:46
460 }
461
462-//line gititemrefs.qtpl:10
463+//line gititemrefs.qtpl:46
464 func (g *GitItemRefsPage) GitContent() string {
465-//line gititemrefs.qtpl:10
466+//line gititemrefs.qtpl:46
467 qb422016 := qt422016.AcquireByteBuffer()
468-//line gititemrefs.qtpl:10
469+//line gititemrefs.qtpl:46
470 g.WriteGitContent(qb422016)
471-//line gititemrefs.qtpl:10
472+//line gititemrefs.qtpl:46
473 qs422016 := string(qb422016.B)
474-//line gititemrefs.qtpl:10
475+//line gititemrefs.qtpl:46
476 qt422016.ReleaseByteBuffer(qb422016)
477-//line gititemrefs.qtpl:10
478+//line gititemrefs.qtpl:46
479 return qs422016
480-//line gititemrefs.qtpl:10
481+//line gititemrefs.qtpl:46
482 }