forked from
tangled.org/core
Monorepo for Tangled — https://tangled.org
1package knotserver
2
3import (
4 "compress/gzip"
5 "fmt"
6 "net/http"
7 "strings"
8
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"
13)
14
15func (h *Knot) Archive(w http.ResponseWriter, r *http.Request) {
16 var (
17 did = chi.URLParam(r, "did")
18 name = chi.URLParam(r, "name")
19 ref = chi.URLParam(r, "ref")
20 )
21 repo, err := securejoin.SecureJoin(did, name)
22 if err != nil {
23 gitError(w, "repository not found", http.StatusNotFound)
24 h.l.Error("git: failed to secure join repo path", "handler", "InfoRefs", "error", err)
25 return
26 }
27
28 repoPath, err := securejoin.SecureJoin(h.c.Repo.ScanPath, repo)
29 if err != nil {
30 gitError(w, "repository not found", http.StatusNotFound)
31 h.l.Error("git: failed to secure join repo path", "handler", "InfoRefs", "error", err)
32 return
33 }
34
35 gr, err := git.Open(repoPath, ref)
36
37 immutableLink := fmt.Sprintf(
38 "https://%s/%s/%s/archive/%s",
39 h.c.Server.Hostname,
40 did,
41 name,
42 gr.Hash(),
43 )
44
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))
50
51 gw := gzip.NewWriter(w)
52 defer gw.Close()
53
54 err = gr.WriteTar(gw, "")
55 if err != nil {
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)
59 return
60 }
61
62 err = gw.Flush()
63 if err != nil {
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())
67 return
68 }
69}