Monorepo for Tangled tangled.org
2

Configure Feed

Select the types of activity you want to include in your feed.

knotmirror/xrpc: cli based `getArchive`

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

author
Seongmin Lee
committer
Lewis
date (May 29, 2026, 2:50 PM +0300) commit ba3a1a59 parent bcee7195 change-id otrztowu
+23 -25
+23 -25
knotmirror/xrpc/git_get_archive.go
··· 1 1 package xrpc 2 2 3 3 import ( 4 - "compress/gzip" 5 4 "fmt" 6 5 "net/http" 7 6 "net/url" 7 + "os/exec" 8 8 "strings" 9 9 10 10 "github.com/bluesky-social/indigo/atproto/atclient" ··· 12 12 "github.com/go-git/go-git/v5/plumbing" 13 13 "tangled.org/core/api/tangled" 14 14 "tangled.org/core/knotmirror/db" 15 - "tangled.org/core/knotserver/git" 15 + "tangled.org/core/knotmirror/xrpc/gitea" 16 16 ) 17 17 18 18 func (x *Xrpc) GetArchive(w http.ResponseWriter, r *http.Request) { ··· 38 38 } 39 39 40 40 l := x.logger.With("repo", repo, "ref", ref, "format", format, "prefix", prefix) 41 + l.Debug("request") 42 + 41 43 ctx := r.Context() 42 44 43 45 repoPath, err := x.makeRepoPath(ctx, repo) ··· 50 52 return 51 53 } 52 54 53 - gr, err := git.Open(repoPath, ref) 54 - if err != nil { 55 - l.Warn("local mirror failed, trying proxy", "err", err) 56 - if x.proxyToKnot(w, r, repo) { 57 - return 58 - } 59 - writeJson(w, http.StatusInternalServerError, atclient.ErrorBody{Name: "InternalServerError", Message: "failed to open git repo"}) 60 - return 55 + rev := ref 56 + if rev == "" { 57 + rev = "HEAD" 61 58 } 59 + commit, err := gitea.GetCommit(ctx, repoPath, rev) 62 60 63 61 repoName, err := func() (string, error) { 64 62 r, err := db.GetRepoByRepoDid(ctx, x.db, repo) ··· 83 81 immutableLink := func() string { 84 82 params := url.Values{} 85 83 params.Set("repo", repo.String()) 86 - params.Set("ref", gr.Hash().String()) 84 + params.Set("ref", commit.Hash.String()) 87 85 params.Set("format", format) 88 86 params.Set("prefix", prefix) 89 87 return fmt.Sprintf("%s/xrpc/%s?%s", x.cfg.BaseUrl(), tangled.GitTempGetArchiveNSID, params.Encode()) ··· 94 92 w.Header().Set("Content-Type", "application/gzip") 95 93 w.Header().Set("Link", fmt.Sprintf("<%s>; rel=\"immutable\"", immutableLink)) 96 94 97 - gw := gzip.NewWriter(w) 98 - defer gw.Close() 95 + cmd := exec.Command( 96 + "git", 97 + "archive", 98 + fmt.Sprintf("--prefix=%s", prefix), 99 + "--format=tar.gz", 100 + commit.Hash.String(), 101 + ) 99 102 100 - if err := gr.WriteTar(gw, prefix); err != nil { 101 - // once we start writing to the body we can't report error anymore 102 - // so we are only left with logging the error 103 - l.Error("writing tar file", "err", err.Error()) 104 - w.WriteHeader(http.StatusInternalServerError) 105 - return 106 - } 103 + var stderr strings.Builder 104 + cmd.Dir = repoPath 105 + cmd.Stdout = w 106 + cmd.Stderr = &stderr 107 107 108 - if err := gw.Flush(); err != nil { 109 - // once we start writing to the body we can't report error anymore 110 - // so we are only left with logging the error 111 - l.Error("flushing", "err", err.Error()) 108 + if err := cmd.Run(); err != nil { 109 + err = fmt.Errorf("%w\n%s", err, stderr.String()) 110 + l.Error("failed to archive", "err", err) 112 111 w.WriteHeader(http.StatusInternalServerError) 113 - return 114 112 } 115 113 }