appview: prefer models.Repo over ResolvedRepo internally #812

merged
opened by boltless.me targeting master from sl/yurolxtlpsmz
Changed files
+70 -74
appview
+47 -49
appview/pulls/pulls.go
···
return
}
-
mergeCheckResponse := s.mergeCheck(r, f, pull, stack)
-
branchDeleteStatus := s.branchDeleteStatus(r, f, pull)
resubmitResult := pages.Unknown
if user.Did == pull.OwnerDid {
-
resubmitResult = s.resubmitCheck(r, f, pull, stack)
}
s.pages.PullActionsFragment(w, pages.PullActionsParams{
···
stack, _ := r.Context().Value("stack").(models.Stack)
abandonedPulls, _ := r.Context().Value("abandonedPulls").([]*models.Pull)
-
mergeCheckResponse := s.mergeCheck(r, f, pull, stack)
-
branchDeleteStatus := s.branchDeleteStatus(r, f, pull)
resubmitResult := pages.Unknown
if user != nil && user.Did == pull.OwnerDid {
-
resubmitResult = s.resubmitCheck(r, f, pull, stack)
}
m := make(map[string]models.Pipeline)
···
})
}
-
func (s *Pulls) mergeCheck(r *http.Request, f *reporesolver.ResolvedRepo, pull *models.Pull, stack models.Stack) types.MergeCheckResponse {
if pull.State == models.PullMerged {
return types.MergeCheckResponse{}
}
···
return result
}
-
func (s *Pulls) branchDeleteStatus(r *http.Request, f *reporesolver.ResolvedRepo, pull *models.Pull) *models.BranchDeleteStatus {
if pull.State != models.PullMerged {
return nil
}
···
}
var branch string
-
var repo *models.Repo
// check if the branch exists
// NOTE: appview could cache branches/tags etc. for every repo by listening for gitRefUpdates
if pull.IsBranchBased() {
branch = pull.PullSource.Branch
-
repo = &f.Repo
} else if pull.IsForkBased() {
branch = pull.PullSource.Branch
repo = pull.PullSource.Repo
···
}
}
-
func (s *Pulls) resubmitCheck(r *http.Request, f *reporesolver.ResolvedRepo, pull *models.Pull, stack models.Stack) pages.ResubmitResult {
if pull.State == models.PullMerged || pull.State == models.PullDeleted || pull.PullSource == nil {
return pages.Unknown
}
···
repoName = sourceRepo.Name
} else {
// pulls within the same repo
-
knot = f.Knot
-
ownerDid = f.Did
-
repoName = f.Name
}
scheme := "http"
···
Host: host,
}
-
repo := fmt.Sprintf("%s/%s", ownerDid, repoName)
-
branchResp, err := tangled.RepoBranch(r.Context(), xrpcc, pull.PullSource.Branch, repo)
if err != nil {
if xrpcerr := xrpcclient.HandleXrpcErr(err); xrpcerr != nil {
log.Println("failed to call XRPC repo.branches", xrpcerr)
···
s.pages.Notice(w, "pull", "This knot doesn't support branch-based pull requests. Try another way?")
return
}
-
s.handleBranchBasedPull(w, r, f, user, title, body, targetBranch, sourceBranch, isStacked)
} else if isForkBased {
if !caps.PullRequests.ForkSubmissions {
s.pages.Notice(w, "pull", "This knot doesn't support fork-based pull requests. Try another way?")
return
}
-
s.handleForkBasedPull(w, r, f, user, fromFork, title, body, targetBranch, sourceBranch, isStacked)
} else if isPatchBased {
if !caps.PullRequests.PatchSubmissions {
s.pages.Notice(w, "pull", "This knot doesn't support patch-based pull requests. Send your patch over email.")
return
}
-
s.handlePatchBasedPull(w, r, f, user, title, body, targetBranch, patch, isStacked)
}
return
}
···
func (s *Pulls) handleBranchBasedPull(
w http.ResponseWriter,
r *http.Request,
-
f *reporesolver.ResolvedRepo,
user *oauth.User,
title,
body,
···
if !s.config.Core.Dev {
scheme = "https"
}
-
host := fmt.Sprintf("%s://%s", scheme, f.Knot)
xrpcc := &indigoxrpc.Client{
Host: host,
}
-
repo := fmt.Sprintf("%s/%s", f.Did, f.Name)
-
xrpcBytes, err := tangled.RepoCompare(r.Context(), xrpcc, repo, targetBranch, sourceBranch)
if err != nil {
if xrpcerr := xrpcclient.HandleXrpcErr(err); xrpcerr != nil {
log.Println("failed to call XRPC repo.compare", xrpcerr)
···
Sha: comparison.Rev2,
}
-
s.createPullRequest(w, r, f, user, title, body, targetBranch, patch, combined, sourceRev, pullSource, recordPullSource, isStacked)
}
-
func (s *Pulls) handlePatchBasedPull(w http.ResponseWriter, r *http.Request, f *reporesolver.ResolvedRepo, user *oauth.User, title, body, targetBranch, patch string, isStacked bool) {
if err := s.validator.ValidatePatch(&patch); err != nil {
s.logger.Error("patch validation failed", "err", err)
s.pages.Notice(w, "pull", "Invalid patch format. Please provide a valid diff.")
return
}
-
s.createPullRequest(w, r, f, user, title, body, targetBranch, patch, "", "", nil, nil, isStacked)
}
-
func (s *Pulls) handleForkBasedPull(w http.ResponseWriter, r *http.Request, f *reporesolver.ResolvedRepo, user *oauth.User, forkRepo string, title, body, targetBranch, sourceBranch string, isStacked bool) {
repoString := strings.SplitN(forkRepo, "/", 2)
forkOwnerDid := repoString[0]
repoName := repoString[1]
···
Sha: sourceRev,
}
-
s.createPullRequest(w, r, f, user, title, body, targetBranch, patch, combined, sourceRev, pullSource, recordPullSource, isStacked)
}
func (s *Pulls) createPullRequest(
w http.ResponseWriter,
r *http.Request,
-
f *reporesolver.ResolvedRepo,
user *oauth.User,
title, body, targetBranch string,
patch string,
···
s.createStackedPullRequest(
w,
r,
-
f,
user,
targetBranch,
patch,
···
Body: body,
TargetBranch: targetBranch,
OwnerDid: user.Did,
-
RepoAt: f.RepoAt(),
Rkey: rkey,
Submissions: []*models.PullSubmission{
&initialSubmission,
···
s.pages.Notice(w, "pull", "Failed to create pull request. Try again later.")
return
}
-
pullId, err := db.NextPullId(tx, f.RepoAt())
if err != nil {
log.Println("failed to get pull id", err)
s.pages.Notice(w, "pull", "Failed to create pull request. Try again later.")
···
Val: &tangled.RepoPull{
Title: title,
Target: &tangled.RepoPull_Target{
-
Repo: string(f.RepoAt()),
Branch: targetBranch,
},
Patch: patch,
···
s.notifier.NewPull(r.Context(), pull)
-
ownerSlashRepo := reporesolver.GetBaseRepoPath(r, &f.Repo)
s.pages.HxLocation(w, fmt.Sprintf("/%s/pulls/%d", ownerSlashRepo, pullId))
}
func (s *Pulls) createStackedPullRequest(
w http.ResponseWriter,
r *http.Request,
-
f *reporesolver.ResolvedRepo,
user *oauth.User,
targetBranch string,
patch string,
···
// build a stack out of this patch
stackId := uuid.New()
-
stack, err := newStack(f, user, targetBranch, patch, pullSource, stackId.String())
if err != nil {
log.Println("failed to create stack", err)
s.pages.Notice(w, "pull", fmt.Sprintf("Failed to create stack: %v", err))
···
return
}
-
ownerSlashRepo := reporesolver.GetBaseRepoPath(r, &f.Repo)
s.pages.HxLocation(w, fmt.Sprintf("/%s/pulls", ownerSlashRepo))
}
···
patch := r.FormValue("patch")
-
s.resubmitPullHelper(w, r, f, user, pull, patch, "", "")
}
func (s *Pulls) resubmitBranch(w http.ResponseWriter, r *http.Request) {
···
patch := comparison.FormatPatchRaw
combined := comparison.CombinedPatchRaw
-
s.resubmitPullHelper(w, r, f, user, pull, patch, combined, sourceRev)
}
func (s *Pulls) resubmitFork(w http.ResponseWriter, r *http.Request) {
···
patch := comparison.FormatPatchRaw
combined := comparison.CombinedPatchRaw
-
s.resubmitPullHelper(w, r, f, user, pull, patch, combined, sourceRev)
}
func (s *Pulls) resubmitPullHelper(
w http.ResponseWriter,
r *http.Request,
-
f *reporesolver.ResolvedRepo,
user *oauth.User,
pull *models.Pull,
patch string,
···
) {
if pull.IsStacked() {
log.Println("resubmitting stacked PR")
-
s.resubmitStackedPullHelper(w, r, f, user, pull, patch, pull.StackId)
return
}
···
Val: &tangled.RepoPull{
Title: pull.Title,
Target: &tangled.RepoPull_Target{
-
Repo: string(f.RepoAt()),
Branch: pull.TargetBranch,
},
Patch: patch, // new patch
···
return
}
-
ownerSlashRepo := reporesolver.GetBaseRepoPath(r, &f.Repo)
s.pages.HxLocation(w, fmt.Sprintf("/%s/pulls/%d", ownerSlashRepo, pull.PullId))
}
func (s *Pulls) resubmitStackedPullHelper(
w http.ResponseWriter,
r *http.Request,
-
f *reporesolver.ResolvedRepo,
user *oauth.User,
pull *models.Pull,
patch string,
···
targetBranch := pull.TargetBranch
origStack, _ := r.Context().Value("stack").(models.Stack)
-
newStack, err := newStack(f, user, targetBranch, patch, pull.PullSource, stackId)
if err != nil {
log.Println("failed to create resubmitted stack", err)
s.pages.Notice(w, "pull-merge-error", "Failed to merge pull request. Try again later.")
···
return
}
-
ownerSlashRepo := reporesolver.GetBaseRepoPath(r, &f.Repo)
s.pages.HxLocation(w, fmt.Sprintf("/%s/pulls/%d", ownerSlashRepo, pull.PullId))
}
···
s.pages.HxLocation(w, fmt.Sprintf("/%s/pulls/%d", ownerSlashRepo, pull.PullId))
}
-
func newStack(f *reporesolver.ResolvedRepo, user *oauth.User, targetBranch, patch string, pullSource *models.PullSource, stackId string) (models.Stack, error) {
formatPatches, err := patchutil.ExtractPatches(patch)
if err != nil {
return nil, fmt.Errorf("Failed to extract patches: %v", err)
···
Body: body,
TargetBranch: targetBranch,
OwnerDid: user.Did,
-
RepoAt: f.RepoAt(),
Rkey: rkey,
Submissions: []*models.PullSubmission{
&initialSubmission,
···
return
}
+
mergeCheckResponse := s.mergeCheck(r, &f.Repo, pull, stack)
+
branchDeleteStatus := s.branchDeleteStatus(r, &f.Repo, pull)
resubmitResult := pages.Unknown
if user.Did == pull.OwnerDid {
+
resubmitResult = s.resubmitCheck(r, &f.Repo, pull, stack)
}
s.pages.PullActionsFragment(w, pages.PullActionsParams{
···
stack, _ := r.Context().Value("stack").(models.Stack)
abandonedPulls, _ := r.Context().Value("abandonedPulls").([]*models.Pull)
+
mergeCheckResponse := s.mergeCheck(r, &f.Repo, pull, stack)
+
branchDeleteStatus := s.branchDeleteStatus(r, &f.Repo, pull)
resubmitResult := pages.Unknown
if user != nil && user.Did == pull.OwnerDid {
+
resubmitResult = s.resubmitCheck(r, &f.Repo, pull, stack)
}
m := make(map[string]models.Pipeline)
···
})
}
+
func (s *Pulls) mergeCheck(r *http.Request, f *models.Repo, pull *models.Pull, stack models.Stack) types.MergeCheckResponse {
if pull.State == models.PullMerged {
return types.MergeCheckResponse{}
}
···
return result
}
+
func (s *Pulls) branchDeleteStatus(r *http.Request, repo *models.Repo, pull *models.Pull) *models.BranchDeleteStatus {
if pull.State != models.PullMerged {
return nil
}
···
}
var branch string
// check if the branch exists
// NOTE: appview could cache branches/tags etc. for every repo by listening for gitRefUpdates
if pull.IsBranchBased() {
branch = pull.PullSource.Branch
} else if pull.IsForkBased() {
branch = pull.PullSource.Branch
repo = pull.PullSource.Repo
···
}
}
+
func (s *Pulls) resubmitCheck(r *http.Request, repo *models.Repo, pull *models.Pull, stack models.Stack) pages.ResubmitResult {
if pull.State == models.PullMerged || pull.State == models.PullDeleted || pull.PullSource == nil {
return pages.Unknown
}
···
repoName = sourceRepo.Name
} else {
// pulls within the same repo
+
knot = repo.Knot
+
ownerDid = repo.Did
+
repoName = repo.Name
}
scheme := "http"
···
Host: host,
}
+
didSlashName := fmt.Sprintf("%s/%s", ownerDid, repoName)
+
branchResp, err := tangled.RepoBranch(r.Context(), xrpcc, pull.PullSource.Branch, didSlashName)
if err != nil {
if xrpcerr := xrpcclient.HandleXrpcErr(err); xrpcerr != nil {
log.Println("failed to call XRPC repo.branches", xrpcerr)
···
s.pages.Notice(w, "pull", "This knot doesn't support branch-based pull requests. Try another way?")
return
}
+
s.handleBranchBasedPull(w, r, &f.Repo, user, title, body, targetBranch, sourceBranch, isStacked)
} else if isForkBased {
if !caps.PullRequests.ForkSubmissions {
s.pages.Notice(w, "pull", "This knot doesn't support fork-based pull requests. Try another way?")
return
}
+
s.handleForkBasedPull(w, r, &f.Repo, user, fromFork, title, body, targetBranch, sourceBranch, isStacked)
} else if isPatchBased {
if !caps.PullRequests.PatchSubmissions {
s.pages.Notice(w, "pull", "This knot doesn't support patch-based pull requests. Send your patch over email.")
return
}
+
s.handlePatchBasedPull(w, r, &f.Repo, user, title, body, targetBranch, patch, isStacked)
}
return
}
···
func (s *Pulls) handleBranchBasedPull(
w http.ResponseWriter,
r *http.Request,
+
repo *models.Repo,
user *oauth.User,
title,
body,
···
if !s.config.Core.Dev {
scheme = "https"
}
+
host := fmt.Sprintf("%s://%s", scheme, repo.Knot)
xrpcc := &indigoxrpc.Client{
Host: host,
}
+
didSlashRepo := fmt.Sprintf("%s/%s", repo.Did, repo.Name)
+
xrpcBytes, err := tangled.RepoCompare(r.Context(), xrpcc, didSlashRepo, targetBranch, sourceBranch)
if err != nil {
if xrpcerr := xrpcclient.HandleXrpcErr(err); xrpcerr != nil {
log.Println("failed to call XRPC repo.compare", xrpcerr)
···
Sha: comparison.Rev2,
}
+
s.createPullRequest(w, r, repo, user, title, body, targetBranch, patch, combined, sourceRev, pullSource, recordPullSource, isStacked)
}
+
func (s *Pulls) handlePatchBasedPull(w http.ResponseWriter, r *http.Request, repo *models.Repo, user *oauth.User, title, body, targetBranch, patch string, isStacked bool) {
if err := s.validator.ValidatePatch(&patch); err != nil {
s.logger.Error("patch validation failed", "err", err)
s.pages.Notice(w, "pull", "Invalid patch format. Please provide a valid diff.")
return
}
+
s.createPullRequest(w, r, repo, user, title, body, targetBranch, patch, "", "", nil, nil, isStacked)
}
+
func (s *Pulls) handleForkBasedPull(w http.ResponseWriter, r *http.Request, repo *models.Repo, user *oauth.User, forkRepo string, title, body, targetBranch, sourceBranch string, isStacked bool) {
repoString := strings.SplitN(forkRepo, "/", 2)
forkOwnerDid := repoString[0]
repoName := repoString[1]
···
Sha: sourceRev,
}
+
s.createPullRequest(w, r, repo, user, title, body, targetBranch, patch, combined, sourceRev, pullSource, recordPullSource, isStacked)
}
func (s *Pulls) createPullRequest(
w http.ResponseWriter,
r *http.Request,
+
repo *models.Repo,
user *oauth.User,
title, body, targetBranch string,
patch string,
···
s.createStackedPullRequest(
w,
r,
+
repo,
user,
targetBranch,
patch,
···
Body: body,
TargetBranch: targetBranch,
OwnerDid: user.Did,
+
RepoAt: repo.RepoAt(),
Rkey: rkey,
Submissions: []*models.PullSubmission{
&initialSubmission,
···
s.pages.Notice(w, "pull", "Failed to create pull request. Try again later.")
return
}
+
pullId, err := db.NextPullId(tx, repo.RepoAt())
if err != nil {
log.Println("failed to get pull id", err)
s.pages.Notice(w, "pull", "Failed to create pull request. Try again later.")
···
Val: &tangled.RepoPull{
Title: title,
Target: &tangled.RepoPull_Target{
+
Repo: string(repo.RepoAt()),
Branch: targetBranch,
},
Patch: patch,
···
s.notifier.NewPull(r.Context(), pull)
+
ownerSlashRepo := reporesolver.GetBaseRepoPath(r, repo)
s.pages.HxLocation(w, fmt.Sprintf("/%s/pulls/%d", ownerSlashRepo, pullId))
}
func (s *Pulls) createStackedPullRequest(
w http.ResponseWriter,
r *http.Request,
+
repo *models.Repo,
user *oauth.User,
targetBranch string,
patch string,
···
// build a stack out of this patch
stackId := uuid.New()
+
stack, err := newStack(repo, user, targetBranch, patch, pullSource, stackId.String())
if err != nil {
log.Println("failed to create stack", err)
s.pages.Notice(w, "pull", fmt.Sprintf("Failed to create stack: %v", err))
···
return
}
+
ownerSlashRepo := reporesolver.GetBaseRepoPath(r, repo)
s.pages.HxLocation(w, fmt.Sprintf("/%s/pulls", ownerSlashRepo))
}
···
patch := r.FormValue("patch")
+
s.resubmitPullHelper(w, r, &f.Repo, user, pull, patch, "", "")
}
func (s *Pulls) resubmitBranch(w http.ResponseWriter, r *http.Request) {
···
patch := comparison.FormatPatchRaw
combined := comparison.CombinedPatchRaw
+
s.resubmitPullHelper(w, r, &f.Repo, user, pull, patch, combined, sourceRev)
}
func (s *Pulls) resubmitFork(w http.ResponseWriter, r *http.Request) {
···
patch := comparison.FormatPatchRaw
combined := comparison.CombinedPatchRaw
+
s.resubmitPullHelper(w, r, &f.Repo, user, pull, patch, combined, sourceRev)
}
func (s *Pulls) resubmitPullHelper(
w http.ResponseWriter,
r *http.Request,
+
repo *models.Repo,
user *oauth.User,
pull *models.Pull,
patch string,
···
) {
if pull.IsStacked() {
log.Println("resubmitting stacked PR")
+
s.resubmitStackedPullHelper(w, r, repo, user, pull, patch, pull.StackId)
return
}
···
Val: &tangled.RepoPull{
Title: pull.Title,
Target: &tangled.RepoPull_Target{
+
Repo: string(repo.RepoAt()),
Branch: pull.TargetBranch,
},
Patch: patch, // new patch
···
return
}
+
ownerSlashRepo := reporesolver.GetBaseRepoPath(r, repo)
s.pages.HxLocation(w, fmt.Sprintf("/%s/pulls/%d", ownerSlashRepo, pull.PullId))
}
func (s *Pulls) resubmitStackedPullHelper(
w http.ResponseWriter,
r *http.Request,
+
repo *models.Repo,
user *oauth.User,
pull *models.Pull,
patch string,
···
targetBranch := pull.TargetBranch
origStack, _ := r.Context().Value("stack").(models.Stack)
+
newStack, err := newStack(repo, user, targetBranch, patch, pull.PullSource, stackId)
if err != nil {
log.Println("failed to create resubmitted stack", err)
s.pages.Notice(w, "pull-merge-error", "Failed to merge pull request. Try again later.")
···
return
}
+
ownerSlashRepo := reporesolver.GetBaseRepoPath(r, repo)
s.pages.HxLocation(w, fmt.Sprintf("/%s/pulls/%d", ownerSlashRepo, pull.PullId))
}
···
s.pages.HxLocation(w, fmt.Sprintf("/%s/pulls/%d", ownerSlashRepo, pull.PullId))
}
+
func newStack(repo *models.Repo, user *oauth.User, targetBranch, patch string, pullSource *models.PullSource, stackId string) (models.Stack, error) {
formatPatches, err := patchutil.ExtractPatches(patch)
if err != nil {
return nil, fmt.Errorf("Failed to extract patches: %v", err)
···
Body: body,
TargetBranch: targetBranch,
OwnerDid: user.Did,
+
RepoAt: repo.RepoAt(),
Rkey: rkey,
Submissions: []*models.PullSubmission{
&initialSubmission,
+3 -4
appview/repo/artifact.go
···
"tangled.org/core/appview/db"
"tangled.org/core/appview/models"
"tangled.org/core/appview/pages"
-
"tangled.org/core/appview/reporesolver"
"tangled.org/core/appview/xrpcclient"
"tangled.org/core/tid"
"tangled.org/core/types"
···
return
}
-
tag, err := rp.resolveTag(r.Context(), f, tagParam)
if err != nil {
log.Println("failed to resolve tag", err)
rp.pages.Notice(w, "upload", "failed to upload artifact, error in tag resolution")
···
tagParam := chi.URLParam(r, "tag")
filename := chi.URLParam(r, "file")
-
tag, err := rp.resolveTag(r.Context(), f, tagParam)
if err != nil {
log.Println("failed to resolve tag", err)
rp.pages.Notice(w, "upload", "failed to upload artifact, error in tag resolution")
···
w.Write([]byte{})
}
-
func (rp *Repo) resolveTag(ctx context.Context, f *reporesolver.ResolvedRepo, tagParam string) (*types.TagReference, error) {
tagParam, err := url.QueryUnescape(tagParam)
if err != nil {
return nil, err
···
"tangled.org/core/appview/db"
"tangled.org/core/appview/models"
"tangled.org/core/appview/pages"
"tangled.org/core/appview/xrpcclient"
"tangled.org/core/tid"
"tangled.org/core/types"
···
return
}
+
tag, err := rp.resolveTag(r.Context(), &f.Repo, tagParam)
if err != nil {
log.Println("failed to resolve tag", err)
rp.pages.Notice(w, "upload", "failed to upload artifact, error in tag resolution")
···
tagParam := chi.URLParam(r, "tag")
filename := chi.URLParam(r, "file")
+
tag, err := rp.resolveTag(r.Context(), &f.Repo, tagParam)
if err != nil {
log.Println("failed to resolve tag", err)
rp.pages.Notice(w, "upload", "failed to upload artifact, error in tag resolution")
···
w.Write([]byte{})
}
+
func (rp *Repo) resolveTag(ctx context.Context, f *models.Repo, tagParam string) (*types.TagReference, error) {
tagParam, err := url.QueryUnescape(tagParam)
if err != nil {
return nil, err
+6 -6
appview/repo/blob.go
···
}
// Create the blob view
-
blobView := NewBlobView(resp, rp.config, f, ref, filePath, r.URL.Query())
user := rp.oauth.GetUser(r)
···
}
// NewBlobView creates a BlobView from the XRPC response
-
func NewBlobView(resp *tangled.RepoBlob_Output, config *config.Config, f *reporesolver.ResolvedRepo, ref, filePath string, queryParams url.Values) models.BlobView {
view := models.BlobView{
Contents: "",
Lines: 0,
···
// Determine if binary
if resp.IsBinary != nil && *resp.IsBinary {
-
view.ContentSrc = generateBlobURL(config, f, ref, filePath)
ext := strings.ToLower(filepath.Ext(resp.Path))
switch ext {
···
return view
}
-
func generateBlobURL(config *config.Config, f *reporesolver.ResolvedRepo, ref, filePath string) string {
scheme := "http"
if !config.Core.Dev {
scheme = "https"
}
-
repoName := fmt.Sprintf("%s/%s", f.Did, f.Name)
baseURL := &url.URL{
Scheme: scheme,
-
Host: f.Knot,
Path: "/xrpc/sh.tangled.repo.blob",
}
query := baseURL.Query()
···
}
// Create the blob view
+
blobView := NewBlobView(resp, rp.config, &f.Repo, ref, filePath, r.URL.Query())
user := rp.oauth.GetUser(r)
···
}
// NewBlobView creates a BlobView from the XRPC response
+
func NewBlobView(resp *tangled.RepoBlob_Output, config *config.Config, repo *models.Repo, ref, filePath string, queryParams url.Values) models.BlobView {
view := models.BlobView{
Contents: "",
Lines: 0,
···
// Determine if binary
if resp.IsBinary != nil && *resp.IsBinary {
+
view.ContentSrc = generateBlobURL(config, repo, ref, filePath)
ext := strings.ToLower(filepath.Ext(resp.Path))
switch ext {
···
return view
}
+
func generateBlobURL(config *config.Config, repo *models.Repo, ref, filePath string) string {
scheme := "http"
if !config.Core.Dev {
scheme = "https"
}
+
repoName := fmt.Sprintf("%s/%s", repo.Did, repo.Name)
baseURL := &url.URL{
Scheme: scheme,
+
Host: repo.Knot,
Path: "/xrpc/sh.tangled.repo.blob",
}
query := baseURL.Query()
+14 -15
appview/repo/index.go
···
"tangled.org/core/appview/db"
"tangled.org/core/appview/models"
"tangled.org/core/appview/pages"
-
"tangled.org/core/appview/reporesolver"
"tangled.org/core/appview/xrpcclient"
"tangled.org/core/types"
···
user := rp.oauth.GetUser(r)
// Build index response from multiple XRPC calls
-
result, err := rp.buildIndexResponse(r.Context(), xrpcc, f, ref)
if xrpcerr := xrpcclient.HandleXrpcErr(err); xrpcerr != nil {
if errors.Is(xrpcerr, xrpcclient.ErrXrpcUnsupported) {
l.Error("failed to call XRPC repo.index", "err", err)
···
}
// TODO: a bit dirty
-
languageInfo, err := rp.getLanguageInfo(r.Context(), l, f, xrpcc, result.Ref, ref == "")
if err != nil {
l.Warn("failed to compute language percentages", "err", err)
// non-fatal
···
func (rp *Repo) getLanguageInfo(
ctx context.Context,
l *slog.Logger,
-
f *reporesolver.ResolvedRepo,
xrpcc *indigoxrpc.Client,
currentRef string,
isDefaultRef bool,
···
// first attempt to fetch from db
langs, err := db.GetRepoLanguages(
rp.db,
-
db.FilterEq("repo_at", f.RepoAt()),
db.FilterEq("ref", currentRef),
)
if err != nil || langs == nil {
// non-fatal, fetch langs from ks via XRPC
-
repo := fmt.Sprintf("%s/%s", f.Did, f.Name)
-
ls, err := tangled.RepoLanguages(ctx, xrpcc, currentRef, repo)
if err != nil {
if xrpcerr := xrpcclient.HandleXrpcErr(err); xrpcerr != nil {
l.Error("failed to call XRPC repo.languages", "err", xrpcerr)
···
for _, lang := range ls.Languages {
langs = append(langs, models.RepoLanguage{
-
RepoAt: f.RepoAt(),
Ref: currentRef,
IsDefaultRef: isDefaultRef,
Language: lang.Name,
···
defer tx.Rollback()
// update appview's cache
-
err = db.UpdateRepoLanguages(tx, f.RepoAt(), currentRef, langs)
if err != nil {
// non-fatal
l.Error("failed to cache lang results", "err", err)
···
}
// buildIndexResponse creates a RepoIndexResponse by combining multiple xrpc calls in parallel
-
func (rp *Repo) buildIndexResponse(ctx context.Context, xrpcc *indigoxrpc.Client, f *reporesolver.ResolvedRepo, ref string) (*types.RepoIndexResponse, error) {
-
repo := fmt.Sprintf("%s/%s", f.Did, f.Name)
// first get branches to determine the ref if not specified
-
branchesBytes, err := tangled.RepoBranches(ctx, xrpcc, "", 0, repo)
if err != nil {
return nil, fmt.Errorf("failed to call repoBranches: %w", err)
}
···
wg.Add(1)
go func() {
defer wg.Done()
-
tagsBytes, err := tangled.RepoTags(ctx, xrpcc, "", 0, repo)
if err != nil {
errs = errors.Join(errs, fmt.Errorf("failed to call repoTags: %w", err))
return
···
wg.Add(1)
go func() {
defer wg.Done()
-
resp, err := tangled.RepoTree(ctx, xrpcc, "", ref, repo)
if err != nil {
errs = errors.Join(errs, fmt.Errorf("failed to call repoTree: %w", err))
return
···
wg.Add(1)
go func() {
defer wg.Done()
-
logBytes, err := tangled.RepoLog(ctx, xrpcc, "", 50, "", ref, repo)
if err != nil {
errs = errors.Join(errs, fmt.Errorf("failed to call repoLog: %w", err))
return
···
"tangled.org/core/appview/db"
"tangled.org/core/appview/models"
"tangled.org/core/appview/pages"
"tangled.org/core/appview/xrpcclient"
"tangled.org/core/types"
···
user := rp.oauth.GetUser(r)
// Build index response from multiple XRPC calls
+
result, err := rp.buildIndexResponse(r.Context(), xrpcc, &f.Repo, ref)
if xrpcerr := xrpcclient.HandleXrpcErr(err); xrpcerr != nil {
if errors.Is(xrpcerr, xrpcclient.ErrXrpcUnsupported) {
l.Error("failed to call XRPC repo.index", "err", err)
···
}
// TODO: a bit dirty
+
languageInfo, err := rp.getLanguageInfo(r.Context(), l, &f.Repo, xrpcc, result.Ref, ref == "")
if err != nil {
l.Warn("failed to compute language percentages", "err", err)
// non-fatal
···
func (rp *Repo) getLanguageInfo(
ctx context.Context,
l *slog.Logger,
+
repo *models.Repo,
xrpcc *indigoxrpc.Client,
currentRef string,
isDefaultRef bool,
···
// first attempt to fetch from db
langs, err := db.GetRepoLanguages(
rp.db,
+
db.FilterEq("repo_at", repo.RepoAt()),
db.FilterEq("ref", currentRef),
)
if err != nil || langs == nil {
// non-fatal, fetch langs from ks via XRPC
+
didSlashRepo := fmt.Sprintf("%s/%s", repo.Did, repo.Name)
+
ls, err := tangled.RepoLanguages(ctx, xrpcc, currentRef, didSlashRepo)
if err != nil {
if xrpcerr := xrpcclient.HandleXrpcErr(err); xrpcerr != nil {
l.Error("failed to call XRPC repo.languages", "err", xrpcerr)
···
for _, lang := range ls.Languages {
langs = append(langs, models.RepoLanguage{
+
RepoAt: repo.RepoAt(),
Ref: currentRef,
IsDefaultRef: isDefaultRef,
Language: lang.Name,
···
defer tx.Rollback()
// update appview's cache
+
err = db.UpdateRepoLanguages(tx, repo.RepoAt(), currentRef, langs)
if err != nil {
// non-fatal
l.Error("failed to cache lang results", "err", err)
···
}
// buildIndexResponse creates a RepoIndexResponse by combining multiple xrpc calls in parallel
+
func (rp *Repo) buildIndexResponse(ctx context.Context, xrpcc *indigoxrpc.Client, repo *models.Repo, ref string) (*types.RepoIndexResponse, error) {
+
didSlashRepo := fmt.Sprintf("%s/%s", repo.Did, repo.Name)
// first get branches to determine the ref if not specified
+
branchesBytes, err := tangled.RepoBranches(ctx, xrpcc, "", 0, didSlashRepo)
if err != nil {
return nil, fmt.Errorf("failed to call repoBranches: %w", err)
}
···
wg.Add(1)
go func() {
defer wg.Done()
+
tagsBytes, err := tangled.RepoTags(ctx, xrpcc, "", 0, didSlashRepo)
if err != nil {
errs = errors.Join(errs, fmt.Errorf("failed to call repoTags: %w", err))
return
···
wg.Add(1)
go func() {
defer wg.Done()
+
resp, err := tangled.RepoTree(ctx, xrpcc, "", ref, didSlashRepo)
if err != nil {
errs = errors.Join(errs, fmt.Errorf("failed to call repoTree: %w", err))
return
···
wg.Add(1)
go func() {
defer wg.Done()
+
logBytes, err := tangled.RepoLog(ctx, xrpcc, "", 50, "", ref, didSlashRepo)
if err != nil {
errs = errors.Join(errs, fmt.Errorf("failed to call repoLog: %w", err))
return