aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGabriel A. Giovanini <mail@gabrielgio.me>2024-06-23 15:20:47 +0200
committerAnirudh Oppiliappan <x@icyphox.sh>2024-06-29 11:16:38 +0300
commitacac8d47d0dd4bab02274f750d22937044bee988 (patch)
tree439bb87c27e9982a594d66531b08180c567d521b
parentgit: Add function to generate tar file from repo (diff)
downloadlegitrx-acac8d47d0dd4bab02274f750d22937044bee988.tar.gz
legitrx-acac8d47d0dd4bab02274f750d22937044bee988.tar.zst
legitrx-acac8d47d0dd4bab02274f750d22937044bee988.zip
routes: Add handler to generate tar gz file
-rw-r--r--routes/handler.go1
-rw-r--r--routes/routes.go53
-rw-r--r--routes/util.go14
3 files changed, 68 insertions, 0 deletions
diff --git a/routes/handler.go b/routes/handler.go
index bbe5e2c..2a35168 100644
--- a/routes/handler.go
+++ b/routes/handler.go
@@ -39,6 +39,7 @@ func Handlers(c *config.Config) *http.ServeMux {
mux.HandleFunc("GET /{name}/tree/{ref}/{rest...}", d.RepoTree)
mux.HandleFunc("GET /{name}/blob/{ref}/{rest...}", d.FileContent)
mux.HandleFunc("GET /{name}/log/{ref}", d.Log)
+ mux.HandleFunc("GET /{name}/archive/{file}", d.Archive)
mux.HandleFunc("GET /{name}/commit/{ref}", d.Diff)
mux.HandleFunc("GET /{name}/refs/{$}", d.Refs)
mux.HandleFunc("GET /{name}/{rest...}", d.Multiplex)
diff --git a/routes/routes.go b/routes/routes.go
index e22c7f9..14dbcf7 100644
--- a/routes/routes.go
+++ b/routes/routes.go
@@ -1,6 +1,7 @@
package routes
import (
+ "compress/gzip"
"fmt"
"html/template"
"log"
@@ -9,6 +10,7 @@ import (
"path/filepath"
"sort"
"strconv"
+ "strings"
"time"
"git.icyphox.sh/legit/config"
@@ -235,6 +237,57 @@ func (d *deps) FileContent(w http.ResponseWriter, r *http.Request) {
return
}
+func (d *deps) Archive(w http.ResponseWriter, r *http.Request) {
+ name := r.PathValue("name")
+ if d.isIgnored(name) {
+ d.Write404(w)
+ return
+ }
+
+ file := r.PathValue("file")
+
+ // TODO: extend this to add more files compression (e.g.: xz)
+ if !strings.HasSuffix(file, ".tar.gz") {
+ d.Write404(w)
+ return
+ }
+
+ ref := strings.TrimSuffix(file, ".tar.gz")
+
+ // This allows the browser to use a proper name for the file when
+ // downloading
+ filename := fmt.Sprintf("%s-%s.tar.gz", name, ref)
+ setContentDisposition(w, filename)
+ setGZipMIME(w)
+
+ path := filepath.Join(d.c.Repo.ScanPath, name)
+ gr, err := git.Open(path, ref)
+ if err != nil {
+ d.Write404(w)
+ return
+ }
+
+ gw := gzip.NewWriter(w)
+ defer gw.Close()
+
+ prefix := fmt.Sprintf("%s-%s", name, ref)
+ err = gr.WriteTar(gw, prefix)
+ if err != nil {
+ // once we start writing to the body we can't report error anymore
+ // so we are only left with printing the error.
+ log.Println(err)
+ return
+ }
+
+ err = gw.Flush()
+ if err != nil {
+ // once we start writing to the body we can't report error anymore
+ // so we are only left with printing the error.
+ log.Println(err)
+ return
+ }
+}
+
func (d *deps) Log(w http.ResponseWriter, r *http.Request) {
name := r.PathValue("name")
if d.isIgnored(name) {
diff --git a/routes/util.go b/routes/util.go
index bc15b7e..1b31b17 100644
--- a/routes/util.go
+++ b/routes/util.go
@@ -3,6 +3,7 @@ package routes
import (
"io/fs"
"log"
+ "net/http"
"os"
"path/filepath"
"strings"
@@ -88,3 +89,16 @@ func (d *deps) getAllRepos() ([]repoInfo, error) {
func (d *deps) category(path string) string {
return strings.TrimPrefix(filepath.Dir(strings.TrimPrefix(path, d.c.Repo.ScanPath)), string(os.PathSeparator))
}
+
+func setContentDisposition(w http.ResponseWriter, name string) {
+ h := "inline; filename=\"" + name + "\""
+ w.Header().Add("Content-Disposition", h)
+}
+
+func setGZipMIME(w http.ResponseWriter) {
+ setMIME(w, "application/gzip")
+}
+
+func setMIME(w http.ResponseWriter, mime string) {
+ w.Header().Add("Content-Type", mime)
+}