diff --git a/pkg/git/git.go b/pkg/git/git.go
index b9ab235f7226301c7f57ca245c5b1660fa6230b9..80c0e4613fdd261329634bf48bd58069ff827f6b 100644
--- a/pkg/git/git.go
+++ b/pkg/git/git.go
@@ -2,6 +2,8 @@ package git
import (
"errors"
+ "fmt"
+ "io"
"github.com/go-git/go-git/v5"
"github.com/go-git/go-git/v5/plumbing/object"
@@ -46,3 +48,36 @@ return nil, err
}
return c, nil
}
+
+func (g *GitRepository) Commits() ([]*object.Commit, error) {
+ repo, err := git.PlainOpen(g.path)
+ if err != nil {
+ return nil, err
+ }
+ ref, err := repo.Head()
+ if err != nil {
+ return nil, errors.Join(MissingHeadErr, err)
+ }
+
+ ci, err := repo.Log(&git.LogOptions{From: ref.Hash()})
+ if err != nil {
+ return nil, fmt.Errorf("commits from ref: %w", err)
+ }
+
+ commits := []*object.Commit{}
+ // TODO: for now only load first 1000
+ for x := 0; x < 1000; x++ {
+ c, err := ci.Next()
+ if err != nil && errors.Is(err, io.EOF) {
+ break
+ } else if err != nil {
+ return nil, err
+ }
+ commits = append(commits, c)
+ }
+ if err != nil {
+ return nil, err
+ }
+
+ return commits, nil
+}
diff --git a/pkg/handler/git/handler.go b/pkg/handler/git/handler.go
index 45cd865ea42c7929931a0472529d7916644bd8ce..ebfb37f298597e7aee5afa1ca9026e44fe9b364e 100644
--- a/pkg/handler/git/handler.go
+++ b/pkg/handler/git/handler.go
@@ -6,6 +6,7 @@ "net/http"
"git.gabrielgio.me/cerrado/pkg/service"
"git.gabrielgio.me/cerrado/templates"
+ "github.com/go-git/go-git/v5/plumbing/object"
"github.com/gorilla/mux"
)
@@ -16,6 +17,7 @@ }
gitService interface {
ListRepositories() ([]*service.Repository, error)
+ ListCommits(string) ([]*object.Commit, error)
}
)
@@ -74,9 +76,18 @@ }
func (g *GitHandler) Log(w http.ResponseWriter, r *http.Request) {
name := mux.Vars(r)["name"]
+
+ commits, err := g.gitService.ListCommits(name)
+ if err != nil {
+ slog.Error("Error loading commits", "error", err)
+ return
+ }
+
gitList := &templates.GitItemPage{
- Name: name,
- GitItemBase: &templates.GitItemLogPage{},
+ Name: name,
+ GitItemBase: &templates.GitItemLogPage{
+ Commits: commits,
+ },
}
templates.WritePageTemplate(w, gitList)
}
diff --git a/pkg/service/git.go b/pkg/service/git.go
index 2b1fe252f8e7785238896329ceca3305c71b817c..614770fa55884c145409031ec3e31fee1c9f6a07 100644
--- a/pkg/service/git.go
+++ b/pkg/service/git.go
@@ -5,6 +5,7 @@ "path"
"git.gabrielgio.me/cerrado/pkg/config"
"git.gabrielgio.me/cerrado/pkg/git"
+ "github.com/go-git/go-git/v5/plumbing/object"
)
type (
@@ -21,6 +22,7 @@ }
configurationRepository interface {
List() []*config.GitRepositoryConfiguration
+ GetByName(name string) *config.GitRepositoryConfiguration
}
)
@@ -55,3 +57,11 @@ }
return repos, nil
}
+
+func (g *GitService) ListCommits(name string) ([]*object.Commit, error) {
+ // TODO: handle nil
+ r := g.configRepo.GetByName(name)
+
+ repo := git.NewGitRepository(r.Path)
+ return repo.Commits()
+}
diff --git a/scss/main.scss b/scss/main.scss
index deea23b381c4ce957482bdf81c2d71ecdb0972dc..9f17dadab978cf2bef7863c4ff6a292d87e107a8 100644
--- a/scss/main.scss
+++ b/scss/main.scss
@@ -26,10 +26,6 @@ font-size: $base-font-size;
margin: 0;
}
-.card-body {
- padding: 5px;
-}
-
.navbar-nav {
margin-top: 0px
}
@@ -65,3 +61,34 @@ .code-view {
display: grid;
overflow-x: auto;
}
+
+.logs {
+ >div:nth-child(odd) {
+ background: #f8f9fa;
+ }
+
+ >div {
+ padding: 10px;
+ }
+
+ pre {
+ white-space: break-spaces;
+ margin: 0;
+ }
+}
+
+.logs pre::first-line {
+ font-weight: bold;
+}
+
+@include media-breakpoint-down(sm) {
+ // add extra spacing then list is seen on vertical
+ .logs>div>div:first-child {
+ margin-bottom: 15px;
+ }
+ .logs>div>div:last-child {
+ margin-top: 15px;
+ }
+}
+
+
diff --git a/templates/base.qtpl b/templates/base.qtpl
index ba32aad77d3aa3bf33796127b6af71409d673e1c..16b878014575bb4d5d6dc275b17774b1d63079c3 100644
--- a/templates/base.qtpl
+++ b/templates/base.qtpl
@@ -1,6 +1,7 @@
This is a base page template. All the other template pages implement this interface.
{% import "strconv" %}
+{% import "time" %}
{% code
var Slug = ""
@@ -21,6 +22,11 @@ if u != nil {
return strconv.FormatUint(uint64(*u), 10)
}
return ""
+ }
+%}
+
+{% code func TimeFormat(t time.Time) string {
+ return t.Format("2006-01-02")
}
%}
diff --git a/templates/base.qtpl.go b/templates/base.qtpl.go
index 2f419c68086d58c248e274382152c0ab9a3fc6fb..6d4d0a082e97a6f3bba19dc6a343ba313eabcc21 100644
--- a/templates/base.qtpl.go
+++ b/templates/base.qtpl.go
@@ -10,52 +10,55 @@
//line base.qtpl:3
import "strconv"
-//line base.qtpl:5
+//line base.qtpl:4
+import "time"
+
+//line base.qtpl:6
import (
qtio422016 "io"
qt422016 "github.com/valyala/quicktemplate"
)
-//line base.qtpl:5
+//line base.qtpl:6
var (
_ = qtio422016.Copy
_ = qt422016.AcquireByteBuffer
)
-//line base.qtpl:6
+//line base.qtpl:7
var Slug = ""
-//line base.qtpl:10
+//line base.qtpl:11
type Page interface {
-//line base.qtpl:10
+//line base.qtpl:11
Title() string
-//line base.qtpl:10
+//line base.qtpl:11
StreamTitle(qw422016 *qt422016.Writer)
-//line base.qtpl:10
+//line base.qtpl:11
WriteTitle(qq422016 qtio422016.Writer)
-//line base.qtpl:10
+//line base.qtpl:11
Content() string
-//line base.qtpl:10
+//line base.qtpl:11
StreamContent(qw422016 *qt422016.Writer)
-//line base.qtpl:10
+//line base.qtpl:11
WriteContent(qq422016 qtio422016.Writer)
-//line base.qtpl:10
+//line base.qtpl:11
Script() string
-//line base.qtpl:10
+//line base.qtpl:11
StreamScript(qw422016 *qt422016.Writer)
-//line base.qtpl:10
+//line base.qtpl:11
WriteScript(qq422016 qtio422016.Writer)
-//line base.qtpl:10
+//line base.qtpl:11
Navbar() string
-//line base.qtpl:10
+//line base.qtpl:11
StreamNavbar(qw422016 *qt422016.Writer)
-//line base.qtpl:10
+//line base.qtpl:11
WriteNavbar(qq422016 qtio422016.Writer)
-//line base.qtpl:10
+//line base.qtpl:11
}
-//line base.qtpl:19
+//line base.qtpl:20
func FromUInttoString(u *uint) string {
if u != nil {
return strconv.FormatUint(uint64(*u), 10)
@@ -63,174 +66,179 @@ }
return ""
}
+//line base.qtpl:28
+func TimeFormat(t time.Time) string {
+ return t.Format("2006-01-02")
+}
+
// Page prints a page implementing Page interface.
-//line base.qtpl:28
+//line base.qtpl:34
func StreamPageTemplate(qw422016 *qt422016.Writer, p Page) {
-//line base.qtpl:28
+//line base.qtpl:34
qw422016.N().S(`
<html lang="en">
<head>
<meta charset="utf-8">
<link rel="icon" href="data:,">
<title>cerrado | `)
-//line base.qtpl:33
+//line base.qtpl:39
p.StreamTitle(qw422016)
-//line base.qtpl:33
+//line base.qtpl:39
qw422016.N().S(`</title>
<link rel="stylesheet" href="/static/main`)
-//line base.qtpl:34
+//line base.qtpl:40
qw422016.E().S(Slug)
-//line base.qtpl:34
+//line base.qtpl:40
qw422016.N().S(`.css">
<meta name="viewport" content="width=device-width, initial-scale=1" />
</head>
<body>
`)
-//line base.qtpl:38
+//line base.qtpl:44
p.StreamNavbar(qw422016)
-//line base.qtpl:38
+//line base.qtpl:44
qw422016.N().S(`
<div class="container">
`)
-//line base.qtpl:40
+//line base.qtpl:46
p.StreamContent(qw422016)
-//line base.qtpl:40
+//line base.qtpl:46
qw422016.N().S(`
</div>
</body>
`)
-//line base.qtpl:43
+//line base.qtpl:49
p.StreamScript(qw422016)
-//line base.qtpl:43
+//line base.qtpl:49
qw422016.N().S(`
</html>
`)
-//line base.qtpl:45
+//line base.qtpl:51
}
-//line base.qtpl:45
+//line base.qtpl:51
func WritePageTemplate(qq422016 qtio422016.Writer, p Page) {
-//line base.qtpl:45
+//line base.qtpl:51
qw422016 := qt422016.AcquireWriter(qq422016)
-//line base.qtpl:45
+//line base.qtpl:51
StreamPageTemplate(qw422016, p)
-//line base.qtpl:45
+//line base.qtpl:51
qt422016.ReleaseWriter(qw422016)
-//line base.qtpl:45
+//line base.qtpl:51
}
-//line base.qtpl:45
+//line base.qtpl:51
func PageTemplate(p Page) string {
-//line base.qtpl:45
+//line base.qtpl:51
qb422016 := qt422016.AcquireByteBuffer()
-//line base.qtpl:45
+//line base.qtpl:51
WritePageTemplate(qb422016, p)
-//line base.qtpl:45
+//line base.qtpl:51
qs422016 := string(qb422016.B)
-//line base.qtpl:45
+//line base.qtpl:51
qt422016.ReleaseByteBuffer(qb422016)
-//line base.qtpl:45
+//line base.qtpl:51
return qs422016
-//line base.qtpl:45
+//line base.qtpl:51
}
-//line base.qtpl:47
+//line base.qtpl:53
type BasePage struct{}
-//line base.qtpl:48
+//line base.qtpl:54
func (p *BasePage) StreamTitle(qw422016 *qt422016.Writer) {
-//line base.qtpl:48
+//line base.qtpl:54
qw422016.N().S(`Empty`)
-//line base.qtpl:48
+//line base.qtpl:54
}
-//line base.qtpl:48
+//line base.qtpl:54
func (p *BasePage) WriteTitle(qq422016 qtio422016.Writer) {
-//line base.qtpl:48
+//line base.qtpl:54
qw422016 := qt422016.AcquireWriter(qq422016)
-//line base.qtpl:48
+//line base.qtpl:54
p.StreamTitle(qw422016)
-//line base.qtpl:48
+//line base.qtpl:54
qt422016.ReleaseWriter(qw422016)
-//line base.qtpl:48
+//line base.qtpl:54
}
-//line base.qtpl:48
+//line base.qtpl:54
func (p *BasePage) Title() string {
-//line base.qtpl:48
+//line base.qtpl:54
qb422016 := qt422016.AcquireByteBuffer()
-//line base.qtpl:48
+//line base.qtpl:54
p.WriteTitle(qb422016)
-//line base.qtpl:48
+//line base.qtpl:54
qs422016 := string(qb422016.B)
-//line base.qtpl:48
+//line base.qtpl:54
qt422016.ReleaseByteBuffer(qb422016)
-//line base.qtpl:48
+//line base.qtpl:54
return qs422016
-//line base.qtpl:48
+//line base.qtpl:54
}
-//line base.qtpl:49
+//line base.qtpl:55
func (p *BasePage) StreamBody(qw422016 *qt422016.Writer) {
-//line base.qtpl:49
+//line base.qtpl:55
qw422016.N().S(`HelloWorld`)
-//line base.qtpl:49
+//line base.qtpl:55
}
-//line base.qtpl:49
+//line base.qtpl:55
func (p *BasePage) WriteBody(qq422016 qtio422016.Writer) {
-//line base.qtpl:49
+//line base.qtpl:55
qw422016 := qt422016.AcquireWriter(qq422016)
-//line base.qtpl:49
+//line base.qtpl:55
p.StreamBody(qw422016)
-//line base.qtpl:49
+//line base.qtpl:55
qt422016.ReleaseWriter(qw422016)
-//line base.qtpl:49
+//line base.qtpl:55
}
-//line base.qtpl:49
+//line base.qtpl:55
func (p *BasePage) Body() string {
-//line base.qtpl:49
+//line base.qtpl:55
qb422016 := qt422016.AcquireByteBuffer()
-//line base.qtpl:49
+//line base.qtpl:55
p.WriteBody(qb422016)
-//line base.qtpl:49
+//line base.qtpl:55
qs422016 := string(qb422016.B)
-//line base.qtpl:49
+//line base.qtpl:55
qt422016.ReleaseByteBuffer(qb422016)
-//line base.qtpl:49
+//line base.qtpl:55
return qs422016
-//line base.qtpl:49
+//line base.qtpl:55
}
-//line base.qtpl:50
+//line base.qtpl:56
func (p *BasePage) StreamScript(qw422016 *qt422016.Writer) {
-//line base.qtpl:50
+//line base.qtpl:56
}
-//line base.qtpl:50
+//line base.qtpl:56
func (p *BasePage) WriteScript(qq422016 qtio422016.Writer) {
-//line base.qtpl:50
+//line base.qtpl:56
qw422016 := qt422016.AcquireWriter(qq422016)
-//line base.qtpl:50
+//line base.qtpl:56
p.StreamScript(qw422016)
-//line base.qtpl:50
+//line base.qtpl:56
qt422016.ReleaseWriter(qw422016)
-//line base.qtpl:50
+//line base.qtpl:56
}
-//line base.qtpl:50
+//line base.qtpl:56
func (p *BasePage) Script() string {
-//line base.qtpl:50
+//line base.qtpl:56
qb422016 := qt422016.AcquireByteBuffer()
-//line base.qtpl:50
+//line base.qtpl:56
p.WriteScript(qb422016)
-//line base.qtpl:50
+//line base.qtpl:56
qs422016 := string(qb422016.B)
-//line base.qtpl:50
+//line base.qtpl:56
qt422016.ReleaseByteBuffer(qb422016)
-//line base.qtpl:50
+//line base.qtpl:56
return qs422016
-//line base.qtpl:50
+//line base.qtpl:56
}
diff --git a/templates/gititem.qtpl b/templates/gititem.qtpl
index 4a6c49a5709efe777228786bb881715991e01268..d2fcea7fcbac20ca753c668f71b7937a7c61e7c5 100644
--- a/templates/gititem.qtpl
+++ b/templates/gititem.qtpl
@@ -23,7 +23,7 @@ </div>
<div class="row">
{%= p.Nav(p.Name) %}
</div>
-<div class="row">
+<div class="container">
{%= p.GitContent() %}
</div>
{% endfunc %}
diff --git a/templates/gititem.qtpl.go b/templates/gititem.qtpl.go
index f978c4d3d66423b73ba92eecd30ca5c359004237..9709a43ec697fd27687af9e2ac9b424ff8e981a1 100644
--- a/templates/gititem.qtpl.go
+++ b/templates/gititem.qtpl.go
@@ -124,7 +124,7 @@ p.StreamNav(qw422016, p.Name)
//line gititem.qtpl:24
qw422016.N().S(`
</div>
-<div class="row">
+<div class="container">
`)
//line gititem.qtpl:27
p.StreamGitContent(qw422016)
diff --git a/templates/gititemlog.qtpl b/templates/gititemlog.qtpl
index ae88a5205a998eec94dc046b0a7e2f2e71d3ede4..a39fb777497d50df7bec71fa6d2465b3a1b56570 100644
--- a/templates/gititemlog.qtpl
+++ b/templates/gititemlog.qtpl
@@ -1,10 +1,27 @@
+{% import "github.com/go-git/go-git/v5/plumbing/object" %}
+
{% code
type GitItemLogPage struct {
+ Commits []*object.Commit
}
%}
{% func (g *GitItemLogPage) Nav(name string) %}{%= GitItemNav(name, Log) %}{% endfunc %}
{% func (g *GitItemLogPage) GitContent() %}
-<h4>Log</h4>
+<div class="logs">
+ {% for _, c := range g.Commits %}
+ <div class="row">
+ <div class="col-sm-2">
+ {%s TimeFormat(c.Committer.When) %}
+ </div>
+ <div class="col-sm-7">
+ <pre>{%s c.Message %}</pre>
+ </div>
+ <div class="col-sm-3">
+ {%s c.Committer.Name %}
+ </div>
+ </div>
+ {% endfor %}
+</div>
{% endfunc %}
diff --git a/templates/gititemlog.qtpl.go b/templates/gititemlog.qtpl.go
index 2d559d745fa7d15387f20e382b4e8f18bc8b29b6..cc5652d56de5724d82b1ec87ed045e9722c6dfc5 100644
--- a/templates/gititemlog.qtpl.go
+++ b/templates/gititemlog.qtpl.go
@@ -5,86 +5,124 @@ //line gititemlog.qtpl:1
package templates
//line gititemlog.qtpl:1
+import "github.com/go-git/go-git/v5/plumbing/object"
+
+//line gititemlog.qtpl:3
import (
qtio422016 "io"
qt422016 "github.com/valyala/quicktemplate"
)
-//line gititemlog.qtpl:1
+//line gititemlog.qtpl:3
var (
_ = qtio422016.Copy
_ = qt422016.AcquireByteBuffer
)
-//line gititemlog.qtpl:2
+//line gititemlog.qtpl:4
type GitItemLogPage struct {
+ Commits []*object.Commit
}
-//line gititemlog.qtpl:6
+//line gititemlog.qtpl:9
func (g *GitItemLogPage) StreamNav(qw422016 *qt422016.Writer, name string) {
-//line gititemlog.qtpl:6
+//line gititemlog.qtpl:9
StreamGitItemNav(qw422016, name, Log)
-//line gititemlog.qtpl:6
+//line gititemlog.qtpl:9
}
-//line gititemlog.qtpl:6
+//line gititemlog.qtpl:9
func (g *GitItemLogPage) WriteNav(qq422016 qtio422016.Writer, name string) {
-//line gititemlog.qtpl:6
+//line gititemlog.qtpl:9
qw422016 := qt422016.AcquireWriter(qq422016)
-//line gititemlog.qtpl:6
+//line gititemlog.qtpl:9
g.StreamNav(qw422016, name)
-//line gititemlog.qtpl:6
+//line gititemlog.qtpl:9
qt422016.ReleaseWriter(qw422016)
-//line gititemlog.qtpl:6
+//line gititemlog.qtpl:9
}
-//line gititemlog.qtpl:6
+//line gititemlog.qtpl:9
func (g *GitItemLogPage) Nav(name string) string {
-//line gititemlog.qtpl:6
+//line gititemlog.qtpl:9
qb422016 := qt422016.AcquireByteBuffer()
-//line gititemlog.qtpl:6
+//line gititemlog.qtpl:9
g.WriteNav(qb422016, name)
-//line gititemlog.qtpl:6
+//line gititemlog.qtpl:9
qs422016 := string(qb422016.B)
-//line gititemlog.qtpl:6
+//line gititemlog.qtpl:9
qt422016.ReleaseByteBuffer(qb422016)
-//line gititemlog.qtpl:6
+//line gititemlog.qtpl:9
return qs422016
-//line gititemlog.qtpl:6
+//line gititemlog.qtpl:9
}
-//line gititemlog.qtpl:8
+//line gititemlog.qtpl:11
func (g *GitItemLogPage) StreamGitContent(qw422016 *qt422016.Writer) {
-//line gititemlog.qtpl:8
+//line gititemlog.qtpl:11
qw422016.N().S(`
-<h4>Log</h4>
+<div class="logs">
+ `)
+//line gititemlog.qtpl:13
+ for _, c := range g.Commits {
+//line gititemlog.qtpl:13
+ qw422016.N().S(`
+ <div class="row">
+ <div class="col-sm-2">
+ `)
+//line gititemlog.qtpl:16
+ qw422016.E().S(TimeFormat(c.Committer.When))
+//line gititemlog.qtpl:16
+ qw422016.N().S(`
+ </div>
+ <div class="col-sm-7">
+ <pre>`)
+//line gititemlog.qtpl:19
+ qw422016.E().S(c.Message)
+//line gititemlog.qtpl:19
+ qw422016.N().S(`</pre>
+ </div>
+ <div class="col-sm-3">
+ `)
+//line gititemlog.qtpl:22
+ qw422016.E().S(c.Committer.Name)
+//line gititemlog.qtpl:22
+ qw422016.N().S(`
+ </div>
+ </div>
+ `)
+//line gititemlog.qtpl:25
+ }
+//line gititemlog.qtpl:25
+ qw422016.N().S(`
+</div>
`)
-//line gititemlog.qtpl:10
+//line gititemlog.qtpl:27
}
-//line gititemlog.qtpl:10
+//line gititemlog.qtpl:27
func (g *GitItemLogPage) WriteGitContent(qq422016 qtio422016.Writer) {
-//line gititemlog.qtpl:10
+//line gititemlog.qtpl:27
qw422016 := qt422016.AcquireWriter(qq422016)
-//line gititemlog.qtpl:10
+//line gititemlog.qtpl:27
g.StreamGitContent(qw422016)
-//line gititemlog.qtpl:10
+//line gititemlog.qtpl:27
qt422016.ReleaseWriter(qw422016)
-//line gititemlog.qtpl:10
+//line gititemlog.qtpl:27
}
-//line gititemlog.qtpl:10
+//line gititemlog.qtpl:27
func (g *GitItemLogPage) GitContent() string {
-//line gititemlog.qtpl:10
+//line gititemlog.qtpl:27
qb422016 := qt422016.AcquireByteBuffer()
-//line gititemlog.qtpl:10
+//line gititemlog.qtpl:27
g.WriteGitContent(qb422016)
-//line gititemlog.qtpl:10
+//line gititemlog.qtpl:27
qs422016 := string(qb422016.B)
-//line gititemlog.qtpl:10
+//line gititemlog.qtpl:27
qt422016.ReleaseByteBuffer(qb422016)
-//line gititemlog.qtpl:10
+//line gititemlog.qtpl:27
return qs422016
-//line gititemlog.qtpl:10
+//line gititemlog.qtpl:27
}