diff options
author | Gabriel A. Giovanini <mail@gabrielgio.me> | 2024-06-07 14:02:25 +0200 |
---|---|---|
committer | Gabriel A. Giovanini <mail@gabrielgio.me> | 2024-06-07 14:02:25 +0200 |
commit | 18aa098f50e2a2c7db01dd4d04dde460fd40f5d5 (patch) | |
tree | 5e3b3d3ba3206f2765db1a23a378275852154a51 /pkg | |
parent | d0e0c1eb99303e1000140d4b98c610077278dc42 (diff) | |
download | cerrado-18aa098f50e2a2c7db01dd4d04dde460fd40f5d5.tar.gz cerrado-18aa098f50e2a2c7db01dd4d04dde460fd40f5d5.tar.bz2 cerrado-18aa098f50e2a2c7db01dd4d04dde460fd40f5d5.zip |
feat: Add blob endpoint
Diffstat (limited to 'pkg')
-rw-r--r-- | pkg/git/git.go | 67 | ||||
-rw-r--r-- | pkg/handler/git/handler.go | 81 | ||||
-rw-r--r-- | pkg/handler/router.go | 3 | ||||
-rw-r--r-- | pkg/service/git.go | 32 |
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) |