appview: directly inherit Repo on ResolvedRepo #392

merged
opened by boltless.me targeting master from boltless.me/core: ref/inherit-repo
  • reduce duplicated codes
  • possibly remove/refactor ResolvedRepo in future
  • allow accessing db.Repo after it is resolved
Changed files
+65 -101
appview
db
issues
middleware
repo
reporesolver
state
+19 -19
appview/issues/issues.go
···
return
}
-
issue, comments, err := db.GetIssueWithComments(rp.db, f.RepoAt, issueIdInt)
+
issue, comments, err := db.GetIssueWithComments(rp.db, f.RepoAt(), issueIdInt)
if err != nil {
log.Println("failed to get issue and comments", err)
rp.pages.Notice(w, "issues", "Failed to load issue. Try again later.")
···
return
}
-
issue, err := db.GetIssue(rp.db, f.RepoAt, issueIdInt)
+
issue, err := db.GetIssue(rp.db, f.RepoAt(), issueIdInt)
if err != nil {
log.Println("failed to get issue", err)
rp.pages.Notice(w, "issue-action", "Failed to close issue. Try again later.")
···
return
}
-
err = db.CloseIssue(rp.db, f.RepoAt, issueIdInt)
+
err = db.CloseIssue(rp.db, f.RepoAt(), issueIdInt)
if err != nil {
log.Println("failed to close issue", err)
rp.pages.Notice(w, "issue-action", "Failed to close issue. Try again later.")
···
return
}
-
issue, err := db.GetIssue(rp.db, f.RepoAt, issueIdInt)
+
issue, err := db.GetIssue(rp.db, f.RepoAt(), issueIdInt)
if err != nil {
log.Println("failed to get issue", err)
rp.pages.Notice(w, "issue-action", "Failed to close issue. Try again later.")
···
isIssueOwner := user.Did == issue.OwnerDid
if isCollaborator || isIssueOwner {
-
err := db.ReopenIssue(rp.db, f.RepoAt, issueIdInt)
+
err := db.ReopenIssue(rp.db, f.RepoAt(), issueIdInt)
if err != nil {
log.Println("failed to reopen issue", err)
rp.pages.Notice(w, "issue-action", "Failed to reopen issue. Try again later.")
···
err := db.NewIssueComment(rp.db, &db.Comment{
OwnerDid: user.Did,
-
RepoAt: f.RepoAt,
+
RepoAt: f.RepoAt(),
Issue: issueIdInt,
CommentId: commentId,
Body: body,
···
createdAt := time.Now().Format(time.RFC3339)
commentIdInt64 := int64(commentId)
ownerDid := user.Did
-
issueAt, err := db.GetIssueAt(rp.db, f.RepoAt, issueIdInt)
+
issueAt, err := db.GetIssueAt(rp.db, f.RepoAt(), issueIdInt)
if err != nil {
log.Println("failed to get issue at", err)
rp.pages.Notice(w, "issue-comment", "Failed to create comment.")
return
}
-
atUri := f.RepoAt.String()
+
atUri := f.RepoAt().String()
client, err := rp.oauth.AuthorizedClient(r)
if err != nil {
log.Println("failed to get authorized client", err)
···
return
}
-
issue, err := db.GetIssue(rp.db, f.RepoAt, issueIdInt)
+
issue, err := db.GetIssue(rp.db, f.RepoAt(), issueIdInt)
if err != nil {
log.Println("failed to get issue", err)
rp.pages.Notice(w, "issues", "Failed to load issue. Try again later.")
return
}
-
comment, err := db.GetComment(rp.db, f.RepoAt, issueIdInt, commentIdInt)
+
comment, err := db.GetComment(rp.db, f.RepoAt(), issueIdInt, commentIdInt)
if err != nil {
http.Error(w, "bad comment id", http.StatusBadRequest)
return
···
return
}
-
issue, err := db.GetIssue(rp.db, f.RepoAt, issueIdInt)
+
issue, err := db.GetIssue(rp.db, f.RepoAt(), issueIdInt)
if err != nil {
log.Println("failed to get issue", err)
rp.pages.Notice(w, "issues", "Failed to load issue. Try again later.")
return
}
-
comment, err := db.GetComment(rp.db, f.RepoAt, issueIdInt, commentIdInt)
+
comment, err := db.GetComment(rp.db, f.RepoAt(), issueIdInt, commentIdInt)
if err != nil {
http.Error(w, "bad comment id", http.StatusBadRequest)
return
···
return
}
-
issue, err := db.GetIssue(rp.db, f.RepoAt, issueIdInt)
+
issue, err := db.GetIssue(rp.db, f.RepoAt(), issueIdInt)
if err != nil {
log.Println("failed to get issue", err)
rp.pages.Notice(w, "issues", "Failed to load issue. Try again later.")
···
return
}
-
comment, err := db.GetComment(rp.db, f.RepoAt, issueIdInt, commentIdInt)
+
comment, err := db.GetComment(rp.db, f.RepoAt(), issueIdInt, commentIdInt)
if err != nil {
http.Error(w, "bad comment id", http.StatusBadRequest)
return
···
// optimistic deletion
deleted := time.Now()
-
err = db.DeleteComment(rp.db, f.RepoAt, issueIdInt, commentIdInt)
+
err = db.DeleteComment(rp.db, f.RepoAt(), issueIdInt, commentIdInt)
if err != nil {
log.Println("failed to delete comment")
rp.pages.Notice(w, fmt.Sprintf("comment-%s-status", commentId), "failed to delete comment")
···
return
}
-
issues, err := db.GetIssues(rp.db, f.RepoAt, isOpen, page)
+
issues, err := db.GetIssues(rp.db, f.RepoAt(), isOpen, page)
if err != nil {
log.Println("failed to get issues", err)
rp.pages.Notice(w, "issues", "Failed to load issues. Try again later.")
···
}
issue := &db.Issue{
-
RepoAt: f.RepoAt,
+
RepoAt: f.RepoAt(),
Title: title,
Body: body,
OwnerDid: user.Did,
···
rp.pages.Notice(w, "issues", "Failed to create issue.")
return
}
-
atUri := f.RepoAt.String()
+
atUri := f.RepoAt().String()
resp, err := client.RepoPutRecord(r.Context(), &comatproto.RepoPutRecord_Input{
Collection: tangled.RepoIssueNSID,
Repo: user.Did,
···
return
}
-
err = db.SetIssueAt(rp.db, f.RepoAt, issue.IssueId, resp.Uri)
+
err = db.SetIssueAt(rp.db, f.RepoAt(), issue.IssueId, resp.Uri)
if err != nil {
log.Println("failed to set issue at", err)
rp.pages.Notice(w, "issues", "Failed to create issue.")
+3 -8
appview/middleware/middleware.go
···
"slices"
"strconv"
"strings"
-
"time"
"github.com/bluesky-social/indigo/atproto/identity"
"github.com/go-chi/chi/v5"
···
return
}
-
ctx := context.WithValue(req.Context(), "knot", repo.Knot)
-
ctx = context.WithValue(ctx, "repoAt", repo.AtUri)
-
ctx = context.WithValue(ctx, "repoDescription", repo.Description)
-
ctx = context.WithValue(ctx, "repoSpindle", repo.Spindle)
-
ctx = context.WithValue(ctx, "repoAddedAt", repo.Created.Format(time.RFC3339))
+
ctx := context.WithValue(req.Context(), "repo", repo)
next.ServeHTTP(w, req.WithContext(ctx))
})
}
···
return
}
-
pr, err := db.GetPull(mw.db, f.RepoAt, prIdInt)
+
pr, err := db.GetPull(mw.db, f.RepoAt(), prIdInt)
if err != nil {
log.Println("failed to get pull and comments", err)
return
···
return
}
-
fullName := f.OwnerHandle() + "/" + f.RepoName
+
fullName := f.OwnerHandle() + "/" + f.Name
if r.Header.Get("User-Agent") == "Go-http-client/1.1" {
if r.URL.Query().Get("go-get") == "1" {
+6 -6
appview/repo/artifact.go
···
Artifact: uploadBlobResp.Blob,
CreatedAt: createdAt.Format(time.RFC3339),
Name: handler.Filename,
-
Repo: f.RepoAt.String(),
+
Repo: f.RepoAt().String(),
Tag: tag.Tag.Hash[:],
},
},
···
artifact := db.Artifact{
Did: user.Did,
Rkey: rkey,
-
RepoAt: f.RepoAt,
+
RepoAt: f.RepoAt(),
Tag: tag.Tag.Hash,
CreatedAt: createdAt,
BlobCid: cid.Cid(uploadBlobResp.Blob.Ref),
···
artifacts, err := db.GetArtifact(
rp.db,
-
db.FilterEq("repo_at", f.RepoAt),
+
db.FilterEq("repo_at", f.RepoAt()),
db.FilterEq("tag", tag.Tag.Hash[:]),
db.FilterEq("name", filename),
)
···
artifacts, err := db.GetArtifact(
rp.db,
-
db.FilterEq("repo_at", f.RepoAt),
+
db.FilterEq("repo_at", f.RepoAt()),
db.FilterEq("tag", tag[:]),
db.FilterEq("name", filename),
)
···
defer tx.Rollback()
err = db.DeleteArtifact(tx,
-
db.FilterEq("repo_at", f.RepoAt),
+
db.FilterEq("repo_at", f.RepoAt()),
db.FilterEq("tag", artifact.Tag[:]),
db.FilterEq("name", filename),
)
···
return nil, err
}
-
result, err := us.Tags(f.OwnerDid(), f.RepoName)
+
result, err := us.Tags(f.OwnerDid(), f.Name)
if err != nil {
log.Println("failed to reach knotserver", err)
return nil, err
+5 -5
appview/repo/index.go
···
return
}
-
result, err := us.Index(f.OwnerDid(), f.RepoName, ref)
+
result, err := us.Index(f.OwnerDid(), f.Name, ref)
if err != nil {
rp.pages.Error503(w)
log.Println("failed to reach knotserver", err)
···
// first attempt to fetch from db
langs, err := db.GetRepoLanguages(
rp.db,
-
db.FilterEq("repo_at", f.RepoAt),
+
db.FilterEq("repo_at", f.RepoAt()),
db.FilterEq("ref", f.Ref),
)
if err != nil || langs == nil {
// non-fatal, fetch langs from ks
-
ls, err := signedClient.RepoLanguages(f.OwnerDid(), f.RepoName, f.Ref)
+
ls, err := signedClient.RepoLanguages(f.OwnerDid(), f.Name, f.Ref)
if err != nil {
return nil, err
}
···
for l, s := range ls.Languages {
langs = append(langs, db.RepoLanguage{
-
RepoAt: f.RepoAt,
+
RepoAt: f.RepoAt(),
Ref: f.Ref,
IsDefaultRef: isDefaultRef,
Language: l,
···
hiddenRef := fmt.Sprintf("hidden/%s/%s", f.Ref, f.Ref)
var status types.AncestorCheckResponse
-
forkSyncableResp, err := signedClient.RepoForkAheadBehind(user.Did, string(f.RepoAt), repoInfo.Name, f.Ref, hiddenRef)
+
forkSyncableResp, err := signedClient.RepoForkAheadBehind(user.Did, string(f.RepoAt()), repoInfo.Name, f.Ref, hiddenRef)
if err != nil {
log.Printf("failed to check if fork is ahead/behind: %s", err)
return nil, err
+25 -58
appview/reporesolver/resolver.go
···
"strings"
"github.com/bluesky-social/indigo/atproto/identity"
-
"github.com/bluesky-social/indigo/atproto/syntax"
securejoin "github.com/cyphar/filepath-securejoin"
"github.com/go-chi/chi/v5"
"tangled.sh/tangled.sh/core/appview/config"
···
)
type ResolvedRepo struct {
-
Knot string
+
db.Repo
OwnerId identity.Identity
-
RepoName string
-
RepoAt syntax.ATURI
-
Description string
-
Spindle string
-
CreatedAt string
Ref string
CurrentDir string
···
}
func (rr *RepoResolver) Resolve(r *http.Request) (*ResolvedRepo, error) {
-
repoName := chi.URLParam(r, "repo")
-
knot, ok := r.Context().Value("knot").(string)
+
repo, ok := r.Context().Value("repo").(*db.Repo)
if !ok {
-
log.Println("malformed middleware")
+
log.Println("malformed middleware: `repo` not exist in context")
return nil, fmt.Errorf("malformed middleware")
}
id, ok := r.Context().Value("resolvedId").(identity.Identity)
···
return nil, fmt.Errorf("malformed middleware")
}
-
repoAt, ok := r.Context().Value("repoAt").(string)
-
if !ok {
-
log.Println("malformed middleware")
-
return nil, fmt.Errorf("malformed middleware")
-
}
-
-
parsedRepoAt, err := syntax.ParseATURI(repoAt)
-
if err != nil {
-
log.Println("malformed repo at-uri")
-
return nil, fmt.Errorf("malformed middleware")
-
}
-
ref := chi.URLParam(r, "ref")
if ref == "" {
-
us, err := knotclient.NewUnsignedClient(knot, rr.config.Core.Dev)
+
us, err := knotclient.NewUnsignedClient(repo.Knot, rr.config.Core.Dev)
if err != nil {
return nil, err
}
-
defaultBranch, err := us.DefaultBranch(id.DID.String(), repoName)
+
defaultBranch, err := us.DefaultBranch(id.DID.String(), repo.Name)
if err != nil {
return nil, err
}
···
currentDir := path.Dir(extractPathAfterRef(r.URL.EscapedPath(), ref))
-
// pass through values from the middleware
-
description, ok := r.Context().Value("repoDescription").(string)
-
addedAt, ok := r.Context().Value("repoAddedAt").(string)
-
spindle, ok := r.Context().Value("repoSpindle").(string)
-
return &ResolvedRepo{
-
Knot: knot,
-
OwnerId: id,
-
RepoName: repoName,
-
RepoAt: parsedRepoAt,
-
Description: description,
-
CreatedAt: addedAt,
-
Ref: ref,
-
CurrentDir: currentDir,
-
Spindle: spindle,
+
Repo: *repo,
+
OwnerId: id,
+
Ref: ref,
+
CurrentDir: currentDir,
rr: rr,
}, nil
···
var p string
if handle != "" && !handle.IsInvalidHandle() {
-
p, _ = securejoin.SecureJoin(fmt.Sprintf("@%s", handle), f.RepoName)
+
p, _ = securejoin.SecureJoin(fmt.Sprintf("@%s", handle), f.Name)
} else {
-
p, _ = securejoin.SecureJoin(f.OwnerDid(), f.RepoName)
+
p, _ = securejoin.SecureJoin(f.OwnerDid(), f.Name)
}
return p
}
-
func (f *ResolvedRepo) DidSlashRepo() string {
-
p, _ := securejoin.SecureJoin(f.OwnerDid(), f.RepoName)
-
return p
-
}
-
func (f *ResolvedRepo) Collaborators(ctx context.Context) ([]pages.Collaborator, error) {
repoCollaborators, err := f.rr.enforcer.E.GetImplicitUsersForResourceByDomain(f.DidSlashRepo(), f.Knot)
if err != nil {
···
// this function is a bit weird since it now returns RepoInfo from an entirely different
// package. we should refactor this or get rid of RepoInfo entirely.
func (f *ResolvedRepo) RepoInfo(user *oauth.User) repoinfo.RepoInfo {
+
repoAt := f.RepoAt()
isStarred := false
if user != nil {
-
isStarred = db.GetStarStatus(f.rr.execer, user.Did, syntax.ATURI(f.RepoAt))
+
isStarred = db.GetStarStatus(f.rr.execer, user.Did, repoAt)
}
-
starCount, err := db.GetStarCount(f.rr.execer, f.RepoAt)
+
starCount, err := db.GetStarCount(f.rr.execer, repoAt)
if err != nil {
-
log.Println("failed to get star count for ", f.RepoAt)
+
log.Println("failed to get star count for ", repoAt)
}
-
issueCount, err := db.GetIssueCount(f.rr.execer, f.RepoAt)
+
issueCount, err := db.GetIssueCount(f.rr.execer, repoAt)
if err != nil {
-
log.Println("failed to get issue count for ", f.RepoAt)
+
log.Println("failed to get issue count for ", repoAt)
}
-
pullCount, err := db.GetPullCount(f.rr.execer, f.RepoAt)
+
pullCount, err := db.GetPullCount(f.rr.execer, repoAt)
if err != nil {
-
log.Println("failed to get issue count for ", f.RepoAt)
+
log.Println("failed to get issue count for ", repoAt)
}
-
source, err := db.GetRepoSource(f.rr.execer, f.RepoAt)
+
source, err := db.GetRepoSource(f.rr.execer, repoAt)
if errors.Is(err, sql.ErrNoRows) {
source = ""
} else if err != nil {
-
log.Println("failed to get repo source for ", f.RepoAt, err)
+
log.Println("failed to get repo source for ", repoAt, err)
}
var sourceRepo *db.Repo
···
if err != nil {
log.Printf("failed to create unsigned client for %s: %v", knot, err)
} else {
-
result, err := us.Branches(f.OwnerDid(), f.RepoName)
+
result, err := us.Branches(f.OwnerDid(), f.Name)
if err != nil {
-
log.Printf("failed to get branches for %s/%s: %v", f.OwnerDid(), f.RepoName, err)
+
log.Printf("failed to get branches for %s/%s: %v", f.OwnerDid(), f.Name, err)
}
if len(result.Branches) == 0 {
···
repoInfo := repoinfo.RepoInfo{
OwnerDid: f.OwnerDid(),
OwnerHandle: f.OwnerHandle(),
-
Name: f.RepoName,
-
RepoAt: f.RepoAt,
+
Name: f.Name,
+
RepoAt: repoAt,
Description: f.Description,
Ref: f.Ref,
IsStarred: isStarred,
+7 -4
appview/db/repos.go
···
var description, spindle sql.NullString
row := e.QueryRow(`
-
select did, name, knot, created, at_uri, description, spindle
+
select did, name, knot, created, at_uri, description, spindle, rkey
from repos
where did = ? and name = ?
`,
···
)
var createdAt string
-
if err := row.Scan(&repo.Did, &repo.Name, &repo.Knot, &createdAt, &repo.AtUri, &description, &spindle); err != nil {
+
if err := row.Scan(&repo.Did, &repo.Name, &repo.Knot, &createdAt, &repo.AtUri, &description, &spindle, &repo.Rkey); err != nil {
return nil, err
}
createdAtTime, _ := time.Parse(time.RFC3339, createdAt)
···
var repo Repo
var nullableDescription sql.NullString
-
row := e.QueryRow(`select did, name, knot, created, at_uri, description from repos where at_uri = ?`, atUri)
+
row := e.QueryRow(`select did, name, knot, created, at_uri, rkey, description from repos where at_uri = ?`, atUri)
var createdAt string
-
if err := row.Scan(&repo.Did, &repo.Name, &repo.Knot, &createdAt, &repo.AtUri, &nullableDescription); err != nil {
+
if err := row.Scan(&repo.Did, &repo.Name, &repo.Knot, &createdAt, &repo.AtUri, &repo.Rkey, &nullableDescription); err != nil {
return nil, err
}
createdAtTime, _ := time.Parse(time.RFC3339, createdAt)
···
}
func AddRepo(e Execer, repo *Repo) error {
+
if repo.AtUri == "" {
+
repo.AtUri = repo.RepoAt().String()
+
}
_, err := e.Exec(
`insert into repos
(did, name, knot, rkey, at_uri, description, source)
-1
appview/state/state.go
···
// continue
}
-
repo.AtUri = atresp.Uri
err = db.AddRepo(tx, repo)
if err != nil {
log.Println(err)