aboutsummaryrefslogtreecommitdiff
path: root/pkg
diff options
context:
space:
mode:
authorGabriel A. Giovanini <mail@gabrielgio.me>2024-06-07 14:02:25 +0200
committerGabriel A. Giovanini <mail@gabrielgio.me>2024-06-07 14:02:25 +0200
commit18aa098f50e2a2c7db01dd4d04dde460fd40f5d5 (patch)
tree5e3b3d3ba3206f2765db1a23a378275852154a51 /pkg
parentd0e0c1eb99303e1000140d4b98c610077278dc42 (diff)
downloadcerrado-18aa098f50e2a2c7db01dd4d04dde460fd40f5d5.tar.gz
cerrado-18aa098f50e2a2c7db01dd4d04dde460fd40f5d5.tar.bz2
cerrado-18aa098f50e2a2c7db01dd4d04dde460fd40f5d5.zip
feat: Add blob endpoint
Diffstat (limited to 'pkg')
-rw-r--r--pkg/git/git.go67
-rw-r--r--pkg/handler/git/handler.go81
-rw-r--r--pkg/handler/router.go3
-rw-r--r--pkg/service/git.go32
4 files changed, 178 insertions, 5 deletions
diff --git a/pkg/git/git.go b/pkg/git/git.go
index ce72465..6a7b91f 100644
--- a/pkg/git/git.go
+++ b/pkg/git/git.go
@@ -13,7 +13,8 @@ import (
var ()
var (
- MissingRefErr = errors.New("Reference not found")
+ MissingRefErr = errors.New("Reference not found")
+ TreeForFileErr = errors.New("Trying to get tree of a file")
)
type (
@@ -145,9 +146,73 @@ func (g *GitRepository) Branches() ([]*plumbing.Reference, error) {
return branches, nil
}
+func (g *GitRepository) Tree(path string) (*object.Tree, error) {
+ err := g.validateRef()
+ if err != nil {
+ return nil, err
+ }
+
+ c, err := g.repository.CommitObject(g.ref)
+ if err != nil {
+ return nil, err
+ }
+
+ tree, err := c.Tree()
+ if err != nil {
+ return nil, err
+ }
+
+ if path == "" {
+ return tree, nil
+ } else {
+ o, err := tree.FindEntry(path)
+ if err != nil {
+ return nil, err
+ }
+
+ if !o.Mode.IsFile() {
+ subtree, err := tree.Tree(path)
+ if err != nil {
+ return nil, err
+ }
+ return subtree, nil
+ } else {
+ return nil, TreeForFileErr
+ }
+ }
+}
+
func (g *GitRepository) validateRef() error {
if !g.setRef {
return g.SetRef("")
}
return nil
}
+
+func (g *GitRepository) FileContent(path string) (string, error) {
+ c, err := g.repository.CommitObject(g.ref)
+ if err != nil {
+ return "", err
+ }
+
+ tree, err := c.Tree()
+ if err != nil {
+ return "", err
+ }
+
+ file, err := tree.File(path)
+ if err != nil {
+ return "", err
+ }
+
+ isbin, err := file.IsBinary()
+ if err != nil {
+ return "", err
+ }
+
+ if !isbin {
+ return file.Contents()
+ } else {
+ return "Binary file", nil
+ }
+}
diff --git a/pkg/handler/git/handler.go b/pkg/handler/git/handler.go
index e2f4042..f3e74c7 100644
--- a/pkg/handler/git/handler.go
+++ b/pkg/handler/git/handler.go
@@ -1,11 +1,17 @@
package git
import (
+ "bytes"
"log/slog"
"net/http"
+ "path/filepath"
"git.gabrielgio.me/cerrado/pkg/service"
"git.gabrielgio.me/cerrado/templates"
+ "github.com/alecthomas/chroma/v2"
+ "github.com/alecthomas/chroma/v2/formatters/html"
+ "github.com/alecthomas/chroma/v2/lexers"
+ "github.com/alecthomas/chroma/v2/styles"
"github.com/go-git/go-git/v5/plumbing"
"github.com/go-git/go-git/v5/plumbing/object"
)
@@ -19,6 +25,8 @@ type (
ListRepositories() ([]*service.Repository, error)
ListCommits(name string, ref string) ([]*object.Commit, error)
GetHead(name string) (*plumbing.Reference, error)
+ GetTree(name, ref, path string) (*object.Tree, error)
+ GetFileContent(name, ref, path string) (string, error)
ListTags(name string) ([]*object.Tag, error)
ListBranches(name string) ([]*plumbing.Reference, error)
}
@@ -107,10 +115,64 @@ func (g *GitHandler) Refs(w http.ResponseWriter, r *http.Request) {
func (g *GitHandler) Tree(w http.ResponseWriter, r *http.Request) {
name := r.PathValue("name")
ref := r.PathValue("ref")
+ rest := r.PathValue("rest")
+
+ tree, err := g.gitService.GetTree(name, ref, rest)
+ if err != nil {
+ slog.Error("Error loading tree", "error", err)
+ return
+ }
+
gitList := &templates.GitItemPage{
- Name: name,
- Ref: ref,
- GitItemBase: &templates.GitItemTreePage{},
+ Name: name,
+ Ref: ref,
+ GitItemBase: &templates.GitItemTreePage{
+ CurrentPath: rest,
+ Tree: tree,
+ Ref: ref,
+ Name: name,
+ },
+ }
+ templates.WritePageTemplate(w, gitList)
+}
+
+func (g *GitHandler) Blob(w http.ResponseWriter, r *http.Request) {
+ name := r.PathValue("name")
+ ref := r.PathValue("ref")
+ rest := r.PathValue("rest")
+
+ file, err := g.gitService.GetFileContent(name, ref, rest)
+ if err != nil {
+ slog.Error("Error loading blob", "error", err)
+ return
+ }
+
+ filename := filepath.Base(rest)
+ lexer := GetLexers(filename)
+ style := styles.Get("xcode")
+ formatter := html.New(
+ html.WithLineNumbers(true),
+ )
+ iterator, err := lexer.Tokenise(nil, file)
+ if err != nil {
+ slog.Error("Error tokenise", "error", err)
+ return
+ }
+
+ var code bytes.Buffer
+ err = formatter.Format(&code, style, iterator)
+ if err != nil {
+ slog.Error("Error format", "error", err)
+ return
+ }
+
+ gitList := &templates.GitItemPage{
+ Name: name,
+ Ref: ref,
+ GitItemBase: &templates.GitItemBlobPage{
+ File: rest,
+ Content: code.Bytes(),
+ },
}
templates.WritePageTemplate(w, gitList)
}
@@ -134,3 +196,16 @@ func (g *GitHandler) Log(w http.ResponseWriter, r *http.Request) {
}
templates.WritePageTemplate(w, gitList)
}
+
+func GetLexers(filename string) chroma.Lexer {
+ if filename == "APKBUILD" {
+ return lexers.Get("sh")
+ }
+
+ lexer := lexers.Get(filename)
+
+ if lexer == nil {
+ lexer = lexers.Get("txt")
+ }
+ return lexer
+}
diff --git a/pkg/handler/router.go b/pkg/handler/router.go
index bdf883e..ed782f7 100644
--- a/pkg/handler/router.go
+++ b/pkg/handler/router.go
@@ -35,7 +35,8 @@ func MountHandler(
mux.HandleFunc("/{name}/about/{$}", gitHandler.About)
mux.HandleFunc("/{name}", gitHandler.Summary)
mux.HandleFunc("/{name}/refs/{$}", gitHandler.Refs)
- mux.HandleFunc("/{name}/tree/{ref}", gitHandler.Tree)
+ mux.HandleFunc("/{name}/tree/{ref}/{rest...}", gitHandler.Tree)
+ mux.HandleFunc("/{name}/blob/{ref}/{rest...}", gitHandler.Blob)
mux.HandleFunc("/{name}/log/{ref}", gitHandler.Log)
mux.HandleFunc("/config", configHander)
mux.HandleFunc("/about", aboutHandler.About)
diff --git a/pkg/service/git.go b/pkg/service/git.go
index 9bf11f4..f886785 100644
--- a/pkg/service/git.go
+++ b/pkg/service/git.go
@@ -89,6 +89,38 @@ func (g *GitService) ListCommits(name, ref string) ([]*object.Commit, error) {
return repo.Commits()
}
+func (g *GitService) GetTree(name, ref, path string) (*object.Tree, error) {
+ // TODO: handle nil
+ r := g.configRepo.GetByName(name)
+
+ repo, err := git.OpenRepository(r.Path)
+ if err != nil {
+ return nil, err
+ }
+ err = repo.SetRef(ref)
+ if err != nil {
+ return nil, err
+ }
+
+ return repo.Tree(path)
+}
+
+func (g *GitService) GetFileContent(name, ref, path string) (string, error) {
+ // TODO: handle nil
+ r := g.configRepo.GetByName(name)
+
+ repo, err := git.OpenRepository(r.Path)
+ if err != nil {
+ return "", err
+ }
+ err = repo.SetRef(ref)
+ if err != nil {
+ return "", err
+ }
+
+ return repo.FileContent(path)
+}
+
func (g *GitService) ListTags(name string) ([]*object.Tag, error) {
// TODO: handle nil
r := g.configRepo.GetByName(name)