this repo has no description
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 := 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.NewXrpcError( 44 xrpcerr.WithTag("RefNotFound"), 45 xrpcerr.WithMessage("repository or ref not found"), 46 ), http.StatusNotFound) 47 return 48 } 49 50 repoParts := strings.Split(repo, "/") 51 repoName := repoParts[len(repoParts)-1] 52 53 safeRefFilename := strings.ReplaceAll(plumbing.ReferenceName(ref).Short(), "/", "-") 54 55 var archivePrefix string 56 if prefix != "" { 57 archivePrefix = prefix 58 } else { 59 archivePrefix = fmt.Sprintf("%s-%s", repoName, safeRefFilename) 60 } 61 62 filename := fmt.Sprintf("%s-%s.tar.gz", repoName, safeRefFilename) 63 w.Header().Set("Content-Disposition", fmt.Sprintf("attachment; filename=\"%s\"", filename)) 64 w.Header().Set("Content-Type", "application/gzip") 65 66 gw := gzip.NewWriter(w) 67 defer gw.Close() 68 69 err = gr.WriteTar(gw, archivePrefix) 70 if err != nil { 71 // once we start writing to the body we can't report error anymore 72 // so we are only left with logging the error 73 x.Logger.Error("writing tar file", "error", err.Error()) 74 return 75 } 76 77 err = gw.Flush() 78 if err != nil { 79 // once we start writing to the body we can't report error anymore 80 // so we are only left with logging the error 81 x.Logger.Error("flushing", "error", err.Error()) 82 return 83 } 84}