This repository has no description
1.7 kB
60 lines
1package xrpc
2
3import (
4 "fmt"
5 "net/http"
6
7 "tangled.org/core/api/tangled"
8 "tangled.org/core/gitutil"
9 "tangled.org/core/knotserver/git"
10 xrpcerr "tangled.org/core/xrpc/errors"
11)
12
13func (x *Xrpc) RepoArchive(w http.ResponseWriter, r *http.Request) {
14 params, err := gitutil.ParseArchiveParams(r.URL.Query())
15 if err != nil {
16 writeError(w, xrpcerr.NewXrpcError(
17 xrpcerr.WithTag("InvalidRequest"),
18 xrpcerr.WithMessage(err.Error()),
19 ), http.StatusBadRequest)
20 return
21 }
22
23 repo := r.URL.Query().Get("repo")
24 resolved, err := x.resolveRepo(repo)
25 if err != nil {
26 writeError(w, err.(xrpcerr.XrpcError), http.StatusBadRequest)
27 return
28 }
29
30 // ref can be empty (git.Open handles this)
31 gr, err := git.Open(resolved.path, params.Rev.String())
32 if err != nil {
33 writeError(w, xrpcerr.RefNotFoundError, http.StatusNotFound)
34 return
35 }
36
37 hash := gr.Hash()
38 params.Rev = params.Rev.OrHash(hash)
39 params.Prefix = params.Prefix.OrDefault(resolved.name, params.Rev)
40
41 params.SetHeaders(w.Header(), resolved.name)
42 w.Header().Set("Link", gitutil.ImmutableLink(
43 x.archiveURL(repo, params.WithRev(gitutil.RevFromHash(hash))),
44 ))
45
46 if err := gitutil.WriteArchive(r.Context(), w, resolved.path, gitutil.RevFromHash(hash), params.Format, params.Prefix); err != nil {
47 // once we start writing to the body we can't report error anymore
48 // so we are only left with logging the error
49 x.Logger.Error("writing archive", "error", err.Error(), "format", params.Format)
50 }
51}
52
53func (x *Xrpc) archiveURL(repo string, params gitutil.ArchiveParams) string {
54 scheme := "https"
55 if x.Config.Server.Dev {
56 scheme = "http"
57 }
58 return fmt.Sprintf("%s://%s/xrpc/%s?%s",
59 scheme, x.Config.Server.Hostname, tangled.RepoArchiveNSID, params.Query(repo).Encode())
60}