Monorepo for Tangled tangled.org

appview,knotserver: produce combined patch in comparisons

this is calculated by the knotserver in sh.tangled.repo.compare and
cached by the appview in pull submissions, this cannot be calculated on
the appview side with just the format-patch because this calculation
requires a git-index.

Signed-off-by: oppiliappan <me@oppi.li>

oppi.li 808807f5 196d3df7

verified
Changed files
+95 -67
appview
db
models
pulls
repo
knotserver
types
+9
appview/db/db.go
··· 1097 1097 }) 1098 1098 conn.ExecContext(ctx, "pragma foreign_keys = on;") 1099 1099 1100 + // knots may report the combined patch for a comparison, we can store that on the appview side 1101 + // (but not on the pds record), because calculating the combined patch requires a git index 1102 + runMigration(conn, logger, "add-combined-column-submissions", func(tx *sql.Tx) error { 1103 + _, err := tx.Exec(` 1104 + alter table pull_submissions add column combined text; 1105 + `) 1106 + return err 1107 + }) 1108 + 1100 1109 return &DB{ 1101 1110 db, 1102 1111 logger,
+21 -17
appview/db/pulls.go
··· 90 90 pull.ID = int(id) 91 91 92 92 _, err = tx.Exec(` 93 - insert into pull_submissions (pull_at, round_number, patch, source_rev) 94 - values (?, ?, ?, ?) 95 - `, pull.PullAt(), 0, pull.Submissions[0].Patch, pull.Submissions[0].SourceRev) 93 + insert into pull_submissions (pull_at, round_number, patch, combined, source_rev) 94 + values (?, ?, ?, ?, ?) 95 + `, pull.PullAt(), 0, pull.Submissions[0].Patch, pull.Submissions[0].Combined, pull.Submissions[0].SourceRev) 96 96 return err 97 97 } 98 98 ··· 313 313 pull_at, 314 314 round_number, 315 315 patch, 316 + combined, 316 317 created, 317 318 source_rev 318 319 from ··· 332 333 333 334 for rows.Next() { 334 335 var submission models.PullSubmission 335 - var createdAt string 336 - var sourceRev sql.NullString 336 + var submissionCreatedStr string 337 + var submissionSourceRev, submissionCombined sql.NullString 337 338 err := rows.Scan( 338 339 &submission.ID, 339 340 &submission.PullAt, 340 341 &submission.RoundNumber, 341 342 &submission.Patch, 342 - &createdAt, 343 - &sourceRev, 343 + &submissionCombined, 344 + &submissionCreatedStr, 345 + &submissionSourceRev, 344 346 ) 345 347 if err != nil { 346 348 return nil, err 347 349 } 348 350 349 - createdTime, err := time.Parse(time.RFC3339, createdAt) 350 - if err != nil { 351 - return nil, err 351 + if t, err := time.Parse(time.RFC3339, submissionCreatedStr); err == nil { 352 + submission.Created = t 353 + } 354 + 355 + if submissionSourceRev.Valid { 356 + submission.SourceRev = submissionSourceRev.String 352 357 } 353 - submission.Created = createdTime 354 358 355 - if sourceRev.Valid { 356 - submission.SourceRev = sourceRev.String 359 + if submissionCombined.Valid { 360 + submission.Combined = submissionCombined.String 357 361 } 358 362 359 363 submissionMap[submission.ID] = &submission ··· 590 594 return err 591 595 } 592 596 593 - func ResubmitPull(e Execer, pull *models.Pull, newPatch, sourceRev string) error { 597 + func ResubmitPull(e Execer, pull *models.Pull, newPatch, combined, sourceRev string) error { 594 598 newRoundNumber := len(pull.Submissions) 595 599 _, err := e.Exec(` 596 - insert into pull_submissions (pull_at, round_number, patch, source_rev) 597 - values (?, ?, ?, ?) 598 - `, pull.PullAt(), newRoundNumber, newPatch, sourceRev) 600 + insert into pull_submissions (pull_at, round_number, patch, combined, source_rev) 601 + values (?, ?, ?, ?, ?) 602 + `, pull.PullAt(), newRoundNumber, newPatch, combined, sourceRev) 599 603 600 604 return err 601 605 }
+9
appview/models/pull.go
··· 134 134 // content 135 135 RoundNumber int 136 136 Patch string 137 + Combined string 137 138 Comments []PullComment 138 139 SourceRev string // include the rev that was used to create this submission: only for branch/fork PRs 139 140 ··· 261 262 } 262 263 263 264 return participants 265 + } 266 + 267 + func (s PullSubmission) CombinedPatch() string { 268 + if s.Combined == "" { 269 + return s.Patch 270 + } 271 + 272 + return s.Combined 264 273 } 265 274 266 275 type Stack []*Pull
+23 -40
appview/pulls/pulls.go
··· 146 146 stack, _ := r.Context().Value("stack").(models.Stack) 147 147 abandonedPulls, _ := r.Context().Value("abandonedPulls").([]*models.Pull) 148 148 149 - totalIdents := 1 150 - for _, submission := range pull.Submissions { 151 - totalIdents += len(submission.Comments) 152 - } 153 - 154 - identsToResolve := make([]string, totalIdents) 155 - 156 - // populate idents 157 - identsToResolve[0] = pull.OwnerDid 158 - idx := 1 159 - for _, submission := range pull.Submissions { 160 - for _, comment := range submission.Comments { 161 - identsToResolve[idx] = comment.OwnerDid 162 - idx += 1 163 - } 164 - } 165 - 166 149 mergeCheckResponse := s.mergeCheck(r, f, pull, stack) 167 150 branchDeleteStatus := s.branchDeleteStatus(r, f, pull) 168 151 resubmitResult := pages.Unknown ··· 460 443 return 461 444 } 462 445 463 - patch := pull.Submissions[roundIdInt].Patch 446 + patch := pull.Submissions[roundIdInt].CombinedPatch() 464 447 diff := patchutil.AsNiceDiff(patch, pull.TargetBranch) 465 448 466 449 s.pages.RepoPullPatchPage(w, pages.RepoPullPatchParams{ ··· 511 494 return 512 495 } 513 496 514 - currentPatch, err := patchutil.AsDiff(pull.Submissions[roundIdInt].Patch) 497 + currentPatch, err := patchutil.AsDiff(pull.Submissions[roundIdInt].CombinedPatch()) 515 498 if err != nil { 516 499 log.Println("failed to interdiff; current patch malformed") 517 500 s.pages.Notice(w, fmt.Sprintf("interdiff-error-%d", roundIdInt), "Failed to calculate interdiff; current patch is invalid.") 518 501 return 519 502 } 520 503 521 - previousPatch, err := patchutil.AsDiff(pull.Submissions[roundIdInt-1].Patch) 504 + previousPatch, err := patchutil.AsDiff(pull.Submissions[roundIdInt-1].CombinedPatch()) 522 505 if err != nil { 523 506 log.Println("failed to interdiff; previous patch malformed") 524 507 s.pages.Notice(w, fmt.Sprintf("interdiff-error-%d", roundIdInt), "Failed to calculate interdiff; previous patch is invalid.") ··· 720 703 721 704 createdAt := time.Now().Format(time.RFC3339) 722 705 723 - pullAt, err := db.GetPullAt(s.db, f.RepoAt(), pull.PullId) 724 - if err != nil { 725 - log.Println("failed to get pull at", err) 726 - s.pages.Notice(w, "pull-comment", "Failed to create comment.") 727 - return 728 - } 729 - 730 706 client, err := s.oauth.AuthorizedClient(r) 731 707 if err != nil { 732 708 log.Println("failed to get authorized client", err) ··· 739 715 Rkey: tid.TID(), 740 716 Record: &lexutil.LexiconTypeDecoder{ 741 717 Val: &tangled.RepoPullComment{ 742 - Pull: string(pullAt), 718 + Pull: pull.PullAt().String(), 743 719 Body: body, 744 720 CreatedAt: createdAt, 745 721 }, ··· 987 963 } 988 964 989 965 sourceRev := comparison.Rev2 990 - patch := comparison.Patch 966 + patch := comparison.FormatPatchRaw 967 + combined := comparison.CombinedPatchRaw 991 968 992 969 if !patchutil.IsPatchValid(patch) { 993 970 s.pages.Notice(w, "pull", "Invalid patch format. Please provide a valid diff.") ··· 1002 979 Sha: comparison.Rev2, 1003 980 } 1004 981 1005 - s.createPullRequest(w, r, f, user, title, body, targetBranch, patch, sourceRev, pullSource, recordPullSource, isStacked) 982 + s.createPullRequest(w, r, f, user, title, body, targetBranch, patch, combined, sourceRev, pullSource, recordPullSource, isStacked) 1006 983 } 1007 984 1008 985 func (s *Pulls) handlePatchBasedPull(w http.ResponseWriter, r *http.Request, f *reporesolver.ResolvedRepo, user *oauth.User, title, body, targetBranch, patch string, isStacked bool) { ··· 1011 988 return 1012 989 } 1013 990 1014 - s.createPullRequest(w, r, f, user, title, body, targetBranch, patch, "", nil, nil, isStacked) 991 + s.createPullRequest(w, r, f, user, title, body, targetBranch, patch, "", "", nil, nil, isStacked) 1015 992 } 1016 993 1017 994 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) { ··· 1094 1071 } 1095 1072 1096 1073 sourceRev := comparison.Rev2 1097 - patch := comparison.Patch 1074 + patch := comparison.FormatPatchRaw 1075 + combined := comparison.CombinedPatchRaw 1098 1076 1099 1077 if !patchutil.IsPatchValid(patch) { 1100 1078 s.pages.Notice(w, "pull", "Invalid patch format. Please provide a valid diff.") ··· 1114 1092 Sha: sourceRev, 1115 1093 } 1116 1094 1117 - s.createPullRequest(w, r, f, user, title, body, targetBranch, patch, sourceRev, pullSource, recordPullSource, isStacked) 1095 + s.createPullRequest(w, r, f, user, title, body, targetBranch, patch, combined, sourceRev, pullSource, recordPullSource, isStacked) 1118 1096 } 1119 1097 1120 1098 func (s *Pulls) createPullRequest( ··· 1124 1102 user *oauth.User, 1125 1103 title, body, targetBranch string, 1126 1104 patch string, 1105 + combined string, 1127 1106 sourceRev string, 1128 1107 pullSource *models.PullSource, 1129 1108 recordPullSource *tangled.RepoPull_Source, ··· 1183 1162 rkey := tid.TID() 1184 1163 initialSubmission := models.PullSubmission{ 1185 1164 Patch: patch, 1165 + Combined: combined, 1186 1166 SourceRev: sourceRev, 1187 1167 } 1188 1168 pull := &models.Pull{ ··· 1612 1592 1613 1593 patch := r.FormValue("patch") 1614 1594 1615 - s.resubmitPullHelper(w, r, f, user, pull, patch, "") 1595 + s.resubmitPullHelper(w, r, f, user, pull, patch, "", "") 1616 1596 } 1617 1597 1618 1598 func (s *Pulls) resubmitBranch(w http.ResponseWriter, r *http.Request) { ··· 1673 1653 } 1674 1654 1675 1655 sourceRev := comparison.Rev2 1676 - patch := comparison.Patch 1656 + patch := comparison.FormatPatchRaw 1657 + combined := comparison.CombinedPatchRaw 1677 1658 1678 - s.resubmitPullHelper(w, r, f, user, pull, patch, sourceRev) 1659 + s.resubmitPullHelper(w, r, f, user, pull, patch, combined, sourceRev) 1679 1660 } 1680 1661 1681 1662 func (s *Pulls) resubmitFork(w http.ResponseWriter, r *http.Request) { ··· 1768 1749 comparison := forkComparison 1769 1750 1770 1751 sourceRev := comparison.Rev2 1771 - patch := comparison.Patch 1752 + patch := comparison.FormatPatchRaw 1753 + combined := comparison.CombinedPatchRaw 1772 1754 1773 - s.resubmitPullHelper(w, r, f, user, pull, patch, sourceRev) 1755 + s.resubmitPullHelper(w, r, f, user, pull, patch, combined, sourceRev) 1774 1756 } 1775 1757 1776 1758 // validate a resubmission against a pull request ··· 1797 1779 user *oauth.User, 1798 1780 pull *models.Pull, 1799 1781 patch string, 1782 + combined string, 1800 1783 sourceRev string, 1801 1784 ) { 1802 1785 if pull.IsStacked() { ··· 1826 1809 } 1827 1810 defer tx.Rollback() 1828 1811 1829 - err = db.ResubmitPull(tx, pull, patch, sourceRev) 1812 + err = db.ResubmitPull(tx, pull, patch, combined, sourceRev) 1830 1813 if err != nil { 1831 1814 log.Println("failed to create pull request", err) 1832 1815 s.pages.Notice(w, "resubmit-error", "Failed to create pull request. Try again later.") ··· 2042 2025 submission := np.Submissions[np.LastRoundNumber()] 2043 2026 2044 2027 // resubmit the old pull 2045 - err := db.ResubmitPull(tx, op, submission.Patch, submission.SourceRev) 2028 + err := db.ResubmitPull(tx, op, submission.Patch, submission.Combined, submission.SourceRev) 2046 2029 2047 2030 if err != nil { 2048 2031 log.Println("failed to update pull", err, op.PullId)
+6 -1
appview/repo/repo.go
··· 2565 2565 return 2566 2566 } 2567 2567 2568 - diff := patchutil.AsNiceDiff(formatPatch.Patch, base) 2568 + var diff types.NiceDiff 2569 + if formatPatch.CombinedPatchRaw != "" { 2570 + diff = patchutil.AsNiceDiff(formatPatch.CombinedPatchRaw, base) 2571 + } else { 2572 + diff = patchutil.AsNiceDiff(formatPatch.FormatPatchRaw, base) 2573 + } 2569 2574 2570 2575 repoinfo := f.RepoInfo(user) 2571 2576
+20 -4
knotserver/xrpc/repo_compare.go
··· 4 4 "fmt" 5 5 "net/http" 6 6 7 + "github.com/bluekeyes/go-gitdiff/gitdiff" 7 8 "tangled.org/core/knotserver/git" 8 9 "tangled.org/core/types" 9 10 xrpcerr "tangled.org/core/xrpc/errors" ··· 71 72 return 72 73 } 73 74 75 + var combinedPatch []*gitdiff.File 76 + var combinedPatchRaw string 77 + // we need the combined patch 78 + if len(formatPatch) >= 2 { 79 + diffTree, err := gr.DiffTree(commit1, commit2) 80 + if err != nil { 81 + x.Logger.Error("error comparing revisions", "msg", err.Error()) 82 + } else { 83 + combinedPatch = diffTree.Diff 84 + combinedPatchRaw = diffTree.Patch 85 + } 86 + } 87 + 74 88 response := types.RepoFormatPatchResponse{ 75 - Rev1: commit1.Hash.String(), 76 - Rev2: commit2.Hash.String(), 77 - FormatPatch: formatPatch, 78 - Patch: rawPatch, 89 + Rev1: commit1.Hash.String(), 90 + Rev2: commit2.Hash.String(), 91 + FormatPatch: formatPatch, 92 + FormatPatchRaw: rawPatch, 93 + CombinedPatch: combinedPatch, 94 + CombinedPatchRaw: combinedPatchRaw, 79 95 } 80 96 81 97 writeJson(w, response)
+7 -5
types/repo.go
··· 1 1 package types 2 2 3 3 import ( 4 + "github.com/bluekeyes/go-gitdiff/gitdiff" 4 5 "github.com/go-git/go-git/v5/plumbing/object" 5 6 ) 6 7 ··· 33 34 } 34 35 35 36 type RepoFormatPatchResponse struct { 36 - Rev1 string `json:"rev1,omitempty"` 37 - Rev2 string `json:"rev2,omitempty"` 38 - FormatPatch []FormatPatch `json:"format_patch,omitempty"` 39 - MergeBase string `json:"merge_base,omitempty"` // deprecated 40 - Patch string `json:"patch,omitempty"` 37 + Rev1 string `json:"rev1,omitempty"` 38 + Rev2 string `json:"rev2,omitempty"` 39 + FormatPatch []FormatPatch `json:"format_patch,omitempty"` 40 + FormatPatchRaw string `json:"patch,omitempty"` 41 + CombinedPatch []*gitdiff.File `json:"combined_patch,omitempty"` 42 + CombinedPatchRaw string `json:"combined_patch_raw,omitempty"` 41 43 } 42 44 43 45 type RepoTreeResponse struct {