···
9
+
securejoin "github.com/cyphar/filepath-securejoin"
10
+
"github.com/go-chi/chi/v5"
11
+
"github.com/go-git/go-git/v5/plumbing"
12
+
"tangled.org/core/knotserver/git"
15
+
func (h *Knot) Archive(w http.ResponseWriter, r *http.Request) {
17
+
did = chi.URLParam(r, "did")
18
+
name = chi.URLParam(r, "name")
19
+
ref = chi.URLParam(r, "ref")
21
+
repo, err := securejoin.SecureJoin(did, name)
23
+
gitError(w, "repository not found", http.StatusNotFound)
24
+
h.l.Error("git: failed to secure join repo path", "handler", "InfoRefs", "error", err)
28
+
repoPath, err := securejoin.SecureJoin(h.c.Repo.ScanPath, repo)
30
+
gitError(w, "repository not found", http.StatusNotFound)
31
+
h.l.Error("git: failed to secure join repo path", "handler", "InfoRefs", "error", err)
35
+
gr, err := git.Open(repoPath, ref)
37
+
immutableLink := fmt.Sprintf(
38
+
"https://%s/%s/%s/archive/%s",
39
+
h.c.Server.Hostname,
45
+
safeRefFilename := strings.ReplaceAll(plumbing.ReferenceName(ref).Short(), "/", "-")
46
+
filename := fmt.Sprintf("%s-%s.tar.gz", name, safeRefFilename)
47
+
w.Header().Set("Content-Disposition", fmt.Sprintf("attachment; filename=\"%s\"", filename))
48
+
w.Header().Set("Content-Type", "application/gzip")
49
+
w.Header().Set("Link", fmt.Sprintf("<%s>; rel=\"immutable\"", immutableLink))
51
+
gw := gzip.NewWriter(w)
54
+
err = gr.WriteTar(gw, "")
56
+
// once we start writing to the body we can't report error anymore
57
+
// so we are only left with logging the error
58
+
h.l.Error("writing tar file", "error", err)
64
+
// once we start writing to the body we can't report error anymore
65
+
// so we are only left with logging the error
66
+
h.l.Error("flushing", "error", err.Error())