+47
-49
appview/pulls/pulls.go
+47
-49
appview/pulls/pulls.go
···
115
return
116
}
117
118
-
mergeCheckResponse := s.mergeCheck(r, f, pull, stack)
119
-
branchDeleteStatus := s.branchDeleteStatus(r, f, pull)
120
resubmitResult := pages.Unknown
121
if user.Did == pull.OwnerDid {
122
-
resubmitResult = s.resubmitCheck(r, f, pull, stack)
123
}
124
125
s.pages.PullActionsFragment(w, pages.PullActionsParams{
···
155
stack, _ := r.Context().Value("stack").(models.Stack)
156
abandonedPulls, _ := r.Context().Value("abandonedPulls").([]*models.Pull)
157
158
-
mergeCheckResponse := s.mergeCheck(r, f, pull, stack)
159
-
branchDeleteStatus := s.branchDeleteStatus(r, f, pull)
160
resubmitResult := pages.Unknown
161
if user != nil && user.Did == pull.OwnerDid {
162
-
resubmitResult = s.resubmitCheck(r, f, pull, stack)
163
}
164
165
m := make(map[string]models.Pipeline)
···
238
})
239
}
240
241
-
func (s *Pulls) mergeCheck(r *http.Request, f *reporesolver.ResolvedRepo, pull *models.Pull, stack models.Stack) types.MergeCheckResponse {
242
if pull.State == models.PullMerged {
243
return types.MergeCheckResponse{}
244
}
···
305
return result
306
}
307
308
-
func (s *Pulls) branchDeleteStatus(r *http.Request, f *reporesolver.ResolvedRepo, pull *models.Pull) *models.BranchDeleteStatus {
309
if pull.State != models.PullMerged {
310
return nil
311
}
···
316
}
317
318
var branch string
319
-
var repo *models.Repo
320
// check if the branch exists
321
// NOTE: appview could cache branches/tags etc. for every repo by listening for gitRefUpdates
322
if pull.IsBranchBased() {
323
branch = pull.PullSource.Branch
324
-
repo = &f.Repo
325
} else if pull.IsForkBased() {
326
branch = pull.PullSource.Branch
327
repo = pull.PullSource.Repo
···
360
}
361
}
362
363
-
func (s *Pulls) resubmitCheck(r *http.Request, f *reporesolver.ResolvedRepo, pull *models.Pull, stack models.Stack) pages.ResubmitResult {
364
if pull.State == models.PullMerged || pull.State == models.PullDeleted || pull.PullSource == nil {
365
return pages.Unknown
366
}
···
380
repoName = sourceRepo.Name
381
} else {
382
// pulls within the same repo
383
-
knot = f.Knot
384
-
ownerDid = f.Did
385
-
repoName = f.Name
386
}
387
388
scheme := "http"
···
394
Host: host,
395
}
396
397
-
repo := fmt.Sprintf("%s/%s", ownerDid, repoName)
398
-
branchResp, err := tangled.RepoBranch(r.Context(), xrpcc, pull.PullSource.Branch, repo)
399
if err != nil {
400
if xrpcerr := xrpcclient.HandleXrpcErr(err); xrpcerr != nil {
401
log.Println("failed to call XRPC repo.branches", xrpcerr)
···
953
s.pages.Notice(w, "pull", "This knot doesn't support branch-based pull requests. Try another way?")
954
return
955
}
956
-
s.handleBranchBasedPull(w, r, f, user, title, body, targetBranch, sourceBranch, isStacked)
957
} else if isForkBased {
958
if !caps.PullRequests.ForkSubmissions {
959
s.pages.Notice(w, "pull", "This knot doesn't support fork-based pull requests. Try another way?")
960
return
961
}
962
-
s.handleForkBasedPull(w, r, f, user, fromFork, title, body, targetBranch, sourceBranch, isStacked)
963
} else if isPatchBased {
964
if !caps.PullRequests.PatchSubmissions {
965
s.pages.Notice(w, "pull", "This knot doesn't support patch-based pull requests. Send your patch over email.")
966
return
967
}
968
-
s.handlePatchBasedPull(w, r, f, user, title, body, targetBranch, patch, isStacked)
969
}
970
return
971
}
···
974
func (s *Pulls) handleBranchBasedPull(
975
w http.ResponseWriter,
976
r *http.Request,
977
-
f *reporesolver.ResolvedRepo,
978
user *oauth.User,
979
title,
980
body,
···
986
if !s.config.Core.Dev {
987
scheme = "https"
988
}
989
-
host := fmt.Sprintf("%s://%s", scheme, f.Knot)
990
xrpcc := &indigoxrpc.Client{
991
Host: host,
992
}
993
994
-
repo := fmt.Sprintf("%s/%s", f.Did, f.Name)
995
-
xrpcBytes, err := tangled.RepoCompare(r.Context(), xrpcc, repo, targetBranch, sourceBranch)
996
if err != nil {
997
if xrpcerr := xrpcclient.HandleXrpcErr(err); xrpcerr != nil {
998
log.Println("failed to call XRPC repo.compare", xrpcerr)
···
1029
Sha: comparison.Rev2,
1030
}
1031
1032
-
s.createPullRequest(w, r, f, user, title, body, targetBranch, patch, combined, sourceRev, pullSource, recordPullSource, isStacked)
1033
}
1034
1035
-
func (s *Pulls) handlePatchBasedPull(w http.ResponseWriter, r *http.Request, f *reporesolver.ResolvedRepo, user *oauth.User, title, body, targetBranch, patch string, isStacked bool) {
1036
if err := s.validator.ValidatePatch(&patch); err != nil {
1037
s.logger.Error("patch validation failed", "err", err)
1038
s.pages.Notice(w, "pull", "Invalid patch format. Please provide a valid diff.")
1039
return
1040
}
1041
1042
-
s.createPullRequest(w, r, f, user, title, body, targetBranch, patch, "", "", nil, nil, isStacked)
1043
}
1044
1045
-
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) {
1046
repoString := strings.SplitN(forkRepo, "/", 2)
1047
forkOwnerDid := repoString[0]
1048
repoName := repoString[1]
···
1144
Sha: sourceRev,
1145
}
1146
1147
-
s.createPullRequest(w, r, f, user, title, body, targetBranch, patch, combined, sourceRev, pullSource, recordPullSource, isStacked)
1148
}
1149
1150
func (s *Pulls) createPullRequest(
1151
w http.ResponseWriter,
1152
r *http.Request,
1153
-
f *reporesolver.ResolvedRepo,
1154
user *oauth.User,
1155
title, body, targetBranch string,
1156
patch string,
···
1165
s.createStackedPullRequest(
1166
w,
1167
r,
1168
-
f,
1169
user,
1170
targetBranch,
1171
patch,
···
1222
Body: body,
1223
TargetBranch: targetBranch,
1224
OwnerDid: user.Did,
1225
-
RepoAt: f.RepoAt(),
1226
Rkey: rkey,
1227
Submissions: []*models.PullSubmission{
1228
&initialSubmission,
···
1235
s.pages.Notice(w, "pull", "Failed to create pull request. Try again later.")
1236
return
1237
}
1238
-
pullId, err := db.NextPullId(tx, f.RepoAt())
1239
if err != nil {
1240
log.Println("failed to get pull id", err)
1241
s.pages.Notice(w, "pull", "Failed to create pull request. Try again later.")
···
1250
Val: &tangled.RepoPull{
1251
Title: title,
1252
Target: &tangled.RepoPull_Target{
1253
-
Repo: string(f.RepoAt()),
1254
Branch: targetBranch,
1255
},
1256
Patch: patch,
···
1273
1274
s.notifier.NewPull(r.Context(), pull)
1275
1276
-
ownerSlashRepo := reporesolver.GetBaseRepoPath(r, &f.Repo)
1277
s.pages.HxLocation(w, fmt.Sprintf("/%s/pulls/%d", ownerSlashRepo, pullId))
1278
}
1279
1280
func (s *Pulls) createStackedPullRequest(
1281
w http.ResponseWriter,
1282
r *http.Request,
1283
-
f *reporesolver.ResolvedRepo,
1284
user *oauth.User,
1285
targetBranch string,
1286
patch string,
···
1312
1313
// build a stack out of this patch
1314
stackId := uuid.New()
1315
-
stack, err := newStack(f, user, targetBranch, patch, pullSource, stackId.String())
1316
if err != nil {
1317
log.Println("failed to create stack", err)
1318
s.pages.Notice(w, "pull", fmt.Sprintf("Failed to create stack: %v", err))
···
1375
return
1376
}
1377
1378
-
ownerSlashRepo := reporesolver.GetBaseRepoPath(r, &f.Repo)
1379
s.pages.HxLocation(w, fmt.Sprintf("/%s/pulls", ownerSlashRepo))
1380
}
1381
···
1647
1648
patch := r.FormValue("patch")
1649
1650
-
s.resubmitPullHelper(w, r, f, user, pull, patch, "", "")
1651
}
1652
1653
func (s *Pulls) resubmitBranch(w http.ResponseWriter, r *http.Request) {
···
1712
patch := comparison.FormatPatchRaw
1713
combined := comparison.CombinedPatchRaw
1714
1715
-
s.resubmitPullHelper(w, r, f, user, pull, patch, combined, sourceRev)
1716
}
1717
1718
func (s *Pulls) resubmitFork(w http.ResponseWriter, r *http.Request) {
···
1809
patch := comparison.FormatPatchRaw
1810
combined := comparison.CombinedPatchRaw
1811
1812
-
s.resubmitPullHelper(w, r, f, user, pull, patch, combined, sourceRev)
1813
}
1814
1815
func (s *Pulls) resubmitPullHelper(
1816
w http.ResponseWriter,
1817
r *http.Request,
1818
-
f *reporesolver.ResolvedRepo,
1819
user *oauth.User,
1820
pull *models.Pull,
1821
patch string,
···
1824
) {
1825
if pull.IsStacked() {
1826
log.Println("resubmitting stacked PR")
1827
-
s.resubmitStackedPullHelper(w, r, f, user, pull, patch, pull.StackId)
1828
return
1829
}
1830
···
1904
Val: &tangled.RepoPull{
1905
Title: pull.Title,
1906
Target: &tangled.RepoPull_Target{
1907
-
Repo: string(f.RepoAt()),
1908
Branch: pull.TargetBranch,
1909
},
1910
Patch: patch, // new patch
···
1925
return
1926
}
1927
1928
-
ownerSlashRepo := reporesolver.GetBaseRepoPath(r, &f.Repo)
1929
s.pages.HxLocation(w, fmt.Sprintf("/%s/pulls/%d", ownerSlashRepo, pull.PullId))
1930
}
1931
1932
func (s *Pulls) resubmitStackedPullHelper(
1933
w http.ResponseWriter,
1934
r *http.Request,
1935
-
f *reporesolver.ResolvedRepo,
1936
user *oauth.User,
1937
pull *models.Pull,
1938
patch string,
···
1941
targetBranch := pull.TargetBranch
1942
1943
origStack, _ := r.Context().Value("stack").(models.Stack)
1944
-
newStack, err := newStack(f, user, targetBranch, patch, pull.PullSource, stackId)
1945
if err != nil {
1946
log.Println("failed to create resubmitted stack", err)
1947
s.pages.Notice(w, "pull-merge-error", "Failed to merge pull request. Try again later.")
···
2119
return
2120
}
2121
2122
-
ownerSlashRepo := reporesolver.GetBaseRepoPath(r, &f.Repo)
2123
s.pages.HxLocation(w, fmt.Sprintf("/%s/pulls/%d", ownerSlashRepo, pull.PullId))
2124
}
2125
···
2389
s.pages.HxLocation(w, fmt.Sprintf("/%s/pulls/%d", ownerSlashRepo, pull.PullId))
2390
}
2391
2392
-
func newStack(f *reporesolver.ResolvedRepo, user *oauth.User, targetBranch, patch string, pullSource *models.PullSource, stackId string) (models.Stack, error) {
2393
formatPatches, err := patchutil.ExtractPatches(patch)
2394
if err != nil {
2395
return nil, fmt.Errorf("Failed to extract patches: %v", err)
···
2424
Body: body,
2425
TargetBranch: targetBranch,
2426
OwnerDid: user.Did,
2427
-
RepoAt: f.RepoAt(),
2428
Rkey: rkey,
2429
Submissions: []*models.PullSubmission{
2430
&initialSubmission,
···
115
return
116
}
117
118
+
mergeCheckResponse := s.mergeCheck(r, &f.Repo, pull, stack)
119
+
branchDeleteStatus := s.branchDeleteStatus(r, &f.Repo, pull)
120
resubmitResult := pages.Unknown
121
if user.Did == pull.OwnerDid {
122
+
resubmitResult = s.resubmitCheck(r, &f.Repo, pull, stack)
123
}
124
125
s.pages.PullActionsFragment(w, pages.PullActionsParams{
···
155
stack, _ := r.Context().Value("stack").(models.Stack)
156
abandonedPulls, _ := r.Context().Value("abandonedPulls").([]*models.Pull)
157
158
+
mergeCheckResponse := s.mergeCheck(r, &f.Repo, pull, stack)
159
+
branchDeleteStatus := s.branchDeleteStatus(r, &f.Repo, pull)
160
resubmitResult := pages.Unknown
161
if user != nil && user.Did == pull.OwnerDid {
162
+
resubmitResult = s.resubmitCheck(r, &f.Repo, pull, stack)
163
}
164
165
m := make(map[string]models.Pipeline)
···
238
})
239
}
240
241
+
func (s *Pulls) mergeCheck(r *http.Request, f *models.Repo, pull *models.Pull, stack models.Stack) types.MergeCheckResponse {
242
if pull.State == models.PullMerged {
243
return types.MergeCheckResponse{}
244
}
···
305
return result
306
}
307
308
+
func (s *Pulls) branchDeleteStatus(r *http.Request, repo *models.Repo, pull *models.Pull) *models.BranchDeleteStatus {
309
if pull.State != models.PullMerged {
310
return nil
311
}
···
316
}
317
318
var branch string
319
// check if the branch exists
320
// NOTE: appview could cache branches/tags etc. for every repo by listening for gitRefUpdates
321
if pull.IsBranchBased() {
322
branch = pull.PullSource.Branch
323
} else if pull.IsForkBased() {
324
branch = pull.PullSource.Branch
325
repo = pull.PullSource.Repo
···
358
}
359
}
360
361
+
func (s *Pulls) resubmitCheck(r *http.Request, repo *models.Repo, pull *models.Pull, stack models.Stack) pages.ResubmitResult {
362
if pull.State == models.PullMerged || pull.State == models.PullDeleted || pull.PullSource == nil {
363
return pages.Unknown
364
}
···
378
repoName = sourceRepo.Name
379
} else {
380
// pulls within the same repo
381
+
knot = repo.Knot
382
+
ownerDid = repo.Did
383
+
repoName = repo.Name
384
}
385
386
scheme := "http"
···
392
Host: host,
393
}
394
395
+
didSlashName := fmt.Sprintf("%s/%s", ownerDid, repoName)
396
+
branchResp, err := tangled.RepoBranch(r.Context(), xrpcc, pull.PullSource.Branch, didSlashName)
397
if err != nil {
398
if xrpcerr := xrpcclient.HandleXrpcErr(err); xrpcerr != nil {
399
log.Println("failed to call XRPC repo.branches", xrpcerr)
···
951
s.pages.Notice(w, "pull", "This knot doesn't support branch-based pull requests. Try another way?")
952
return
953
}
954
+
s.handleBranchBasedPull(w, r, &f.Repo, user, title, body, targetBranch, sourceBranch, isStacked)
955
} else if isForkBased {
956
if !caps.PullRequests.ForkSubmissions {
957
s.pages.Notice(w, "pull", "This knot doesn't support fork-based pull requests. Try another way?")
958
return
959
}
960
+
s.handleForkBasedPull(w, r, &f.Repo, user, fromFork, title, body, targetBranch, sourceBranch, isStacked)
961
} else if isPatchBased {
962
if !caps.PullRequests.PatchSubmissions {
963
s.pages.Notice(w, "pull", "This knot doesn't support patch-based pull requests. Send your patch over email.")
964
return
965
}
966
+
s.handlePatchBasedPull(w, r, &f.Repo, user, title, body, targetBranch, patch, isStacked)
967
}
968
return
969
}
···
972
func (s *Pulls) handleBranchBasedPull(
973
w http.ResponseWriter,
974
r *http.Request,
975
+
repo *models.Repo,
976
user *oauth.User,
977
title,
978
body,
···
984
if !s.config.Core.Dev {
985
scheme = "https"
986
}
987
+
host := fmt.Sprintf("%s://%s", scheme, repo.Knot)
988
xrpcc := &indigoxrpc.Client{
989
Host: host,
990
}
991
992
+
didSlashRepo := fmt.Sprintf("%s/%s", repo.Did, repo.Name)
993
+
xrpcBytes, err := tangled.RepoCompare(r.Context(), xrpcc, didSlashRepo, targetBranch, sourceBranch)
994
if err != nil {
995
if xrpcerr := xrpcclient.HandleXrpcErr(err); xrpcerr != nil {
996
log.Println("failed to call XRPC repo.compare", xrpcerr)
···
1027
Sha: comparison.Rev2,
1028
}
1029
1030
+
s.createPullRequest(w, r, repo, user, title, body, targetBranch, patch, combined, sourceRev, pullSource, recordPullSource, isStacked)
1031
}
1032
1033
+
func (s *Pulls) handlePatchBasedPull(w http.ResponseWriter, r *http.Request, repo *models.Repo, user *oauth.User, title, body, targetBranch, patch string, isStacked bool) {
1034
if err := s.validator.ValidatePatch(&patch); err != nil {
1035
s.logger.Error("patch validation failed", "err", err)
1036
s.pages.Notice(w, "pull", "Invalid patch format. Please provide a valid diff.")
1037
return
1038
}
1039
1040
+
s.createPullRequest(w, r, repo, user, title, body, targetBranch, patch, "", "", nil, nil, isStacked)
1041
}
1042
1043
+
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) {
1044
repoString := strings.SplitN(forkRepo, "/", 2)
1045
forkOwnerDid := repoString[0]
1046
repoName := repoString[1]
···
1142
Sha: sourceRev,
1143
}
1144
1145
+
s.createPullRequest(w, r, repo, user, title, body, targetBranch, patch, combined, sourceRev, pullSource, recordPullSource, isStacked)
1146
}
1147
1148
func (s *Pulls) createPullRequest(
1149
w http.ResponseWriter,
1150
r *http.Request,
1151
+
repo *models.Repo,
1152
user *oauth.User,
1153
title, body, targetBranch string,
1154
patch string,
···
1163
s.createStackedPullRequest(
1164
w,
1165
r,
1166
+
repo,
1167
user,
1168
targetBranch,
1169
patch,
···
1220
Body: body,
1221
TargetBranch: targetBranch,
1222
OwnerDid: user.Did,
1223
+
RepoAt: repo.RepoAt(),
1224
Rkey: rkey,
1225
Submissions: []*models.PullSubmission{
1226
&initialSubmission,
···
1233
s.pages.Notice(w, "pull", "Failed to create pull request. Try again later.")
1234
return
1235
}
1236
+
pullId, err := db.NextPullId(tx, repo.RepoAt())
1237
if err != nil {
1238
log.Println("failed to get pull id", err)
1239
s.pages.Notice(w, "pull", "Failed to create pull request. Try again later.")
···
1248
Val: &tangled.RepoPull{
1249
Title: title,
1250
Target: &tangled.RepoPull_Target{
1251
+
Repo: string(repo.RepoAt()),
1252
Branch: targetBranch,
1253
},
1254
Patch: patch,
···
1271
1272
s.notifier.NewPull(r.Context(), pull)
1273
1274
+
ownerSlashRepo := reporesolver.GetBaseRepoPath(r, repo)
1275
s.pages.HxLocation(w, fmt.Sprintf("/%s/pulls/%d", ownerSlashRepo, pullId))
1276
}
1277
1278
func (s *Pulls) createStackedPullRequest(
1279
w http.ResponseWriter,
1280
r *http.Request,
1281
+
repo *models.Repo,
1282
user *oauth.User,
1283
targetBranch string,
1284
patch string,
···
1310
1311
// build a stack out of this patch
1312
stackId := uuid.New()
1313
+
stack, err := newStack(repo, user, targetBranch, patch, pullSource, stackId.String())
1314
if err != nil {
1315
log.Println("failed to create stack", err)
1316
s.pages.Notice(w, "pull", fmt.Sprintf("Failed to create stack: %v", err))
···
1373
return
1374
}
1375
1376
+
ownerSlashRepo := reporesolver.GetBaseRepoPath(r, repo)
1377
s.pages.HxLocation(w, fmt.Sprintf("/%s/pulls", ownerSlashRepo))
1378
}
1379
···
1645
1646
patch := r.FormValue("patch")
1647
1648
+
s.resubmitPullHelper(w, r, &f.Repo, user, pull, patch, "", "")
1649
}
1650
1651
func (s *Pulls) resubmitBranch(w http.ResponseWriter, r *http.Request) {
···
1710
patch := comparison.FormatPatchRaw
1711
combined := comparison.CombinedPatchRaw
1712
1713
+
s.resubmitPullHelper(w, r, &f.Repo, user, pull, patch, combined, sourceRev)
1714
}
1715
1716
func (s *Pulls) resubmitFork(w http.ResponseWriter, r *http.Request) {
···
1807
patch := comparison.FormatPatchRaw
1808
combined := comparison.CombinedPatchRaw
1809
1810
+
s.resubmitPullHelper(w, r, &f.Repo, user, pull, patch, combined, sourceRev)
1811
}
1812
1813
func (s *Pulls) resubmitPullHelper(
1814
w http.ResponseWriter,
1815
r *http.Request,
1816
+
repo *models.Repo,
1817
user *oauth.User,
1818
pull *models.Pull,
1819
patch string,
···
1822
) {
1823
if pull.IsStacked() {
1824
log.Println("resubmitting stacked PR")
1825
+
s.resubmitStackedPullHelper(w, r, repo, user, pull, patch, pull.StackId)
1826
return
1827
}
1828
···
1902
Val: &tangled.RepoPull{
1903
Title: pull.Title,
1904
Target: &tangled.RepoPull_Target{
1905
+
Repo: string(repo.RepoAt()),
1906
Branch: pull.TargetBranch,
1907
},
1908
Patch: patch, // new patch
···
1923
return
1924
}
1925
1926
+
ownerSlashRepo := reporesolver.GetBaseRepoPath(r, repo)
1927
s.pages.HxLocation(w, fmt.Sprintf("/%s/pulls/%d", ownerSlashRepo, pull.PullId))
1928
}
1929
1930
func (s *Pulls) resubmitStackedPullHelper(
1931
w http.ResponseWriter,
1932
r *http.Request,
1933
+
repo *models.Repo,
1934
user *oauth.User,
1935
pull *models.Pull,
1936
patch string,
···
1939
targetBranch := pull.TargetBranch
1940
1941
origStack, _ := r.Context().Value("stack").(models.Stack)
1942
+
newStack, err := newStack(repo, user, targetBranch, patch, pull.PullSource, stackId)
1943
if err != nil {
1944
log.Println("failed to create resubmitted stack", err)
1945
s.pages.Notice(w, "pull-merge-error", "Failed to merge pull request. Try again later.")
···
2117
return
2118
}
2119
2120
+
ownerSlashRepo := reporesolver.GetBaseRepoPath(r, repo)
2121
s.pages.HxLocation(w, fmt.Sprintf("/%s/pulls/%d", ownerSlashRepo, pull.PullId))
2122
}
2123
···
2387
s.pages.HxLocation(w, fmt.Sprintf("/%s/pulls/%d", ownerSlashRepo, pull.PullId))
2388
}
2389
2390
+
func newStack(repo *models.Repo, user *oauth.User, targetBranch, patch string, pullSource *models.PullSource, stackId string) (models.Stack, error) {
2391
formatPatches, err := patchutil.ExtractPatches(patch)
2392
if err != nil {
2393
return nil, fmt.Errorf("Failed to extract patches: %v", err)
···
2422
Body: body,
2423
TargetBranch: targetBranch,
2424
OwnerDid: user.Did,
2425
+
RepoAt: repo.RepoAt(),
2426
Rkey: rkey,
2427
Submissions: []*models.PullSubmission{
2428
&initialSubmission,
+3
-4
appview/repo/artifact.go
+3
-4
appview/repo/artifact.go
···
14
"tangled.org/core/appview/db"
15
"tangled.org/core/appview/models"
16
"tangled.org/core/appview/pages"
17
-
"tangled.org/core/appview/reporesolver"
18
"tangled.org/core/appview/xrpcclient"
19
"tangled.org/core/tid"
20
"tangled.org/core/types"
···
39
return
40
}
41
42
-
tag, err := rp.resolveTag(r.Context(), f, tagParam)
43
if err != nil {
44
log.Println("failed to resolve tag", err)
45
rp.pages.Notice(w, "upload", "failed to upload artifact, error in tag resolution")
···
147
tagParam := chi.URLParam(r, "tag")
148
filename := chi.URLParam(r, "file")
149
150
-
tag, err := rp.resolveTag(r.Context(), f, tagParam)
151
if err != nil {
152
log.Println("failed to resolve tag", err)
153
rp.pages.Notice(w, "upload", "failed to upload artifact, error in tag resolution")
···
297
w.Write([]byte{})
298
}
299
300
-
func (rp *Repo) resolveTag(ctx context.Context, f *reporesolver.ResolvedRepo, tagParam string) (*types.TagReference, error) {
301
tagParam, err := url.QueryUnescape(tagParam)
302
if err != nil {
303
return nil, err
···
14
"tangled.org/core/appview/db"
15
"tangled.org/core/appview/models"
16
"tangled.org/core/appview/pages"
17
"tangled.org/core/appview/xrpcclient"
18
"tangled.org/core/tid"
19
"tangled.org/core/types"
···
38
return
39
}
40
41
+
tag, err := rp.resolveTag(r.Context(), &f.Repo, tagParam)
42
if err != nil {
43
log.Println("failed to resolve tag", err)
44
rp.pages.Notice(w, "upload", "failed to upload artifact, error in tag resolution")
···
146
tagParam := chi.URLParam(r, "tag")
147
filename := chi.URLParam(r, "file")
148
149
+
tag, err := rp.resolveTag(r.Context(), &f.Repo, tagParam)
150
if err != nil {
151
log.Println("failed to resolve tag", err)
152
rp.pages.Notice(w, "upload", "failed to upload artifact, error in tag resolution")
···
296
w.Write([]byte{})
297
}
298
299
+
func (rp *Repo) resolveTag(ctx context.Context, f *models.Repo, tagParam string) (*types.TagReference, error) {
300
tagParam, err := url.QueryUnescape(tagParam)
301
if err != nil {
302
return nil, err
+6
-6
appview/repo/blob.go
+6
-6
appview/repo/blob.go
···
74
}
75
76
// Create the blob view
77
-
blobView := NewBlobView(resp, rp.config, f, ref, filePath, r.URL.Query())
78
79
user := rp.oauth.GetUser(r)
80
···
178
}
179
180
// NewBlobView creates a BlobView from the XRPC response
181
-
func NewBlobView(resp *tangled.RepoBlob_Output, config *config.Config, f *reporesolver.ResolvedRepo, ref, filePath string, queryParams url.Values) models.BlobView {
182
view := models.BlobView{
183
Contents: "",
184
Lines: 0,
···
200
201
// Determine if binary
202
if resp.IsBinary != nil && *resp.IsBinary {
203
-
view.ContentSrc = generateBlobURL(config, f, ref, filePath)
204
ext := strings.ToLower(filepath.Ext(resp.Path))
205
206
switch ext {
···
252
return view
253
}
254
255
-
func generateBlobURL(config *config.Config, f *reporesolver.ResolvedRepo, ref, filePath string) string {
256
scheme := "http"
257
if !config.Core.Dev {
258
scheme = "https"
259
}
260
261
-
repoName := fmt.Sprintf("%s/%s", f.Did, f.Name)
262
baseURL := &url.URL{
263
Scheme: scheme,
264
-
Host: f.Knot,
265
Path: "/xrpc/sh.tangled.repo.blob",
266
}
267
query := baseURL.Query()
···
74
}
75
76
// Create the blob view
77
+
blobView := NewBlobView(resp, rp.config, &f.Repo, ref, filePath, r.URL.Query())
78
79
user := rp.oauth.GetUser(r)
80
···
178
}
179
180
// NewBlobView creates a BlobView from the XRPC response
181
+
func NewBlobView(resp *tangled.RepoBlob_Output, config *config.Config, repo *models.Repo, ref, filePath string, queryParams url.Values) models.BlobView {
182
view := models.BlobView{
183
Contents: "",
184
Lines: 0,
···
200
201
// Determine if binary
202
if resp.IsBinary != nil && *resp.IsBinary {
203
+
view.ContentSrc = generateBlobURL(config, repo, ref, filePath)
204
ext := strings.ToLower(filepath.Ext(resp.Path))
205
206
switch ext {
···
252
return view
253
}
254
255
+
func generateBlobURL(config *config.Config, repo *models.Repo, ref, filePath string) string {
256
scheme := "http"
257
if !config.Core.Dev {
258
scheme = "https"
259
}
260
261
+
repoName := fmt.Sprintf("%s/%s", repo.Did, repo.Name)
262
baseURL := &url.URL{
263
Scheme: scheme,
264
+
Host: repo.Knot,
265
Path: "/xrpc/sh.tangled.repo.blob",
266
}
267
query := baseURL.Query()
+14
-15
appview/repo/index.go
+14
-15
appview/repo/index.go
···
22
"tangled.org/core/appview/db"
23
"tangled.org/core/appview/models"
24
"tangled.org/core/appview/pages"
25
-
"tangled.org/core/appview/reporesolver"
26
"tangled.org/core/appview/xrpcclient"
27
"tangled.org/core/types"
28
···
54
user := rp.oauth.GetUser(r)
55
56
// Build index response from multiple XRPC calls
57
-
result, err := rp.buildIndexResponse(r.Context(), xrpcc, f, ref)
58
if xrpcerr := xrpcclient.HandleXrpcErr(err); xrpcerr != nil {
59
if errors.Is(xrpcerr, xrpcclient.ErrXrpcUnsupported) {
60
l.Error("failed to call XRPC repo.index", "err", err)
···
129
}
130
131
// TODO: a bit dirty
132
-
languageInfo, err := rp.getLanguageInfo(r.Context(), l, f, xrpcc, result.Ref, ref == "")
133
if err != nil {
134
l.Warn("failed to compute language percentages", "err", err)
135
// non-fatal
···
164
func (rp *Repo) getLanguageInfo(
165
ctx context.Context,
166
l *slog.Logger,
167
-
f *reporesolver.ResolvedRepo,
168
xrpcc *indigoxrpc.Client,
169
currentRef string,
170
isDefaultRef bool,
···
172
// first attempt to fetch from db
173
langs, err := db.GetRepoLanguages(
174
rp.db,
175
-
db.FilterEq("repo_at", f.RepoAt()),
176
db.FilterEq("ref", currentRef),
177
)
178
179
if err != nil || langs == nil {
180
// non-fatal, fetch langs from ks via XRPC
181
-
repo := fmt.Sprintf("%s/%s", f.Did, f.Name)
182
-
ls, err := tangled.RepoLanguages(ctx, xrpcc, currentRef, repo)
183
if err != nil {
184
if xrpcerr := xrpcclient.HandleXrpcErr(err); xrpcerr != nil {
185
l.Error("failed to call XRPC repo.languages", "err", xrpcerr)
···
194
195
for _, lang := range ls.Languages {
196
langs = append(langs, models.RepoLanguage{
197
-
RepoAt: f.RepoAt(),
198
Ref: currentRef,
199
IsDefaultRef: isDefaultRef,
200
Language: lang.Name,
···
209
defer tx.Rollback()
210
211
// update appview's cache
212
-
err = db.UpdateRepoLanguages(tx, f.RepoAt(), currentRef, langs)
213
if err != nil {
214
// non-fatal
215
l.Error("failed to cache lang results", "err", err)
···
254
}
255
256
// buildIndexResponse creates a RepoIndexResponse by combining multiple xrpc calls in parallel
257
-
func (rp *Repo) buildIndexResponse(ctx context.Context, xrpcc *indigoxrpc.Client, f *reporesolver.ResolvedRepo, ref string) (*types.RepoIndexResponse, error) {
258
-
repo := fmt.Sprintf("%s/%s", f.Did, f.Name)
259
260
// first get branches to determine the ref if not specified
261
-
branchesBytes, err := tangled.RepoBranches(ctx, xrpcc, "", 0, repo)
262
if err != nil {
263
return nil, fmt.Errorf("failed to call repoBranches: %w", err)
264
}
···
302
wg.Add(1)
303
go func() {
304
defer wg.Done()
305
-
tagsBytes, err := tangled.RepoTags(ctx, xrpcc, "", 0, repo)
306
if err != nil {
307
errs = errors.Join(errs, fmt.Errorf("failed to call repoTags: %w", err))
308
return
···
317
wg.Add(1)
318
go func() {
319
defer wg.Done()
320
-
resp, err := tangled.RepoTree(ctx, xrpcc, "", ref, repo)
321
if err != nil {
322
errs = errors.Join(errs, fmt.Errorf("failed to call repoTree: %w", err))
323
return
···
329
wg.Add(1)
330
go func() {
331
defer wg.Done()
332
-
logBytes, err := tangled.RepoLog(ctx, xrpcc, "", 50, "", ref, repo)
333
if err != nil {
334
errs = errors.Join(errs, fmt.Errorf("failed to call repoLog: %w", err))
335
return
···
22
"tangled.org/core/appview/db"
23
"tangled.org/core/appview/models"
24
"tangled.org/core/appview/pages"
25
"tangled.org/core/appview/xrpcclient"
26
"tangled.org/core/types"
27
···
53
user := rp.oauth.GetUser(r)
54
55
// Build index response from multiple XRPC calls
56
+
result, err := rp.buildIndexResponse(r.Context(), xrpcc, &f.Repo, ref)
57
if xrpcerr := xrpcclient.HandleXrpcErr(err); xrpcerr != nil {
58
if errors.Is(xrpcerr, xrpcclient.ErrXrpcUnsupported) {
59
l.Error("failed to call XRPC repo.index", "err", err)
···
128
}
129
130
// TODO: a bit dirty
131
+
languageInfo, err := rp.getLanguageInfo(r.Context(), l, &f.Repo, xrpcc, result.Ref, ref == "")
132
if err != nil {
133
l.Warn("failed to compute language percentages", "err", err)
134
// non-fatal
···
163
func (rp *Repo) getLanguageInfo(
164
ctx context.Context,
165
l *slog.Logger,
166
+
repo *models.Repo,
167
xrpcc *indigoxrpc.Client,
168
currentRef string,
169
isDefaultRef bool,
···
171
// first attempt to fetch from db
172
langs, err := db.GetRepoLanguages(
173
rp.db,
174
+
db.FilterEq("repo_at", repo.RepoAt()),
175
db.FilterEq("ref", currentRef),
176
)
177
178
if err != nil || langs == nil {
179
// non-fatal, fetch langs from ks via XRPC
180
+
didSlashRepo := fmt.Sprintf("%s/%s", repo.Did, repo.Name)
181
+
ls, err := tangled.RepoLanguages(ctx, xrpcc, currentRef, didSlashRepo)
182
if err != nil {
183
if xrpcerr := xrpcclient.HandleXrpcErr(err); xrpcerr != nil {
184
l.Error("failed to call XRPC repo.languages", "err", xrpcerr)
···
193
194
for _, lang := range ls.Languages {
195
langs = append(langs, models.RepoLanguage{
196
+
RepoAt: repo.RepoAt(),
197
Ref: currentRef,
198
IsDefaultRef: isDefaultRef,
199
Language: lang.Name,
···
208
defer tx.Rollback()
209
210
// update appview's cache
211
+
err = db.UpdateRepoLanguages(tx, repo.RepoAt(), currentRef, langs)
212
if err != nil {
213
// non-fatal
214
l.Error("failed to cache lang results", "err", err)
···
253
}
254
255
// buildIndexResponse creates a RepoIndexResponse by combining multiple xrpc calls in parallel
256
+
func (rp *Repo) buildIndexResponse(ctx context.Context, xrpcc *indigoxrpc.Client, repo *models.Repo, ref string) (*types.RepoIndexResponse, error) {
257
+
didSlashRepo := fmt.Sprintf("%s/%s", repo.Did, repo.Name)
258
259
// first get branches to determine the ref if not specified
260
+
branchesBytes, err := tangled.RepoBranches(ctx, xrpcc, "", 0, didSlashRepo)
261
if err != nil {
262
return nil, fmt.Errorf("failed to call repoBranches: %w", err)
263
}
···
301
wg.Add(1)
302
go func() {
303
defer wg.Done()
304
+
tagsBytes, err := tangled.RepoTags(ctx, xrpcc, "", 0, didSlashRepo)
305
if err != nil {
306
errs = errors.Join(errs, fmt.Errorf("failed to call repoTags: %w", err))
307
return
···
316
wg.Add(1)
317
go func() {
318
defer wg.Done()
319
+
resp, err := tangled.RepoTree(ctx, xrpcc, "", ref, didSlashRepo)
320
if err != nil {
321
errs = errors.Join(errs, fmt.Errorf("failed to call repoTree: %w", err))
322
return
···
328
wg.Add(1)
329
go func() {
330
defer wg.Done()
331
+
logBytes, err := tangled.RepoLog(ctx, xrpcc, "", 50, "", ref, didSlashRepo)
332
if err != nil {
333
errs = errors.Join(errs, fmt.Errorf("failed to call repoLog: %w", err))
334
return