diff --git a/knotmirror/xrpc/git_get_blob.go b/knotmirror/xrpc/git_get_blob.go index 8f5fea76..05e04af3 100644 --- a/knotmirror/xrpc/git_get_blob.go +++ b/knotmirror/xrpc/git_get_blob.go @@ -37,7 +37,24 @@ func (x *Xrpc) GetBlob(w http.ResponseWriter, r *http.Request) { return } - size, reader, err := x.getFile(r.Context(), repo, ref, path) + ctx := r.Context() + + repoPath, err := x.makeRepoPath(ctx, repo) + if err != nil { + writeJson(w, http.StatusNotFound, atclient.ErrorBody{Name: "RepoNotFound", Message: fmt.Sprintf("unknown repository: %s", repo)}) + return + } + + entry, err := x.getFile(ctx, repoPath, ref, path) + if err != nil { + l.Warn("local mirror failed, trying proxy", "err", err) + if x.proxyToKnot(w, r, repo) { + return + } + writeJson(w, http.StatusInternalServerError, atclient.ErrorBody{Name: "InternalServerError", Message: "failed to get blob"}) + return + } + size, reader, err := gitea.ReadBlob(ctx, repoPath, entry.Hash) if err != nil { l.Warn("local mirror failed, trying proxy", "err", err) if x.proxyToKnot(w, r, repo) { @@ -100,12 +117,7 @@ func (x *Xrpc) GetBlob(w http.ResponseWriter, r *http.Request) { w.Write(contents) } -func (x *Xrpc) getFile(ctx context.Context, repo syntax.DID, ref, path string) (int64, io.ReadCloser, error) { - repoPath, err := x.makeRepoPath(ctx, repo) - if err != nil { - return 0, nil, fmt.Errorf("resolving repo did: %w", err) - } - +func (x *Xrpc) getFile(ctx context.Context, repoPath, ref, path string) (*object.TreeEntry, error) { rev := ref if rev == "" { rev = "HEAD" @@ -113,7 +125,7 @@ func (x *Xrpc) getFile(ctx context.Context, repo syntax.DID, ref, path string) ( head, err := gitea.GetCommit(ctx, repoPath, rev) if err != nil { - return 0, nil, fmt.Errorf("get head commit: %w", err) + return nil, fmt.Errorf("get head commit: %w", err) } treePath := filepath.Dir(path) @@ -126,7 +138,7 @@ func (x *Xrpc) getFile(ctx context.Context, repo syntax.DID, ref, path string) ( } subTree, err := gitea.GetTree(ctx, repoPath, subRev) if err != nil { - return 0, nil, fmt.Errorf("get subtree %s: %w", subRev, err) + return nil, fmt.Errorf("get subtree %s: %w", subRev, err) } // find entry @@ -139,13 +151,10 @@ func (x *Xrpc) getFile(ctx context.Context, repo syntax.DID, ref, path string) ( return nil, fmt.Errorf("object doesn't exist") }(subTree) if err != nil { - return 0, nil, fmt.Errorf("get file: %w", err) + return nil, fmt.Errorf("get file: %w", err) } - x.logger.Debug("ReadBlob", "name", entry.Name, "mode", entry.Mode.String(), "hash", entry.Hash.String()) - - // find blob - return gitea.ReadBlob(ctx, repoPath, entry.Hash) + return entry, nil } var textualMimeTypes = []string{ diff --git a/knotmirror/xrpc/repo_blob.go b/knotmirror/xrpc/repo_blob.go index 320e49ab..74fa43cc 100644 --- a/knotmirror/xrpc/repo_blob.go +++ b/knotmirror/xrpc/repo_blob.go @@ -12,7 +12,9 @@ import ( "github.com/bluesky-social/indigo/atproto/atclient" "github.com/bluesky-social/indigo/atproto/syntax" + "github.com/go-git/go-git/v5/plumbing/filemode" "tangled.org/core/api/tangled" + "tangled.org/core/knotmirror/xrpc/gitea" "tangled.org/core/knotserver/git" ) @@ -47,11 +49,31 @@ func (x *Xrpc) RepoBlob(w http.ResponseWriter, r *http.Request) { return } - // first check if this path is a submodule - submodule, err := gr.Submodule(path) + ctx := r.Context() + + repoPath, err := x.makeRepoPath(ctx, repo) + if err != nil { + writeJson(w, http.StatusNotFound, atclient.ErrorBody{Name: "RepoNotFound", Message: fmt.Sprintf("unknown repository: %s", repo)}) + return + } + + entry, err := x.getFile(ctx, repoPath, ref, path) if err != nil { - // this is okay, continue and try to treat it as a regular file - } else { + l.Warn("local mirror failed, trying proxy", "err", err) + if x.proxyToKnot(w, r, repo) { + return + } + writeJson(w, http.StatusInternalServerError, atclient.ErrorBody{Name: "InternalServerError", Message: "failed to get blob"}) + return + } + + if entry.Mode == filemode.Submodule { + submodule, err := gr.Submodule(path) + if err != nil { + l.Warn("failed to load submodule", "err", err) + writeJson(w, http.StatusInternalServerError, atclient.ErrorBody{Name: "InternalServerError", Message: "failed to load submodule"}) + return + } writeJson(w, http.StatusOK, tangled.RepoBlob_Output{ Ref: ref, Path: path, @@ -64,7 +86,7 @@ func (x *Xrpc) RepoBlob(w http.ResponseWriter, r *http.Request) { return } - size, reader, err := x.getFile(r.Context(), repo, ref, path) + size, reader, err := gitea.ReadBlob(ctx, repoPath, entry.Hash) if err != nil { l.Warn("local mirror failed, trying proxy", "err", err) if x.proxyToKnot(w, r, repo) {