-81
knotserver/xrpc/repo_archive.go
-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
-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)