Mirror of @tangled.org/core. Running on a Raspberry Pi Zero 2 (Please be gentle).
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

appview/pulls: improve ui + validate patches

authored by

Anirudh Oppiliappan and committed by
Akshay
26f6bc6b d32b264d

+98 -57
+1 -4
appview/pages/templates/repo/issues/issue.html
··· 1 - {{ define "title" }} 2 - {{ .Issue.Title }} &middot; issue #{{ .Issue.IssueId }} &middot; 3 - {{ .RepoInfo.FullName }} 4 - {{ end }} 1 + {{ define "title" }}{{ .Issue.Title }} &middot; issue #{{ .Issue.IssueId }} &middot;{{ .RepoInfo.FullName }}{{ end }} 5 2 6 3 {{ define "repoContent" }} 7 4 <header class="pb-4">
+15 -9
appview/pages/templates/repo/pulls/new.html
··· 15 15 <p class="text-gray-500"> 16 16 The branch you want to make your change against. 17 17 </p> 18 - <select name="targetBranch" class="p-1 border border-gray-200 bg-white"> 19 - <option disabled selected>select a branch</option> 20 - {{ range .Branches }} 21 - <option 22 - value="{{ .Reference.Name }}" 23 - class="py-1"> 24 - {{ .Reference.Name }} 25 - </option> 26 - {{ end }} 18 + <select 19 + name="targetBranch" 20 + class="p-1 border border-gray-200 bg-white" 21 + > 22 + <option disabled selected>select a branch</option> 23 + {{ range .Branches }} 24 + <option value="{{ .Reference.Name }}" class="py-1"> 25 + {{ .Reference.Name }} 26 + </option> 27 + {{ end }} 27 28 </select> 28 29 </div> 29 30 <div> ··· 45 44 rows="10" 46 45 class="w-full resize-y font-mono" 47 46 placeholder="Paste your git-format-patch output here." 47 + hx-post="/pulls/validate" 48 + hx-trigger="input changed delay:500ms" 49 + hx-target="#patch-validation" 50 + hx-include="[name='patch']" 48 51 ></textarea> 52 + <div id="pull-validate"></div> 49 53 </div> 50 54 </div> 51 55 <div>
+29 -38
appview/pages/templates/repo/pulls/pull.html
··· 69 69 {{ $isPullAuthor := and .LoggedInUser (eq .LoggedInUser.Did .Pull.OwnerDid) }} 70 70 {{ $isPushAllowed := .RepoInfo.Roles.IsPushAllowed }} 71 71 72 - {{ if $isPullAuthor }} 72 + {{ if and $isPullAuthor (not .Pull.State.IsMerged) }} 73 73 <section id="update-card" class="mt-8 space-y-4 relative"> 74 74 {{ block "resubmitCard" . }} {{ end }} 75 75 </section> ··· 86 86 {{ end }} 87 87 {{ end }} 88 88 </section> 89 - 90 - {{ if and (or $isPullAuthor $isPushAllowed) (not .Pull.State.IsMerged) }} 91 - {{ $action := "close" }} 92 - {{ $icon := "circle-x" }} 93 - {{ $hoverColor := "red" }} 94 - {{ if .Pull.State.IsClosed }} 95 - {{ $action = "reopen" }} 96 - {{ $icon = "circle-dot" }} 97 - {{ $hoverColor = "green" }} 98 - {{ end }} 99 - <button 100 - hx-post="/{{ .RepoInfo.FullName }}/pulls/{{ .Pull.PullId }}/{{ $action }}" 101 - hx-swap="none" 102 - class="btn mt-8 text-sm flex items-center gap-2"> 103 - <i data-lucide="{{ $icon }}" class="w-4 h-4 mr-2 text-{{ $hoverColor }}-400"></i> 104 - <span class="text-black">{{ $action }}</span> 105 - </button> 106 - {{ end }} 107 89 108 90 <div id="pull-close"></div> 109 91 <div id="pull-reopen"></div> ··· 184 202 <div 185 203 id="merge-status-card" 186 204 class="rounded relative bg-purple-50 border border-purple-200 p-4"> 187 - {{ if gt (len .Comments) 0 }} 188 - <div 189 - class="absolute left-8 -top-4 w-px h-4 bg-gray-300" 190 - ></div> 191 - {{ else }} 192 - <div 193 - class="absolute left-8 -top-8 w-px h-8 bg-gray-300" 194 - ></div> 195 - {{ end }} 196 - 197 205 198 206 <div class="flex items-center gap-2 text-purple-500"> 199 207 <i data-lucide="git-merge" class="w-4 h-4"></i> 200 208 <span class="font-medium" 201 - >Pull request successfully merged</span 209 + >pull request successfully merged</span 202 210 > 203 211 </div> 204 212 ··· 235 263 236 264 {{ define "noConflictsCard" }} 237 265 {{ $isPushAllowed := .RepoInfo.Roles.IsPushAllowed }} 266 + {{ $isPullAuthor := and .LoggedInUser (eq .LoggedInUser.Did .Pull.OwnerDid) }} 238 267 <div 239 268 id="merge-status-card" 240 269 class="rounded relative border bg-green-50 border-green-200 p-4"> ··· 264 291 </button> 265 292 {{ end }} 266 293 294 + {{ if and (or $isPullAuthor $isPushAllowed) (not .Pull.State.IsMerged) }} 295 + {{ $action := "close" }} 296 + {{ $icon := "circle-x" }} 297 + {{ $hoverColor := "red" }} 298 + {{ if .Pull.State.IsClosed }} 299 + {{ $action = "reopen" }} 300 + {{ $icon = "circle-dot" }} 301 + {{ $hoverColor = "green" }} 302 + {{ end }} 303 + <button 304 + hx-post="/{{ .RepoInfo.FullName }}/pulls/{{ .Pull.PullId }}/{{ $action }}" 305 + hx-swap="none" 306 + class="btn mt-4 flex items-center gap-2"> 307 + <i data-lucide="{{ $icon }}" class="w-4 h-4 text-{{ $hoverColor }}-400"></i> 308 + <span class="text-black">{{ $action }}</span> 309 + </button> 310 + {{ end }} 311 + 267 312 <div id="pull-merge-error" class="error"></div> 268 313 <div id="pull-merge-success" class="success"></div> 269 314 </div> ··· 295 304 296 305 <div class="flex items-center gap-2 text-amber-500"> 297 306 <i data-lucide="edit" class="w-4 h-4"></i> 298 - <span class="font-medium">Resubmit your patch</span> 307 + <span class="font-medium">resubmit your patch</span> 299 308 </div> 300 309 301 310 <div class="mt-2 text-sm text-gray-700"> 302 - You can update this patch to address reviews if any. 303 - This begins a new round of reviews, 304 - you can still view your previous submissions and reviews. 311 + You can update this patch to address any reviews. 312 + This will begin a new round of reviews, 313 + but you'll still be able to view your previous submissions and feedback. 305 314 </div> 306 315 307 - <div class="mt-4 flex items-center gap-2"> 308 - <form hx-post="/{{ .RepoInfo.FullName }}/pulls/{{ .Pull.PullId }}/resubmit" class="w-full"> 316 + <div class="mt-4 flex flex-col"> 317 + <form hx-post="/{{ .RepoInfo.FullName }}/pulls/{{ .Pull.PullId }}/resubmit" class="w-full" hx-swap="none"> 309 318 <textarea 310 319 name="patch" 311 - class="w-full p-2 rounded border border-gray-200" 312 - placeholder="Enter new patch" 320 + class="w-full p-2 mb-2 rounded border border-gray-200" 321 + placeholder="Paste your updated patch here." 313 322 ></textarea> 314 323 <button 315 324 type="submit"
+37 -1
appview/state/pull.go
··· 7 7 "log" 8 8 "net/http" 9 9 "strconv" 10 + "strings" 10 11 "time" 11 12 12 13 "github.com/sotangled/tangled/api/tangled" ··· 301 300 return 302 301 } 303 302 303 + // Validate patch format 304 + if !isPatchValid(patch) { 305 + s.pages.Notice(w, "pull", "Invalid patch format. Please provide a valid diff.") 306 + return 307 + } 308 + 304 309 tx, err := s.db.BeginTx(r.Context(), nil) 305 310 if err != nil { 306 311 log.Println("failed to start tx") ··· 399 392 return 400 393 } 401 394 395 + // Validate patch format 396 + if !isPatchValid(patch) { 397 + s.pages.Notice(w, "resubmit-error", "Invalid patch format. Please provide a valid diff.") 398 + return 399 + } 400 + 402 401 tx, err := s.db.BeginTx(r.Context(), nil) 403 402 if err != nil { 404 403 log.Println("failed to start tx") ··· 491 478 } 492 479 493 480 // Merge the pull request 494 - resp, err := ksClient.Merge([]byte(pull.LatestPatch()), user.Did, f.RepoName, pull.TargetBranch) 481 + resp, err := ksClient.Merge([]byte(pull.LatestPatch()), user.Did, f.RepoName, pull.TargetBranch, pull.Title, pull.Body, "", "") 495 482 if err != nil { 496 483 log.Printf("failed to merge pull request: %s", err) 497 484 s.pages.Notice(w, "pull-merge-error", "Failed to merge pull request. Try again later.") ··· 619 606 620 607 s.pages.HxLocation(w, fmt.Sprintf("/%s/pulls/%d", f.OwnerSlashRepo(), pull.PullId)) 621 608 return 609 + } 610 + 611 + // Very basic validation to check if it looks like a diff/patch 612 + // A valid patch usually starts with diff or --- lines 613 + func isPatchValid(patch string) bool { 614 + // Basic validation to check if it looks like a diff/patch 615 + // A valid patch usually starts with diff or --- lines 616 + if len(patch) == 0 { 617 + return false 618 + } 619 + 620 + lines := strings.Split(patch, "\n") 621 + if len(lines) < 2 { 622 + return false 623 + } 624 + 625 + // Check for common patch format markers 626 + firstLine := strings.TrimSpace(lines[0]) 627 + return strings.HasPrefix(firstLine, "diff ") || 628 + strings.HasPrefix(firstLine, "--- ") || 629 + strings.HasPrefix(firstLine, "Index: ") || 630 + strings.HasPrefix(firstLine, "+++ ") || 631 + strings.HasPrefix(firstLine, "@@ ") 622 632 }
+16 -5
appview/state/signer.go
··· 10 10 "net/http" 11 11 "net/url" 12 12 "time" 13 + 14 + "github.com/sotangled/tangled/types" 13 15 ) 14 16 15 17 type SignerTransport struct { ··· 158 156 return s.client.Do(req) 159 157 } 160 158 161 - func (s *SignedClient) Merge(patch []byte, ownerDid, targetRepo, branch string) (*http.Response, error) { 159 + func (s *SignedClient) Merge( 160 + patch []byte, 161 + ownerDid, targetRepo, branch, commitMessage, commitBody, authorName, authorEmail string, 162 + ) (*http.Response, error) { 162 163 const ( 163 164 Method = "POST" 164 165 ) 165 166 endpoint := fmt.Sprintf("/%s/%s/merge", ownerDid, targetRepo) 167 + 168 + mr := types.MergeRequest{ 169 + Branch: branch, 170 + CommitMessage: commitMessage, 171 + CommitBody: commitBody, 172 + AuthorName: authorName, 173 + AuthorEmail: authorEmail, 174 + Patch: string(patch), 175 + } 166 176 167 - body, _ := json.Marshal(map[string]interface{}{ 168 - "patch": string(patch), 169 - "branch": branch, 170 - }) 177 + body, _ := json.Marshal(mr) 171 178 172 179 req, err := s.newRequest(Method, endpoint, body) 173 180 if err != nil {