Author | Jakob Wakeling <[email protected]> |
Date | 2023-08-02 09:44:07 |
Commit | 7ba1b21b11fb9266c475104434c93714b2b67af9 |
Parent | 5aa454cedeed0b7d4c4e48142cdac4d3793fdd7b |
Add README and LICENCE links in repo header
Diffstat
M | README.md | | | 2 | +- |
M | res/repo/header.html | | | 4 | ++-- |
M | src/repo/file.go | | | 8 | ++++++++ |
M | src/repo/log.go | | | 26 | +++++++++++++++++++------- |
M | src/repo/repo.go | | | 60 | ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
M | src/repo/tree.go | | | 7 | +++++++ |
6 files changed, 97 insertions, 10 deletions
diff --git a/README.md b/README.md index 6f5616e..cbcde10 100644 --- a/README.md +++ b/README.md @@ -7,7 +7,7 @@ A simple and lightweight Git web server. - Git Smart HTTP protocol (v2 only) - Git SSH protocol (planned) - Repository log, tree, refs, and commit viewers -- File viewer with syntax highlighting and markdown support (planned) +- File viewer with syntax highlighting (planned) - File raw, blame, and history views (planned) - Public and private repositories - Read and write permissions for non owners (planned) diff --git a/res/repo/header.html b/res/repo/header.html index 3d249a1..c59fbae 100644 --- a/res/repo/header.html +++ b/res/repo/header.html @@ -19,10 +19,10 @@ | <a href="/{{.Name}}/tree">Tree</a> | <a href="/{{.Name}}/refs">Refs</a> {{if .Readme}} - | <a href="">README</a> + | <a href="{{.Readme}}">README</a> {{end}} {{if .Licence}} - | <a href="">LICENCE</a> + | <a href="{{.Licence}}">LICENCE</a> {{end}} </td> </tr> diff --git a/src/repo/file.go b/src/repo/file.go index e19dadd..09e3979 100644 --- a/src/repo/file.go +++ b/src/repo/file.go @@ -5,6 +5,7 @@ import ( "io" "log" "net/http" + "path" "strings" goit "github.com/Jamozed/Goit/src" @@ -61,6 +62,13 @@ func HandleFile(w http.ResponseWriter, r *http.Request) { return } + if readme, _ := findReadme(gr, ref); readme != "" { + data.Readme = path.Join("/", repo.Name, "file", readme) + } + if licence, _ := findLicence(gr, ref); licence != "" { + data.Licence = path.Join("/", repo.Name, "file", licence) + } + commit, err := gr.CommitObject(ref.Hash()) if err != nil { log.Println("[/repo/file]", err.Error()) diff --git a/src/repo/log.go b/src/repo/log.go index 01f63ef..ab408d6 100644 --- a/src/repo/log.go +++ b/src/repo/log.go @@ -5,6 +5,7 @@ import ( "fmt" "log" "net/http" + "path" "strings" "time" @@ -55,13 +56,23 @@ func HandleLog(w http.ResponseWriter, r *http.Request) { return } - if ref, err := gr.Head(); err != nil { - if !errors.Is(err, plumbing.ErrReferenceNotFound) { - log.Println("[/repo/log]", err.Error()) - goit.HttpError(w, http.StatusInternalServerError) - return - } - } else if iter, err := gr.Log(&git.LogOptions{From: ref.Hash()}); err != nil { + ref, err := gr.Head() + if errors.Is(err, plumbing.ErrReferenceNotFound) { + goto execute + } else if err != nil { + log.Println("[/repo/log]", err.Error()) + goit.HttpError(w, http.StatusInternalServerError) + return + } + + if readme, _ := findReadme(gr, ref); readme != "" { + data.Readme = path.Join("/", repo.Name, "file", readme) + } + if licence, _ := findLicence(gr, ref); licence != "" { + data.Licence = path.Join("/", repo.Name, "file", licence) + } + + if iter, err := gr.Log(&git.LogOptions{From: ref.Hash()}); err != nil { log.Println("[/repo/log]", err.Error()) goit.HttpError(w, http.StatusInternalServerError) return @@ -90,6 +101,7 @@ func HandleLog(w http.ResponseWriter, r *http.Request) { return } +execute: if err := goit.Tmpl.ExecuteTemplate(w, "repo/log", data); err != nil { log.Println("[/repo/log]", err.Error()) } diff --git a/src/repo/repo.go b/src/repo/repo.go index 3299296..f118a21 100644 --- a/src/repo/repo.go +++ b/src/repo/repo.go @@ -3,11 +3,19 @@ package repo import ( "log" "net/http" + "regexp" "strconv" goit "github.com/Jamozed/Goit/src" + "github.com/go-git/go-git/v5" + "github.com/go-git/go-git/v5/plumbing" + "github.com/go-git/go-git/v5/plumbing/object" + "github.com/go-git/go-git/v5/plumbing/storer" ) +var readmePattern = regexp.MustCompile(`(?i)^readme(?:\.?(?:md|txt))?$`) +var licencePattern = regexp.MustCompile(`(?i)^licence(?:\.?(?:md|txt))?$`) + func HandleDelete(w http.ResponseWriter, r *http.Request) { auth, admin, uid := goit.AuthCookieAdmin(w, r, true) @@ -37,3 +45,55 @@ func HandleDelete(w http.ResponseWriter, r *http.Request) { http.Redirect(w, r, "/", http.StatusFound) } + +func findReadme(gr *git.Repository, ref *plumbing.Reference) (string, error) { + commit, err := gr.CommitObject(ref.Hash()) + if err != nil { + return "", err + } + + iter, err := commit.Files() + if err != nil { + return "", err + } + + var filename string + if err := iter.ForEach(func(f *object.File) error { + if readmePattern.MatchString(f.Name) { + filename = f.Name + return storer.ErrStop + } + + return nil + }); err != nil { + return "", err + } + + return filename, nil +} + +func findLicence(gr *git.Repository, ref *plumbing.Reference) (string, error) { + commit, err := gr.CommitObject(ref.Hash()) + if err != nil { + return "", err + } + + iter, err := commit.Files() + if err != nil { + return "", err + } + + var filename string + if err := iter.ForEach(func(f *object.File) error { + if licencePattern.MatchString(f.Name) { + filename = f.Name + return storer.ErrStop + } + + return nil + }); err != nil { + return "", err + } + + return filename, nil +} diff --git a/src/repo/tree.go b/src/repo/tree.go index 36dba07..8709225 100644 --- a/src/repo/tree.go +++ b/src/repo/tree.go @@ -57,6 +57,13 @@ func HandleTree(w http.ResponseWriter, r *http.Request) { return } } else { + if readme, _ := findReadme(gr, ref); readme != "" { + data.Readme = path.Join("/", repo.Name, "file", readme) + } + if licence, _ := findLicence(gr, ref); licence != "" { + data.Licence = path.Join("/", repo.Name, "file", licence) + } + commit, err := gr.CommitObject(ref.Hash()) if err != nil { log.Println("[/repo/tree]", err.Error())