forked from tangled.org/core
Monorepo for Tangled — https://tangled.org
at master 1.5 kB view raw
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}