-41
api/tangled/repoarchive.go
-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
-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)
-55
lexicons/repo/archive.json
-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
-
}