+33
api/tangled/reporesolveRef.go
+33
api/tangled/reporesolveRef.go
···
1
+
// Code generated by cmd/lexgen (see Makefile's lexgen); DO NOT EDIT.
2
+
3
+
package tangled
4
+
5
+
// schema: sh.tangled.repo.resolveRef
6
+
7
+
import (
8
+
"bytes"
9
+
"context"
10
+
11
+
"github.com/bluesky-social/indigo/lex/util"
12
+
)
13
+
14
+
const (
15
+
RepoResolveRefNSID = "sh.tangled.repo.resolveRef"
16
+
)
17
+
18
+
// RepoResolveRef calls the XRPC method "sh.tangled.repo.resolveRef".
19
+
//
20
+
// ref: Reference name (branch, tag or other references)
21
+
// repo: Repository identifier in format 'did:plc:.../repoName'
22
+
func RepoResolveRef(ctx context.Context, c util.LexClient, ref string, repo string) ([]byte, error) {
23
+
buf := new(bytes.Buffer)
24
+
25
+
params := map[string]interface{}{}
26
+
params["ref"] = ref
27
+
params["repo"] = repo
28
+
if err := c.LexDo(ctx, util.Query, "", "sh.tangled.repo.resolveRef", params, nil, buf); err != nil {
29
+
return nil, err
30
+
}
31
+
32
+
return buf.Bytes(), nil
33
+
}
+18
-1
appview/repo/repo.go
+18
-1
appview/repo/repo.go
···
110
110
}
111
111
112
112
repo := fmt.Sprintf("%s/%s", f.OwnerDid(), f.Name)
113
-
archiveBytes, err := tangled.RepoArchive(r.Context(), xrpcc, "tar.gz", "", ref, repo)
113
+
// TODO: we are requesting the knot twice here to get permanent commit-hash.
114
+
// This should purely handled from knot instead.
115
+
rawHash, err := tangled.RepoResolveRef(r.Context(), xrpcc, ref, repo)
116
+
if xrpcerr := xrpcclient.HandleXrpcErr(err); xrpcerr != nil {
117
+
l.Error("failed to call XRPC repo.archive", "err", xrpcerr)
118
+
rp.pages.Error503(w)
119
+
return
120
+
}
121
+
hash := string(rawHash)
122
+
immutableLink := fmt.Sprintf(
123
+
"%s/%s/archive/%s",
124
+
rp.config.Core.AppviewHost,
125
+
repo,
126
+
hash,
127
+
)
128
+
129
+
archiveBytes, err := tangled.RepoArchive(r.Context(), xrpcc, "tar.gz", "", hash, repo)
114
130
if xrpcerr := xrpcclient.HandleXrpcErr(err); xrpcerr != nil {
115
131
l.Error("failed to call XRPC repo.archive", "err", xrpcerr)
116
132
rp.pages.Error503(w)
···
123
139
w.Header().Set("Content-Disposition", fmt.Sprintf("attachment; filename=\"%s\"", filename))
124
140
w.Header().Set("Content-Type", "application/gzip")
125
141
w.Header().Set("Content-Length", fmt.Sprintf("%d", len(archiveBytes)))
142
+
w.Header().Set("Link", fmt.Sprintf("<%s>; rel=\"immutable\"", immutableLink))
126
143
127
144
// Write the archive data directly
128
145
w.Write(archiveBytes)
+4
knotserver/git/git.go
+4
knotserver/git/git.go
+31
knotserver/xrpc/repo_resolve_ref.go
+31
knotserver/xrpc/repo_resolve_ref.go
···
1
+
package xrpc
2
+
3
+
import (
4
+
"fmt"
5
+
"net/http"
6
+
7
+
"tangled.org/core/knotserver/git"
8
+
xrpcerr "tangled.org/core/xrpc/errors"
9
+
)
10
+
11
+
func (x *Xrpc) RepoResolveRef(w http.ResponseWriter, r *http.Request) {
12
+
repo := r.URL.Query().Get("repo")
13
+
repoPath, err := x.parseRepoParam(repo)
14
+
if err != nil {
15
+
writeError(w, err.(xrpcerr.XrpcError), http.StatusBadRequest)
16
+
return
17
+
}
18
+
19
+
ref := r.URL.Query().Get("ref")
20
+
// ref can be empty (git.Open handles this)
21
+
22
+
gr, err := git.Open(repoPath, ref)
23
+
if err != nil {
24
+
x.Logger.Error("failed to open", "error", err)
25
+
writeError(w, xrpcerr.RefNotFoundError, http.StatusNotFound)
26
+
return
27
+
}
28
+
29
+
w.Header().Set("Content-Type", "text/plain")
30
+
fmt.Fprint(w, gr.Hash().String())
31
+
}
+1
knotserver/xrpc/xrpc.go
+1
knotserver/xrpc/xrpc.go
···
66
66
r.Get("/"+tangled.RepoBranchNSID, x.RepoBranch)
67
67
r.Get("/"+tangled.RepoArchiveNSID, x.RepoArchive)
68
68
r.Get("/"+tangled.RepoLanguagesNSID, x.RepoLanguages)
69
+
r.Get("/"+tangled.RepoResolveRefNSID, x.RepoResolveRef)
69
70
70
71
// knot query endpoints (no auth required)
71
72
r.Get("/"+tangled.KnotListKeysNSID, x.ListKeys)
+42
lexicons/repo/resolveRef.json
+42
lexicons/repo/resolveRef.json
···
1
+
{
2
+
"lexicon": 1,
3
+
"id": "sh.tangled.repo.resolveRef",
4
+
"defs": {
5
+
"main": {
6
+
"type": "query",
7
+
"description": "Resolve a ref to its corresponding commit hash",
8
+
"parameters": {
9
+
"type": "params",
10
+
"required": ["repo", "ref"],
11
+
"properties": {
12
+
"repo": {
13
+
"type": "string",
14
+
"description": "Repository identifier in format 'did:plc:.../repoName'"
15
+
},
16
+
"ref": {
17
+
"type": "string",
18
+
"description": "Reference name (branch, tag or other references)"
19
+
}
20
+
}
21
+
},
22
+
"output": {
23
+
"encoding": "*/*",
24
+
"description": "Resolved hash"
25
+
},
26
+
"errors": [
27
+
{
28
+
"name": "RepoNotFound",
29
+
"description": "Repository not found or access denied"
30
+
},
31
+
{
32
+
"name": "RefNotFound",
33
+
"description": "Ref not found"
34
+
},
35
+
{
36
+
"name": "InvalidRequest",
37
+
"description": "Invalid request parameters"
38
+
}
39
+
]
40
+
}
41
+
}
42
+
}