Monorepo for Tangled tangled.org

lexicons,knotserver: remove `sh.tangled.repo.archive`

Xrpc is not a good way to implement this as Xrpc clients usually strips
out the response http headers.
The archive should be implemented in raw http endpoint instead like git
https endpoints

Signed-off-by: Seongmin Lee <git@boltless.me>

boltless.me d504541d 9675ae37

verified
Changed files
-178
api
tangled
knotserver
lexicons
-41
api/tangled/repoarchive.go
··· 1 - // Code generated by cmd/lexgen (see Makefile's lexgen); DO NOT EDIT. 2 - 3 - package tangled 4 - 5 - // schema: sh.tangled.repo.archive 6 - 7 - import ( 8 - "bytes" 9 - "context" 10 - 11 - "github.com/bluesky-social/indigo/lex/util" 12 - ) 13 - 14 - const ( 15 - RepoArchiveNSID = "sh.tangled.repo.archive" 16 - ) 17 - 18 - // RepoArchive calls the XRPC method "sh.tangled.repo.archive". 19 - // 20 - // format: Archive format 21 - // prefix: Prefix for files in the archive 22 - // ref: Git reference (branch, tag, or commit SHA) 23 - // repo: Repository identifier in format 'did:plc:.../repoName' 24 - func RepoArchive(ctx context.Context, c util.LexClient, format string, prefix string, ref string, repo string) ([]byte, error) { 25 - buf := new(bytes.Buffer) 26 - 27 - params := map[string]interface{}{} 28 - if format != "" { 29 - params["format"] = format 30 - } 31 - if prefix != "" { 32 - params["prefix"] = prefix 33 - } 34 - params["ref"] = ref 35 - params["repo"] = repo 36 - if err := c.LexDo(ctx, util.Query, "", "sh.tangled.repo.archive", params, nil, buf); err != nil { 37 - return nil, err 38 - } 39 - 40 - return buf.Bytes(), nil 41 - }
-81
knotserver/xrpc/repo_archive.go
··· 1 - package xrpc 2 - 3 - import ( 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 - 15 - func (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 - }
-1
knotserver/xrpc/xrpc.go
··· 64 64 r.Get("/"+tangled.RepoCompareNSID, x.RepoCompare) 65 65 r.Get("/"+tangled.RepoGetDefaultBranchNSID, x.RepoGetDefaultBranch) 66 66 r.Get("/"+tangled.RepoBranchNSID, x.RepoBranch) 67 - r.Get("/"+tangled.RepoArchiveNSID, x.RepoArchive) 68 67 r.Get("/"+tangled.RepoLanguagesNSID, x.RepoLanguages) 69 68 70 69 // knot query endpoints (no auth required)
-55
lexicons/repo/archive.json
··· 1 - { 2 - "lexicon": 1, 3 - "id": "sh.tangled.repo.archive", 4 - "defs": { 5 - "main": { 6 - "type": "query", 7 - "parameters": { 8 - "type": "params", 9 - "required": ["repo", "ref"], 10 - "properties": { 11 - "repo": { 12 - "type": "string", 13 - "description": "Repository identifier in format 'did:plc:.../repoName'" 14 - }, 15 - "ref": { 16 - "type": "string", 17 - "description": "Git reference (branch, tag, or commit SHA)" 18 - }, 19 - "format": { 20 - "type": "string", 21 - "description": "Archive format", 22 - "enum": ["tar", "zip", "tar.gz", "tar.bz2", "tar.xz"], 23 - "default": "tar.gz" 24 - }, 25 - "prefix": { 26 - "type": "string", 27 - "description": "Prefix for files in the archive" 28 - } 29 - } 30 - }, 31 - "output": { 32 - "encoding": "*/*", 33 - "description": "Binary archive data" 34 - }, 35 - "errors": [ 36 - { 37 - "name": "RepoNotFound", 38 - "description": "Repository not found or access denied" 39 - }, 40 - { 41 - "name": "RefNotFound", 42 - "description": "Git reference not found" 43 - }, 44 - { 45 - "name": "InvalidRequest", 46 - "description": "Invalid request parameters" 47 - }, 48 - { 49 - "name": "ArchiveError", 50 - "description": "Failed to create archive" 51 - } 52 - ] 53 - } 54 - } 55 - }