+13
-3
appview/db/pulls.go
+13
-3
appview/db/pulls.go
···
122
122
return len(p.Submissions) - 1
123
123
}
124
124
125
-
func (p *Pull) IsSameRepoBranch() bool {
125
+
func (p *Pull) IsPatchBased() bool {
126
+
return p.PullSource == nil
127
+
}
128
+
129
+
func (p *Pull) IsBranchBased() bool {
126
130
if p.PullSource != nil {
127
131
if p.PullSource.RepoAt != nil {
128
132
return p.PullSource.RepoAt == &p.RepoAt
···
134
138
return false
135
139
}
136
140
137
-
func (p *Pull) IsPatch() bool {
138
-
return p.PullSource == nil
141
+
func (p *Pull) IsForkBased() bool {
142
+
if p.PullSource != nil {
143
+
if p.PullSource.RepoAt != nil {
144
+
// make sure repos are different
145
+
return p.PullSource.RepoAt != &p.RepoAt
146
+
}
147
+
}
148
+
return false
139
149
}
140
150
141
151
func (s PullSubmission) AsNiceDiff(targetBranch string) types.NiceDiff {
+2
-2
appview/pages/templates/fragments/pullActions.html
+2
-2
appview/pages/templates/fragments/pullActions.html
···
9
9
{{ $isConflicted := and .MergeCheck (or .MergeCheck.Error .MergeCheck.IsConflicted) }}
10
10
{{ $isPullAuthor := and .LoggedInUser (eq .LoggedInUser.Did .Pull.OwnerDid) }}
11
11
{{ $isLastRound := eq $roundNumber $lastIdx }}
12
-
{{ $isSameRepoBranch := .Pull.IsSameRepoBranch }}
12
+
{{ $isSameRepoBranch := .Pull.IsBranchBased }}
13
13
{{ $isUpToDate := .ResubmitCheck.No }}
14
14
<div class="relative w-fit">
15
15
<div id="actions-{{$roundNumber}}" class="flex flex-wrap gap-2">
···
42
42
{{ $disabled = "disabled" }}
43
43
{{ end }}
44
44
<button id="resubmitBtn"
45
-
{{ if not .Pull.IsPatch }}
45
+
{{ if not .Pull.IsPatchBased }}
46
46
hx-post="/{{ .RepoInfo.FullName }}/pulls/{{ .Pull.PullId }}/resubmit"
47
47
{{ else }}
48
48
hx-get="/{{ .RepoInfo.FullName }}/pulls/{{ .Pull.PullId }}/resubmit"
+3
-3
appview/pages/templates/repo/pulls/pull.html
+3
-3
appview/pages/templates/repo/pulls/pull.html
···
45
45
<a href="/{{ .RepoInfo.FullName }}/tree/{{ .Pull.TargetBranch }}" class="no-underline hover:underline">{{ .Pull.TargetBranch }}</a>
46
46
</span>
47
47
</span>
48
-
{{ if not .Pull.IsPatch }}
48
+
{{ if not .Pull.IsPatchBased }}
49
49
<span>from
50
-
{{ if not .Pull.IsSameRepoBranch }}
50
+
{{ if not .Pull.IsBranchBased }}
51
51
<a href="/{{ $owner }}/{{ .PullSourceRepo.Name }}" class="no-underline hover:underline">{{ $owner }}/{{ .PullSourceRepo.Name }}</a>
52
52
{{ end }}
53
53
54
54
{{ $fullRepo := .RepoInfo.FullName }}
55
-
{{ if not .Pull.IsSameRepoBranch }}
55
+
{{ if not .Pull.IsBranchBased }}
56
56
{{ $fullRepo = printf "%s/%s" $owner .PullSourceRepo.Name }}
57
57
{{ end }}
58
58
<span class="text-xs rounded bg-gray-100 dark:bg-gray-700 text-black dark:text-white font-mono px-2 mx-1/2 inline-flex items-center">
+2
-2
appview/pages/templates/repo/pulls/pulls.html
+2
-2
appview/pages/templates/repo/pulls/pulls.html
···
78
78
{{ .TargetBranch }}
79
79
</span>
80
80
</span>
81
-
{{ if not .IsPatch }}
81
+
{{ if not .IsPatchBased }}
82
82
<span>from
83
-
{{ if not .IsSameRepoBranch }}
83
+
{{ if not .IsBranchBased }}
84
84
<a href="/{{ $owner }}/{{ .PullSource.Repo.Name }}" class="no-underline hover:underline">{{ $owner }}/{{ .PullSource.Repo.Name }}</a>
85
85
{{ end }}
86
86
+401
-153
appview/state/pull.go
+401
-153
appview/state/pull.go
···
1015
1015
})
1016
1016
return
1017
1017
case http.MethodPost:
1018
-
patch := r.FormValue("patch")
1019
-
var sourceRev string
1020
-
var recordPullSource *tangled.RepoPull_Source
1021
-
1022
-
var ownerDid, repoName, knotName string
1023
-
var isSameRepo bool = pull.IsSameRepoBranch()
1024
-
sourceBranch := pull.PullSource.Branch
1025
-
targetBranch := pull.TargetBranch
1026
-
recordPullSource = &tangled.RepoPull_Source{
1027
-
Branch: sourceBranch,
1018
+
if pull.IsPatchBased() {
1019
+
s.resubmitPatch(w, r)
1020
+
return
1021
+
} else if pull.IsBranchBased() {
1022
+
s.resubmitBranch(w, r)
1023
+
return
1024
+
} else if pull.IsForkBased() {
1025
+
s.resubmitFork(w, r)
1026
+
return
1028
1027
}
1028
+
}
1029
+
}
1029
1030
1030
-
isPushAllowed := f.RepoInfo(s, user).Roles.IsPushAllowed()
1031
-
if isSameRepo && isPushAllowed {
1032
-
ownerDid = f.OwnerDid()
1033
-
repoName = f.RepoName
1034
-
knotName = f.Knot
1035
-
} else if !isSameRepo {
1036
-
sourceRepo, err := db.GetRepoByAtUri(s.db, pull.PullSource.RepoAt.String())
1037
-
if err != nil {
1038
-
log.Println("failed to get source repo", err)
1039
-
s.pages.Notice(w, "pull", "Failed to create pull request. Try again later.")
1040
-
return
1041
-
}
1042
-
ownerDid = sourceRepo.Did
1043
-
repoName = sourceRepo.Name
1044
-
knotName = sourceRepo.Knot
1045
-
}
1031
+
func (s *State) resubmitPatch(w http.ResponseWriter, r *http.Request) {
1032
+
user := s.auth.GetUser(r)
1033
+
1034
+
pull, ok := r.Context().Value("pull").(*db.Pull)
1035
+
if !ok {
1036
+
log.Println("failed to get pull")
1037
+
s.pages.Notice(w, "pull-error", "Failed to edit patch. Try again later.")
1038
+
return
1039
+
}
1040
+
1041
+
f, err := fullyResolvedRepo(r)
1042
+
if err != nil {
1043
+
log.Println("failed to get repo and knot", err)
1044
+
return
1045
+
}
1046
+
1047
+
if user.Did != pull.OwnerDid {
1048
+
log.Println("unauthorized user")
1049
+
w.WriteHeader(http.StatusUnauthorized)
1050
+
return
1051
+
}
1052
+
1053
+
patch := r.FormValue("patch")
1054
+
1055
+
if patch == "" {
1056
+
s.pages.Notice(w, "resubmit-error", "Patch is empty.")
1057
+
return
1058
+
}
1059
+
1060
+
if patch == pull.LatestPatch() {
1061
+
s.pages.Notice(w, "resubmit-error", "Patch is identical to previous submission.")
1062
+
return
1063
+
}
1046
1064
1047
-
if sourceBranch != "" && knotName != "" {
1048
-
// extract patch by performing compare
1049
-
ksClient, err := NewUnsignedClient(knotName, s.config.Dev)
1050
-
if err != nil {
1051
-
log.Printf("failed to create client for %s: %s", knotName, err)
1052
-
s.pages.Notice(w, "pull", "Failed to create pull request. Try again later.")
1053
-
return
1054
-
}
1065
+
if !isPatchValid(patch) {
1066
+
s.pages.Notice(w, "resubmit-error", "Invalid patch format. Please provide a valid diff.")
1067
+
return
1068
+
}
1055
1069
1056
-
if !isSameRepo {
1057
-
secret, err := db.GetRegistrationKey(s.db, knotName)
1058
-
if err != nil {
1059
-
log.Printf("failed to get registration key for %s: %s", knotName, err)
1060
-
s.pages.Notice(w, "pull", "Failed to create pull request. Try again later.")
1061
-
return
1062
-
}
1063
-
// update the hidden tracking branch to latest
1064
-
signedClient, err := NewSignedClient(knotName, secret, s.config.Dev)
1065
-
if err != nil {
1066
-
log.Printf("failed to create signed client for %s: %s", knotName, err)
1067
-
s.pages.Notice(w, "pull", "Failed to create pull request. Try again later.")
1068
-
return
1069
-
}
1070
-
resp, err := signedClient.NewHiddenRef(ownerDid, repoName, sourceBranch, targetBranch)
1071
-
if err != nil || resp.StatusCode != http.StatusNoContent {
1072
-
log.Printf("failed to update tracking branch: %s", err)
1073
-
s.pages.Notice(w, "pull", "Failed to create pull request. Try again later.")
1074
-
return
1075
-
}
1076
-
}
1070
+
tx, err := s.db.BeginTx(r.Context(), nil)
1071
+
if err != nil {
1072
+
log.Println("failed to start tx")
1073
+
s.pages.Notice(w, "resubmit-error", "Failed to create pull request. Try again later.")
1074
+
return
1075
+
}
1076
+
defer tx.Rollback()
1077
1077
1078
-
var compareResp *http.Response
1079
-
if !isSameRepo {
1080
-
hiddenRef := url.QueryEscape(fmt.Sprintf("hidden/%s/%s", sourceBranch, targetBranch))
1081
-
compareResp, err = ksClient.Compare(ownerDid, repoName, hiddenRef, sourceBranch)
1082
-
} else {
1083
-
compareResp, err = ksClient.Compare(ownerDid, repoName, targetBranch, sourceBranch)
1084
-
}
1085
-
if err != nil {
1086
-
log.Printf("failed to compare branches: %s", err)
1087
-
s.pages.Notice(w, "pull", "Failed to create pull request. Try again later.")
1088
-
return
1089
-
}
1090
-
defer compareResp.Body.Close()
1078
+
err = db.ResubmitPull(tx, pull, patch, "")
1079
+
if err != nil {
1080
+
log.Println("failed to resubmit pull request", err)
1081
+
s.pages.Notice(w, "resubmit-error", "Failed to resubmit pull request. Try again later.")
1082
+
return
1083
+
}
1084
+
client, _ := s.auth.AuthorizedClient(r)
1091
1085
1092
-
switch compareResp.StatusCode {
1093
-
case 404:
1094
-
case 400:
1095
-
s.pages.Notice(w, "pull", "Branch based pull requests are not supported on this knot.")
1096
-
return
1097
-
}
1086
+
ex, err := comatproto.RepoGetRecord(r.Context(), client, "", tangled.RepoPullNSID, user.Did, pull.Rkey)
1087
+
if err != nil {
1088
+
// failed to get record
1089
+
s.pages.Notice(w, "resubmit-error", "Failed to update pull, no record found on PDS.")
1090
+
return
1091
+
}
1098
1092
1099
-
respBody, err := io.ReadAll(compareResp.Body)
1100
-
if err != nil {
1101
-
log.Println("failed to compare across branches")
1102
-
s.pages.Notice(w, "pull", "Failed to create pull request. Try again later.")
1103
-
return
1104
-
}
1105
-
defer compareResp.Body.Close()
1093
+
_, err = comatproto.RepoPutRecord(r.Context(), client, &comatproto.RepoPutRecord_Input{
1094
+
Collection: tangled.RepoPullNSID,
1095
+
Repo: user.Did,
1096
+
Rkey: pull.Rkey,
1097
+
SwapRecord: ex.Cid,
1098
+
Record: &lexutil.LexiconTypeDecoder{
1099
+
Val: &tangled.RepoPull{
1100
+
Title: pull.Title,
1101
+
PullId: int64(pull.PullId),
1102
+
TargetRepo: string(f.RepoAt),
1103
+
TargetBranch: pull.TargetBranch,
1104
+
Patch: patch, // new patch
1105
+
},
1106
+
},
1107
+
})
1108
+
if err != nil {
1109
+
log.Println("failed to update record", err)
1110
+
s.pages.Notice(w, "resubmit-error", "Failed to update pull request on the PDS. Try again later.")
1111
+
return
1112
+
}
1106
1113
1107
-
var diffTreeResponse types.RepoDiffTreeResponse
1108
-
err = json.Unmarshal(respBody, &diffTreeResponse)
1109
-
if err != nil {
1110
-
log.Println("failed to unmarshal diff tree response", err)
1111
-
s.pages.Notice(w, "pull", "Failed to create pull request. Try again later.")
1112
-
return
1113
-
}
1114
+
if err = tx.Commit(); err != nil {
1115
+
log.Println("failed to commit transaction", err)
1116
+
s.pages.Notice(w, "resubmit-error", "Failed to resubmit pull.")
1117
+
return
1118
+
}
1114
1119
1115
-
sourceRev = diffTreeResponse.DiffTree.Rev2
1116
-
patch = diffTreeResponse.DiffTree.Patch
1117
-
}
1120
+
s.pages.HxLocation(w, fmt.Sprintf("/%s/pulls/%d", f.OwnerSlashRepo(), pull.PullId))
1121
+
return
1122
+
}
1118
1123
1119
-
if patch == "" {
1120
-
s.pages.Notice(w, "resubmit-error", "Patch is empty.")
1121
-
return
1122
-
}
1124
+
func (s *State) resubmitBranch(w http.ResponseWriter, r *http.Request) {
1125
+
user := s.auth.GetUser(r)
1123
1126
1124
-
if patch == pull.LatestPatch() {
1125
-
s.pages.Notice(w, "resubmit-error", "Patch is identical to previous submission.")
1126
-
return
1127
-
}
1127
+
pull, ok := r.Context().Value("pull").(*db.Pull)
1128
+
if !ok {
1129
+
log.Println("failed to get pull")
1130
+
s.pages.Notice(w, "pull-error", "Failed to edit patch. Try again later.")
1131
+
return
1132
+
}
1128
1133
1129
-
if sourceRev == pull.Submissions[pull.LastRoundNumber()].SourceRev {
1130
-
s.pages.Notice(w, "resubmit-error", "This branch has not changed since the last submission.")
1131
-
return
1132
-
}
1134
+
f, err := fullyResolvedRepo(r)
1135
+
if err != nil {
1136
+
log.Println("failed to get repo and knot", err)
1137
+
return
1138
+
}
1133
1139
1134
-
if !isPatchValid(patch) {
1135
-
s.pages.Notice(w, "resubmit-error", "Invalid patch format. Please provide a valid diff.")
1136
-
return
1137
-
}
1140
+
if user.Did != pull.OwnerDid {
1141
+
log.Println("unauthorized user")
1142
+
w.WriteHeader(http.StatusUnauthorized)
1143
+
return
1144
+
}
1138
1145
1139
-
tx, err := s.db.BeginTx(r.Context(), nil)
1140
-
if err != nil {
1141
-
log.Println("failed to start tx")
1142
-
s.pages.Notice(w, "resubmit-error", "Failed to create pull request. Try again later.")
1143
-
return
1144
-
}
1145
-
defer tx.Rollback()
1146
+
if !f.RepoInfo(s, user).Roles.IsPushAllowed() {
1147
+
log.Println("unauthorized user")
1148
+
w.WriteHeader(http.StatusUnauthorized)
1149
+
return
1150
+
}
1146
1151
1147
-
err = db.ResubmitPull(tx, pull, patch, sourceRev)
1148
-
if err != nil {
1149
-
log.Println("failed to create pull request", err)
1150
-
s.pages.Notice(w, "resubmit-error", "Failed to create pull request. Try again later.")
1151
-
return
1152
-
}
1153
-
client, _ := s.auth.AuthorizedClient(r)
1152
+
ksClient, err := NewUnsignedClient(f.Knot, s.config.Dev)
1153
+
if err != nil {
1154
+
log.Printf("failed to create client for %s: %s", f.Knot, err)
1155
+
s.pages.Notice(w, "pull", "Failed to create pull request. Try again later.")
1156
+
return
1157
+
}
1154
1158
1155
-
ex, err := comatproto.RepoGetRecord(r.Context(), client, "", tangled.RepoPullNSID, user.Did, pull.Rkey)
1156
-
if err != nil {
1157
-
// failed to get record
1158
-
s.pages.Notice(w, "resubmit-error", "Failed to update pull, no record found on PDS.")
1159
-
return
1160
-
}
1159
+
compareResp, err := ksClient.Compare(f.OwnerDid(), f.RepoName, pull.TargetBranch, pull.PullSource.Branch)
1160
+
if err != nil {
1161
+
log.Printf("failed to compare branches: %s", err)
1162
+
s.pages.Notice(w, "pull", "Failed to create pull request. Try again later.")
1163
+
return
1164
+
}
1165
+
defer compareResp.Body.Close()
1161
1166
1162
-
_, err = comatproto.RepoPutRecord(r.Context(), client, &comatproto.RepoPutRecord_Input{
1163
-
Collection: tangled.RepoPullNSID,
1164
-
Repo: user.Did,
1165
-
Rkey: pull.Rkey,
1166
-
SwapRecord: ex.Cid,
1167
-
Record: &lexutil.LexiconTypeDecoder{
1168
-
Val: &tangled.RepoPull{
1169
-
Title: pull.Title,
1170
-
PullId: int64(pull.PullId),
1171
-
TargetRepo: string(f.RepoAt),
1172
-
TargetBranch: pull.TargetBranch,
1173
-
Patch: patch, // new patch
1174
-
Source: recordPullSource,
1175
-
},
1167
+
switch compareResp.StatusCode {
1168
+
case 404:
1169
+
case 400:
1170
+
s.pages.Notice(w, "pull", "Branch based pull requests are not supported on this knot.")
1171
+
return
1172
+
}
1173
+
1174
+
respBody, err := io.ReadAll(compareResp.Body)
1175
+
if err != nil {
1176
+
log.Println("failed to compare across branches")
1177
+
s.pages.Notice(w, "pull", "Failed to create pull request. Try again later.")
1178
+
return
1179
+
}
1180
+
defer compareResp.Body.Close()
1181
+
1182
+
var diffTreeResponse types.RepoDiffTreeResponse
1183
+
err = json.Unmarshal(respBody, &diffTreeResponse)
1184
+
if err != nil {
1185
+
log.Println("failed to unmarshal diff tree response", err)
1186
+
s.pages.Notice(w, "pull", "Failed to create pull request. Try again later.")
1187
+
return
1188
+
}
1189
+
1190
+
sourceRev := diffTreeResponse.DiffTree.Rev2
1191
+
patch := diffTreeResponse.DiffTree.Patch
1192
+
1193
+
if patch == "" {
1194
+
s.pages.Notice(w, "resubmit-error", "Patch is empty.")
1195
+
return
1196
+
}
1197
+
1198
+
if patch == pull.LatestPatch() {
1199
+
s.pages.Notice(w, "resubmit-error", "Patch is identical to previous submission.")
1200
+
return
1201
+
}
1202
+
1203
+
if !isPatchValid(patch) {
1204
+
s.pages.Notice(w, "resubmit-error", "Invalid patch format. Please provide a valid diff.")
1205
+
return
1206
+
}
1207
+
1208
+
if sourceRev == pull.Submissions[pull.LastRoundNumber()].SourceRev {
1209
+
s.pages.Notice(w, "resubmit-error", "This branch has not changed since the last submission.")
1210
+
return
1211
+
}
1212
+
1213
+
tx, err := s.db.BeginTx(r.Context(), nil)
1214
+
if err != nil {
1215
+
log.Println("failed to start tx")
1216
+
s.pages.Notice(w, "resubmit-error", "Failed to create pull request. Try again later.")
1217
+
return
1218
+
}
1219
+
defer tx.Rollback()
1220
+
1221
+
err = db.ResubmitPull(tx, pull, patch, sourceRev)
1222
+
if err != nil {
1223
+
log.Println("failed to create pull request", err)
1224
+
s.pages.Notice(w, "resubmit-error", "Failed to create pull request. Try again later.")
1225
+
return
1226
+
}
1227
+
client, _ := s.auth.AuthorizedClient(r)
1228
+
1229
+
ex, err := comatproto.RepoGetRecord(r.Context(), client, "", tangled.RepoPullNSID, user.Did, pull.Rkey)
1230
+
if err != nil {
1231
+
// failed to get record
1232
+
s.pages.Notice(w, "resubmit-error", "Failed to update pull, no record found on PDS.")
1233
+
return
1234
+
}
1235
+
1236
+
recordPullSource := &tangled.RepoPull_Source{
1237
+
Branch: pull.PullSource.Branch,
1238
+
}
1239
+
_, err = comatproto.RepoPutRecord(r.Context(), client, &comatproto.RepoPutRecord_Input{
1240
+
Collection: tangled.RepoPullNSID,
1241
+
Repo: user.Did,
1242
+
Rkey: pull.Rkey,
1243
+
SwapRecord: ex.Cid,
1244
+
Record: &lexutil.LexiconTypeDecoder{
1245
+
Val: &tangled.RepoPull{
1246
+
Title: pull.Title,
1247
+
PullId: int64(pull.PullId),
1248
+
TargetRepo: string(f.RepoAt),
1249
+
TargetBranch: pull.TargetBranch,
1250
+
Patch: patch, // new patch
1251
+
Source: recordPullSource,
1176
1252
},
1177
-
})
1178
-
if err != nil {
1179
-
log.Println("failed to update record", err)
1180
-
s.pages.Notice(w, "resubmit-error", "Failed to update pull request on the PDS. Try again later.")
1181
-
return
1182
-
}
1253
+
},
1254
+
})
1255
+
if err != nil {
1256
+
log.Println("failed to update record", err)
1257
+
s.pages.Notice(w, "resubmit-error", "Failed to update pull request on the PDS. Try again later.")
1258
+
return
1259
+
}
1260
+
1261
+
if err = tx.Commit(); err != nil {
1262
+
log.Println("failed to commit transaction", err)
1263
+
s.pages.Notice(w, "resubmit-error", "Failed to resubmit pull.")
1264
+
return
1265
+
}
1266
+
1267
+
s.pages.HxLocation(w, fmt.Sprintf("/%s/pulls/%d", f.OwnerSlashRepo(), pull.PullId))
1268
+
return
1269
+
}
1270
+
1271
+
func (s *State) resubmitFork(w http.ResponseWriter, r *http.Request) {
1272
+
user := s.auth.GetUser(r)
1273
+
1274
+
pull, ok := r.Context().Value("pull").(*db.Pull)
1275
+
if !ok {
1276
+
log.Println("failed to get pull")
1277
+
s.pages.Notice(w, "pull-error", "Failed to edit patch. Try again later.")
1278
+
return
1279
+
}
1280
+
1281
+
f, err := fullyResolvedRepo(r)
1282
+
if err != nil {
1283
+
log.Println("failed to get repo and knot", err)
1284
+
return
1285
+
}
1286
+
1287
+
if user.Did != pull.OwnerDid {
1288
+
log.Println("unauthorized user")
1289
+
w.WriteHeader(http.StatusUnauthorized)
1290
+
return
1291
+
}
1292
+
1293
+
forkRepo, err := db.GetRepoByAtUri(s.db, pull.PullSource.RepoAt.String())
1294
+
if err != nil {
1295
+
log.Println("failed to get source repo", err)
1296
+
s.pages.Notice(w, "pull", "Failed to create pull request. Try again later.")
1297
+
return
1298
+
}
1299
+
1300
+
// extract patch by performing compare
1301
+
ksClient, err := NewUnsignedClient(forkRepo.Knot, s.config.Dev)
1302
+
if err != nil {
1303
+
log.Printf("failed to create client for %s: %s", forkRepo.Knot, err)
1304
+
s.pages.Notice(w, "pull", "Failed to create pull request. Try again later.")
1305
+
return
1306
+
}
1307
+
1308
+
secret, err := db.GetRegistrationKey(s.db, forkRepo.Knot)
1309
+
if err != nil {
1310
+
log.Printf("failed to get registration key for %s: %s", forkRepo.Knot, err)
1311
+
s.pages.Notice(w, "pull", "Failed to create pull request. Try again later.")
1312
+
return
1313
+
}
1314
+
// update the hidden tracking branch to latest
1315
+
signedClient, err := NewSignedClient(forkRepo.Knot, secret, s.config.Dev)
1316
+
if err != nil {
1317
+
log.Printf("failed to create signed client for %s: %s", forkRepo.Knot, err)
1318
+
s.pages.Notice(w, "pull", "Failed to create pull request. Try again later.")
1319
+
return
1320
+
}
1321
+
resp, err := signedClient.NewHiddenRef(forkRepo.Did, forkRepo.Name, pull.PullSource.Branch, pull.TargetBranch)
1322
+
if err != nil || resp.StatusCode != http.StatusNoContent {
1323
+
log.Printf("failed to update tracking branch: %s", err)
1324
+
s.pages.Notice(w, "pull", "Failed to create pull request. Try again later.")
1325
+
return
1326
+
}
1327
+
1328
+
hiddenRef := url.QueryEscape(fmt.Sprintf("hidden/%s/%s", pull.PullSource.Branch, pull.TargetBranch))
1329
+
compareResp, err := ksClient.Compare(forkRepo.Did, forkRepo.Name, hiddenRef, pull.PullSource.Branch)
1330
+
if err != nil {
1331
+
log.Printf("failed to compare branches: %s", err)
1332
+
s.pages.Notice(w, "pull", "Failed to create pull request. Try again later.")
1333
+
return
1334
+
}
1335
+
defer compareResp.Body.Close()
1336
+
1337
+
switch compareResp.StatusCode {
1338
+
case 404:
1339
+
case 400:
1340
+
s.pages.Notice(w, "pull", "Branch based pull requests are not supported on this knot.")
1341
+
return
1342
+
}
1343
+
1344
+
respBody, err := io.ReadAll(compareResp.Body)
1345
+
if err != nil {
1346
+
log.Println("failed to compare across branches")
1347
+
s.pages.Notice(w, "pull", "Failed to create pull request. Try again later.")
1348
+
return
1349
+
}
1350
+
defer compareResp.Body.Close()
1183
1351
1184
-
if err = tx.Commit(); err != nil {
1185
-
log.Println("failed to commit transaction", err)
1186
-
s.pages.Notice(w, "resubmit-error", "Failed to resubmit pull.")
1187
-
return
1188
-
}
1352
+
var diffTreeResponse types.RepoDiffTreeResponse
1353
+
err = json.Unmarshal(respBody, &diffTreeResponse)
1354
+
if err != nil {
1355
+
log.Println("failed to unmarshal diff tree response", err)
1356
+
s.pages.Notice(w, "pull", "Failed to create pull request. Try again later.")
1357
+
return
1358
+
}
1359
+
1360
+
sourceRev := diffTreeResponse.DiffTree.Rev2
1361
+
patch := diffTreeResponse.DiffTree.Patch
1189
1362
1190
-
s.pages.HxLocation(w, fmt.Sprintf("/%s/pulls/%d", f.OwnerSlashRepo(), pull.PullId))
1363
+
if patch == "" {
1364
+
s.pages.Notice(w, "resubmit-error", "Patch is empty.")
1365
+
return
1366
+
}
1367
+
1368
+
if patch == pull.LatestPatch() {
1369
+
s.pages.Notice(w, "resubmit-error", "Patch is identical to previous submission.")
1191
1370
return
1192
1371
}
1372
+
1373
+
if !isPatchValid(patch) {
1374
+
s.pages.Notice(w, "resubmit-error", "Invalid patch format. Please provide a valid diff.")
1375
+
return
1376
+
}
1377
+
1378
+
if sourceRev == pull.Submissions[pull.LastRoundNumber()].SourceRev {
1379
+
s.pages.Notice(w, "resubmit-error", "This branch has not changed since the last submission.")
1380
+
return
1381
+
}
1382
+
1383
+
tx, err := s.db.BeginTx(r.Context(), nil)
1384
+
if err != nil {
1385
+
log.Println("failed to start tx")
1386
+
s.pages.Notice(w, "resubmit-error", "Failed to create pull request. Try again later.")
1387
+
return
1388
+
}
1389
+
defer tx.Rollback()
1390
+
1391
+
err = db.ResubmitPull(tx, pull, patch, sourceRev)
1392
+
if err != nil {
1393
+
log.Println("failed to create pull request", err)
1394
+
s.pages.Notice(w, "resubmit-error", "Failed to create pull request. Try again later.")
1395
+
return
1396
+
}
1397
+
client, _ := s.auth.AuthorizedClient(r)
1398
+
1399
+
ex, err := comatproto.RepoGetRecord(r.Context(), client, "", tangled.RepoPullNSID, user.Did, pull.Rkey)
1400
+
if err != nil {
1401
+
// failed to get record
1402
+
s.pages.Notice(w, "resubmit-error", "Failed to update pull, no record found on PDS.")
1403
+
return
1404
+
}
1405
+
1406
+
repoAt := pull.PullSource.RepoAt.String()
1407
+
recordPullSource := &tangled.RepoPull_Source{
1408
+
Branch: pull.PullSource.Branch,
1409
+
Repo: &repoAt,
1410
+
}
1411
+
_, err = comatproto.RepoPutRecord(r.Context(), client, &comatproto.RepoPutRecord_Input{
1412
+
Collection: tangled.RepoPullNSID,
1413
+
Repo: user.Did,
1414
+
Rkey: pull.Rkey,
1415
+
SwapRecord: ex.Cid,
1416
+
Record: &lexutil.LexiconTypeDecoder{
1417
+
Val: &tangled.RepoPull{
1418
+
Title: pull.Title,
1419
+
PullId: int64(pull.PullId),
1420
+
TargetRepo: string(f.RepoAt),
1421
+
TargetBranch: pull.TargetBranch,
1422
+
Patch: patch, // new patch
1423
+
Source: recordPullSource,
1424
+
},
1425
+
},
1426
+
})
1427
+
if err != nil {
1428
+
log.Println("failed to update record", err)
1429
+
s.pages.Notice(w, "resubmit-error", "Failed to update pull request on the PDS. Try again later.")
1430
+
return
1431
+
}
1432
+
1433
+
if err = tx.Commit(); err != nil {
1434
+
log.Println("failed to commit transaction", err)
1435
+
s.pages.Notice(w, "resubmit-error", "Failed to resubmit pull.")
1436
+
return
1437
+
}
1438
+
1439
+
s.pages.HxLocation(w, fmt.Sprintf("/%s/pulls/%d", f.OwnerSlashRepo(), pull.PullId))
1440
+
return
1193
1441
}
1194
1442
1195
1443
func (s *State) MergePull(w http.ResponseWriter, r *http.Request) {
+1
-1
flake.nix
+1
-1
flake.nix
···
420
420
g = config.services.tangled-knotserver.gitUser;
421
421
in [
422
422
"d /var/lib/knotserver 0770 ${u} ${g} - -" # Create the directory first
423
-
"f+ /var/lib/knotserver/secret 0660 ${u} ${g} - KNOT_SERVER_SECRET=6995e040e80e2d593b5e5e9ca611a70140b9ef8044add0a28b48b1ee34aa3e85"
423
+
"f+ /var/lib/knotserver/secret 0660 ${u} ${g} - KNOT_SERVER_SECRET=5b42390da4c6659f34c9a545adebd8af82c4a19960d735f651e3d582623ba9f2"
424
424
];
425
425
services.tangled-knotserver = {
426
426
enable = true;