forked from tangled.org/core
Monorepo for Tangled

wip

Changed files
+422 -164
appview
db
pages
templates
fragments
repo
state
+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
··· 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
··· 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
··· 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
··· 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
··· 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;