forked from
tangled.org/core
Monorepo for Tangled — https://tangled.org
1package repo
2
3import (
4 "fmt"
5 "net/http"
6 "net/url"
7 "strings"
8
9 "tangled.org/core/api/tangled"
10 xrpcclient "tangled.org/core/appview/xrpcclient"
11
12 indigoxrpc "github.com/bluesky-social/indigo/xrpc"
13 "github.com/go-chi/chi/v5"
14 "github.com/go-git/go-git/v5/plumbing"
15)
16
17func (rp *Repo) DownloadArchive(w http.ResponseWriter, r *http.Request) {
18 l := rp.logger.With("handler", "DownloadArchive")
19 ref := chi.URLParam(r, "ref")
20 ref, _ = url.PathUnescape(ref)
21 f, err := rp.repoResolver.Resolve(r)
22 if err != nil {
23 l.Error("failed to get repo and knot", "err", err)
24 return
25 }
26 scheme := "http"
27 if !rp.config.Core.Dev {
28 scheme = "https"
29 }
30 host := fmt.Sprintf("%s://%s", scheme, f.Knot)
31 xrpcc := &indigoxrpc.Client{
32 Host: host,
33 }
34 didSlashRepo := f.DidSlashRepo()
35 archiveBytes, err := tangled.RepoArchive(r.Context(), xrpcc, "tar.gz", "", ref, didSlashRepo)
36 if xrpcerr := xrpcclient.HandleXrpcErr(err); xrpcerr != nil {
37 l.Error("failed to call XRPC repo.archive", "err", xrpcerr)
38 rp.pages.Error503(w)
39 return
40 }
41 // Set headers for file download, just pass along whatever the knot specifies
42 safeRefFilename := strings.ReplaceAll(plumbing.ReferenceName(ref).Short(), "/", "-")
43 filename := fmt.Sprintf("%s-%s.tar.gz", f.Name, safeRefFilename)
44 w.Header().Set("Content-Disposition", fmt.Sprintf("attachment; filename=\"%s\"", filename))
45 w.Header().Set("Content-Type", "application/gzip")
46 w.Header().Set("Content-Length", fmt.Sprintf("%d", len(archiveBytes)))
47 // Write the archive data directly
48 w.Write(archiveBytes)
49}