Author | Jakob Wakeling <[email protected]> |
Date | 2023-11-03 10:00:26 |
Commit | d314664e5432e372cc8908e277f84fc373799af6 |
Parent | 7974d70ab064a04f872f70f1bc94555ca333517b |
Implement raw file viewing
Diffstat
M | main.go | | | 1 | + |
M | res/repo/tree.html | | | 8 | +++++++- |
A | src/repo/raw.go | | | 87 | ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
M | src/repo/tree.go | | | 9 | +++++---- |
4 files changed, 100 insertions, 5 deletions
diff --git a/main.go b/main.go index 61921ad..57acc0c 100644 --- a/main.go +++ b/main.go @@ -51,6 +51,7 @@ func main() { h.Path("/{repo}/tree").Methods("GET").HandlerFunc(repo.HandleTree) h.Path("/{repo}/tree/{path:.*}").Methods("GET").HandlerFunc(repo.HandleTree) h.Path("/{repo}/file/{path:.*}").Methods("GET").HandlerFunc(repo.HandleFile) + h.Path("/{repo}/raw/{path:.*}").Methods("GET").HandlerFunc(repo.HandleRaw) h.Path("/{repo}/refs").Methods("GET").HandlerFunc(repo.HandleRefs) h.Path("/{repo}/edit").Methods("GET", "POST").HandlerFunc(repo.HandleEdit) h.Path("/{repo}/info/refs").Methods("GET").HandlerFunc(goit.HandleInfoRefs) diff --git a/res/repo/tree.html b/res/repo/tree.html index f3c8eae..8c2d7d7 100644 --- a/res/repo/tree.html +++ b/res/repo/tree.html @@ -19,7 +19,13 @@ <td>{{.Mode}}</td> <td><a href="/{{$.Name}}/{{.Path}}">{{.Name}}</a></td> <td align="right" {{if .B}}style="padding-right: calc(2ch + 0.4em);"{{end}}>{{.Size}}</td> - <td>log blame raw download</td> + <td> + {{if .RawPath}} + log blame + <a href="/{{$.Name}}/raw/{{.RawPath}}">raw</a> + download + {{end}} + </td> </tr> {{end}} {{else}} diff --git a/src/repo/raw.go b/src/repo/raw.go new file mode 100644 index 0000000..5a16a31 --- /dev/null +++ b/src/repo/raw.go @@ -0,0 +1,87 @@ +package repo + +import ( + "errors" + "io" + "log" + "net/http" + + 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/gorilla/mux" +) + +func HandleRaw(w http.ResponseWriter, r *http.Request) { + auth, user, err := goit.Auth(w, r, true) + if err != nil { + log.Println("[repo/raw]", err.Error()) + goit.HttpError(w, http.StatusInternalServerError) + return + } + + treepath := mux.Vars(r)["path"] + + repo, err := goit.GetRepoByName(mux.Vars(r)["repo"]) + if err != nil { + goit.HttpError(w, http.StatusInternalServerError) + return + } else if repo == nil || (repo.IsPrivate && (!auth || user.Id != repo.OwnerId)) { + goit.HttpError(w, http.StatusNotFound) + return + } + + gr, err := git.PlainOpen(goit.RepoPath(repo.Name)) + if err != nil { + log.Println("[/repo/file]", err.Error()) + goit.HttpError(w, http.StatusInternalServerError) + return + } + + ref, err := gr.Head() + if errors.Is(err, plumbing.ErrReferenceNotFound) { + goit.HttpError(w, http.StatusNotFound) + return + } else if err != nil { + log.Println("[/repo/file]", err.Error()) + goit.HttpError(w, http.StatusInternalServerError) + return + } + + commit, err := gr.CommitObject(ref.Hash()) + if err != nil { + log.Println("[/repo/file]", err.Error()) + goit.HttpError(w, http.StatusInternalServerError) + return + } + + file, err := commit.File(treepath) + if errors.Is(err, object.ErrFileNotFound) { + goit.HttpError(w, http.StatusNotFound) + return + } else if err != nil { + log.Println("[/repo/file]", err.Error()) + goit.HttpError(w, http.StatusInternalServerError) + return + } + + if rc, err := file.Blob.Reader(); err != nil { + log.Println("[/repo/file]", err.Error()) + goit.HttpError(w, http.StatusInternalServerError) + return + } else { + buf := make([]byte, min(file.Size, (10*1024*1024))) + if _, err := rc.Read(buf); err != nil && !errors.Is(err, io.EOF) { + log.Println("[/repo/file]", err.Error()) + goit.HttpError(w, http.StatusInternalServerError) + return + } + + if _, err := w.Write(buf); err != nil { + log.Println("[/repo/file]", err.Error()) + goit.HttpError(w, http.StatusInternalServerError) + return + } + } +} diff --git a/src/repo/tree.go b/src/repo/tree.go index 7fd9c27..9c78912 100644 --- a/src/repo/tree.go +++ b/src/repo/tree.go @@ -31,8 +31,8 @@ func HandleTree(w http.ResponseWriter, r *http.Request) { } type row struct { - Mode, Name, Path, Size string - B bool + Mode, Name, Path, RawPath, Size string + B bool } data := struct { Title, Name, Description, Url string @@ -105,7 +105,7 @@ func HandleTree(w http.ResponseWriter, r *http.Request) { }) for _, v := range tree.Entries { - var fpath, size string + var fpath, rpath, size string if v.Mode&0o40000 == 0 { file, err := tree.File(v.Name) @@ -116,6 +116,7 @@ func HandleTree(w http.ResponseWriter, r *http.Request) { } fpath = path.Join("file", treepath, v.Name) + rpath = path.Join(treepath, v.Name) size = humanize.IBytes(uint64(file.Size)) } else { var dirSize uint64 @@ -141,7 +142,7 @@ func HandleTree(w http.ResponseWriter, r *http.Request) { } data.Files = append(data.Files, row{ - Mode: util.ModeString(uint32(v.Mode)), Name: v.Name, Path: fpath, Size: size, + Mode: util.ModeString(uint32(v.Mode)), Name: v.Name, Path: fpath, RawPath: rpath, Size: size, B: util.If(strings.HasSuffix(size, " B"), true, false), }) }