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.org/core/knotserver/git" 12 xrpcerr "tangled.org/core/xrpc/errors" 13) 14 15func (x *Xrpc) RepoArchive(w http.ResponseWriter, r *http.Request) { 16 repo := r.URL.Query().Get("repo") 17 repoPath, err := x.parseRepoParam(repo) 18 if err != nil { 19 writeError(w, err.(xrpcerr.XrpcError), http.StatusBadRequest) 20 return 21 } 22 23 ref := r.URL.Query().Get("ref") 24 // ref can be empty (git.Open handles this) 25 26 format := r.URL.Query().Get("format") 27 if format == "" { 28 format = "tar.gz" // default 29 } 30 31 prefix := r.URL.Query().Get("prefix") 32 33 if format != "tar.gz" { 34 writeError(w, xrpcerr.NewXrpcError( 35 xrpcerr.WithTag("InvalidRequest"), 36 xrpcerr.WithMessage("only tar.gz format is supported"), 37 ), http.StatusBadRequest) 38 return 39 } 40 41 gr, err := git.Open(repoPath, ref) 42 if err != nil { 43 writeError(w, xrpcerr.RefNotFoundError, http.StatusNotFound) 44 return 45 } 46 47 repoParts := strings.Split(repo, "/") 48 repoName := repoParts[len(repoParts)-1] 49 50 safeRefFilename := strings.ReplaceAll(plumbing.ReferenceName(ref).Short(), "/", "-") 51 52 var archivePrefix string 53 if prefix != "" { 54 archivePrefix = prefix 55 } else { 56 archivePrefix = fmt.Sprintf("%s-%s", repoName, safeRefFilename) 57 } 58 59 filename := fmt.Sprintf("%s-%s.tar.gz", repoName, safeRefFilename) 60 w.Header().Set("Content-Disposition", fmt.Sprintf("attachment; filename=\"%s\"", filename)) 61 w.Header().Set("Content-Type", "application/gzip") 62 63 gw := gzip.NewWriter(w) 64 defer gw.Close() 65 66 err = gr.WriteTar(gw, archivePrefix) 67 if err != nil { 68 // once we start writing to the body we can't report error anymore 69 // so we are only left with logging the error 70 x.Logger.Error("writing tar file", "error", err.Error()) 71 return 72 } 73 74 err = gw.Flush() 75 if err != nil { 76 // once we start writing to the body we can't report error anymore 77 // so we are only left with logging the error 78 x.Logger.Error("flushing", "error", err.Error()) 79 return 80 } 81}