forked from tangled.org/core
this repo has no description
at master 2.0 kB view raw
1package xrpc 2 3import ( 4 "compress/gzip" 5 "fmt" 6 "net/http" 7 "strings" 8 9 "github.com/go-git/go-git/v5/plumbing" 10 11 "tangled.sh/tangled.sh/core/knotserver/git" 12 xrpcerr "tangled.sh/tangled.sh/core/xrpc/errors" 13) 14 15func (x *Xrpc) RepoArchive(w http.ResponseWriter, r *http.Request) { 16 repo, repoPath, unescapedRef, err := x.parseStandardParams(r) 17 if err != nil { 18 writeError(w, err.(xrpcerr.XrpcError), http.StatusBadRequest) 19 return 20 } 21 22 format := r.URL.Query().Get("format") 23 if format == "" { 24 format = "tar.gz" // default 25 } 26 27 prefix := r.URL.Query().Get("prefix") 28 29 if format != "tar.gz" { 30 writeError(w, xrpcerr.NewXrpcError( 31 xrpcerr.WithTag("InvalidRequest"), 32 xrpcerr.WithMessage("only tar.gz format is supported"), 33 ), http.StatusBadRequest) 34 return 35 } 36 37 gr, err := git.Open(repoPath, unescapedRef) 38 if err != nil { 39 writeError(w, xrpcerr.NewXrpcError( 40 xrpcerr.WithTag("RefNotFound"), 41 xrpcerr.WithMessage("repository or ref not found"), 42 ), http.StatusNotFound) 43 return 44 } 45 46 repoParts := strings.Split(repo, "/") 47 repoName := repoParts[len(repoParts)-1] 48 49 safeRefFilename := strings.ReplaceAll(plumbing.ReferenceName(unescapedRef).Short(), "/", "-") 50 51 var archivePrefix string 52 if prefix != "" { 53 archivePrefix = prefix 54 } else { 55 archivePrefix = fmt.Sprintf("%s-%s", repoName, safeRefFilename) 56 } 57 58 filename := fmt.Sprintf("%s-%s.tar.gz", repoName, safeRefFilename) 59 w.Header().Set("Content-Disposition", fmt.Sprintf("attachment; filename=\"%s\"", filename)) 60 w.Header().Set("Content-Type", "application/gzip") 61 62 gw := gzip.NewWriter(w) 63 defer gw.Close() 64 65 err = gr.WriteTar(gw, archivePrefix) 66 if err != nil { 67 // once we start writing to the body we can't report error anymore 68 // so we are only left with logging the error 69 x.Logger.Error("writing tar file", "error", err.Error()) 70 return 71 } 72 73 err = gw.Flush() 74 if err != nil { 75 // once we start writing to the body we can't report error anymore 76 // so we are only left with logging the error 77 x.Logger.Error("flushing", "error", err.Error()) 78 return 79 } 80}