···
+
securejoin "github.com/cyphar/filepath-securejoin"
+
"github.com/go-chi/chi/v5"
+
"github.com/go-git/go-git/v5/plumbing"
+
"tangled.org/core/knotserver/git"
+
func (h *Knot) Archive(w http.ResponseWriter, r *http.Request) {
+
did = chi.URLParam(r, "did")
+
name = chi.URLParam(r, "name")
+
ref = chi.URLParam(r, "ref")
+
repo, err := securejoin.SecureJoin(did, name)
+
gitError(w, "repository not found", http.StatusNotFound)
+
h.l.Error("git: failed to secure join repo path", "handler", "InfoRefs", "error", err)
+
repoPath, err := securejoin.SecureJoin(h.c.Repo.ScanPath, repo)
+
gitError(w, "repository not found", http.StatusNotFound)
+
h.l.Error("git: failed to secure join repo path", "handler", "InfoRefs", "error", err)
+
gr, err := git.Open(repoPath, ref)
+
immutableLink := fmt.Sprintf(
+
"https://%s/%s/%s/archive/%s",
+
safeRefFilename := strings.ReplaceAll(plumbing.ReferenceName(ref).Short(), "/", "-")
+
filename := fmt.Sprintf("%s-%s.tar.gz", name, safeRefFilename)
+
w.Header().Set("Content-Disposition", fmt.Sprintf("attachment; filename=\"%s\"", filename))
+
w.Header().Set("Content-Type", "application/gzip")
+
w.Header().Set("Link", fmt.Sprintf("<%s>; rel=\"immutable\"", immutableLink))
+
gw := gzip.NewWriter(w)
+
err = gr.WriteTar(gw, "")
+
// once we start writing to the body we can't report error anymore
+
// so we are only left with logging the error
+
h.l.Error("writing tar file", "error", err)
+
// once we start writing to the body we can't report error anymore
+
// so we are only left with logging the error
+
h.l.Error("flushing", "error", err.Error())