+9
appview/db/db.go
+9
appview/db/db.go
···
1094
})
1095
conn.ExecContext(ctx, "pragma foreign_keys = on;")
1096
1097
+
// knots may report the combined patch for a comparison, we can store that on the appview side
1098
+
// (but not on the pds record), because calculating the combined patch requires a git index
1099
+
runMigration(conn, "add-combined-column-submissions", func(tx *sql.Tx) error {
1100
+
_, err := tx.Exec(`
1101
+
alter table pull_submissions add column combined text;
1102
+
`)
1103
+
return err
1104
+
})
1105
+
1106
return &DB{db}, nil
1107
}
1108
+21
-17
appview/db/pulls.go
+21
-17
appview/db/pulls.go
···
90
pull.ID = int(id)
91
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)
96
return err
97
}
98
···
313
pull_at,
314
round_number,
315
patch,
316
created,
317
source_rev
318
from
···
332
333
for rows.Next() {
334
var submission models.PullSubmission
335
-
var createdAt string
336
-
var sourceRev sql.NullString
337
err := rows.Scan(
338
&submission.ID,
339
&submission.PullAt,
340
&submission.RoundNumber,
341
&submission.Patch,
342
-
&createdAt,
343
-
&sourceRev,
344
)
345
if err != nil {
346
return nil, err
347
}
348
349
-
createdTime, err := time.Parse(time.RFC3339, createdAt)
350
-
if err != nil {
351
-
return nil, err
352
}
353
-
submission.Created = createdTime
354
355
-
if sourceRev.Valid {
356
-
submission.SourceRev = sourceRev.String
357
}
358
359
submissionMap[submission.ID] = &submission
···
590
return err
591
}
592
593
-
func ResubmitPull(e Execer, pull *models.Pull, newPatch, sourceRev string) error {
594
newRoundNumber := len(pull.Submissions)
595
_, err := e.Exec(`
596
-
insert into pull_submissions (pull_at, round_number, patch, source_rev)
597
-
values (?, ?, ?, ?)
598
-
`, pull.PullAt(), newRoundNumber, newPatch, sourceRev)
599
600
return err
601
}
···
90
pull.ID = int(id)
91
92
_, err = tx.Exec(`
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
return err
97
}
98
···
313
pull_at,
314
round_number,
315
patch,
316
+
combined,
317
created,
318
source_rev
319
from
···
333
334
for rows.Next() {
335
var submission models.PullSubmission
336
+
var submissionCreatedStr string
337
+
var submissionSourceRev, submissionCombined sql.NullString
338
err := rows.Scan(
339
&submission.ID,
340
&submission.PullAt,
341
&submission.RoundNumber,
342
&submission.Patch,
343
+
&submissionCombined,
344
+
&submissionCreatedStr,
345
+
&submissionSourceRev,
346
)
347
if err != nil {
348
return nil, err
349
}
350
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
357
}
358
359
+
if submissionCombined.Valid {
360
+
submission.Combined = submissionCombined.String
361
}
362
363
submissionMap[submission.ID] = &submission
···
594
return err
595
}
596
597
+
func ResubmitPull(e Execer, pull *models.Pull, newPatch, combined, sourceRev string) error {
598
newRoundNumber := len(pull.Submissions)
599
_, err := e.Exec(`
600
+
insert into pull_submissions (pull_at, round_number, patch, combined, source_rev)
601
+
values (?, ?, ?, ?, ?)
602
+
`, pull.PullAt(), newRoundNumber, newPatch, combined, sourceRev)
603
604
return err
605
}
+9
appview/models/pull.go
+9
appview/models/pull.go
···
134
// content
135
RoundNumber int
136
Patch string
137
+
Combined string
138
Comments []PullComment
139
SourceRev string // include the rev that was used to create this submission: only for branch/fork PRs
140
···
262
}
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
273
}
274
275
type Stack []*Pull
+23
-40
appview/pulls/pulls.go
+23
-40
appview/pulls/pulls.go
···
142
stack, _ := r.Context().Value("stack").(models.Stack)
143
abandonedPulls, _ := r.Context().Value("abandonedPulls").([]*models.Pull)
144
145
-
totalIdents := 1
146
-
for _, submission := range pull.Submissions {
147
-
totalIdents += len(submission.Comments)
148
-
}
149
-
150
-
identsToResolve := make([]string, totalIdents)
151
-
152
-
// populate idents
153
-
identsToResolve[0] = pull.OwnerDid
154
-
idx := 1
155
-
for _, submission := range pull.Submissions {
156
-
for _, comment := range submission.Comments {
157
-
identsToResolve[idx] = comment.OwnerDid
158
-
idx += 1
159
-
}
160
-
}
161
-
162
mergeCheckResponse := s.mergeCheck(r, f, pull, stack)
163
branchDeleteStatus := s.branchDeleteStatus(r, f, pull)
164
resubmitResult := pages.Unknown
···
456
return
457
}
458
459
-
patch := pull.Submissions[roundIdInt].Patch
460
diff := patchutil.AsNiceDiff(patch, pull.TargetBranch)
461
462
s.pages.RepoPullPatchPage(w, pages.RepoPullPatchParams{
···
507
return
508
}
509
510
-
currentPatch, err := patchutil.AsDiff(pull.Submissions[roundIdInt].Patch)
511
if err != nil {
512
log.Println("failed to interdiff; current patch malformed")
513
s.pages.Notice(w, fmt.Sprintf("interdiff-error-%d", roundIdInt), "Failed to calculate interdiff; current patch is invalid.")
514
return
515
}
516
517
-
previousPatch, err := patchutil.AsDiff(pull.Submissions[roundIdInt-1].Patch)
518
if err != nil {
519
log.Println("failed to interdiff; previous patch malformed")
520
s.pages.Notice(w, fmt.Sprintf("interdiff-error-%d", roundIdInt), "Failed to calculate interdiff; previous patch is invalid.")
···
716
717
createdAt := time.Now().Format(time.RFC3339)
718
719
-
pullAt, err := db.GetPullAt(s.db, f.RepoAt(), pull.PullId)
720
-
if err != nil {
721
-
log.Println("failed to get pull at", err)
722
-
s.pages.Notice(w, "pull-comment", "Failed to create comment.")
723
-
return
724
-
}
725
-
726
client, err := s.oauth.AuthorizedClient(r)
727
if err != nil {
728
log.Println("failed to get authorized client", err)
···
735
Rkey: tid.TID(),
736
Record: &lexutil.LexiconTypeDecoder{
737
Val: &tangled.RepoPullComment{
738
-
Pull: string(pullAt),
739
Body: body,
740
CreatedAt: createdAt,
741
},
···
983
}
984
985
sourceRev := comparison.Rev2
986
-
patch := comparison.Patch
987
988
if !patchutil.IsPatchValid(patch) {
989
s.pages.Notice(w, "pull", "Invalid patch format. Please provide a valid diff.")
···
998
Sha: comparison.Rev2,
999
}
1000
1001
-
s.createPullRequest(w, r, f, user, title, body, targetBranch, patch, sourceRev, pullSource, recordPullSource, isStacked)
1002
}
1003
1004
func (s *Pulls) handlePatchBasedPull(w http.ResponseWriter, r *http.Request, f *reporesolver.ResolvedRepo, user *oauth.User, title, body, targetBranch, patch string, isStacked bool) {
···
1007
return
1008
}
1009
1010
-
s.createPullRequest(w, r, f, user, title, body, targetBranch, patch, "", nil, nil, isStacked)
1011
}
1012
1013
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) {
···
1090
}
1091
1092
sourceRev := comparison.Rev2
1093
-
patch := comparison.Patch
1094
1095
if !patchutil.IsPatchValid(patch) {
1096
s.pages.Notice(w, "pull", "Invalid patch format. Please provide a valid diff.")
···
1110
Sha: sourceRev,
1111
}
1112
1113
-
s.createPullRequest(w, r, f, user, title, body, targetBranch, patch, sourceRev, pullSource, recordPullSource, isStacked)
1114
}
1115
1116
func (s *Pulls) createPullRequest(
···
1120
user *oauth.User,
1121
title, body, targetBranch string,
1122
patch string,
1123
sourceRev string,
1124
pullSource *models.PullSource,
1125
recordPullSource *tangled.RepoPull_Source,
···
1179
rkey := tid.TID()
1180
initialSubmission := models.PullSubmission{
1181
Patch: patch,
1182
SourceRev: sourceRev,
1183
}
1184
pull := &models.Pull{
···
1608
1609
patch := r.FormValue("patch")
1610
1611
-
s.resubmitPullHelper(w, r, f, user, pull, patch, "")
1612
}
1613
1614
func (s *Pulls) resubmitBranch(w http.ResponseWriter, r *http.Request) {
···
1669
}
1670
1671
sourceRev := comparison.Rev2
1672
-
patch := comparison.Patch
1673
1674
-
s.resubmitPullHelper(w, r, f, user, pull, patch, sourceRev)
1675
}
1676
1677
func (s *Pulls) resubmitFork(w http.ResponseWriter, r *http.Request) {
···
1764
comparison := forkComparison
1765
1766
sourceRev := comparison.Rev2
1767
-
patch := comparison.Patch
1768
1769
-
s.resubmitPullHelper(w, r, f, user, pull, patch, sourceRev)
1770
}
1771
1772
// validate a resubmission against a pull request
···
1793
user *oauth.User,
1794
pull *models.Pull,
1795
patch string,
1796
sourceRev string,
1797
) {
1798
if pull.IsStacked() {
···
1822
}
1823
defer tx.Rollback()
1824
1825
-
err = db.ResubmitPull(tx, pull, patch, sourceRev)
1826
if err != nil {
1827
log.Println("failed to create pull request", err)
1828
s.pages.Notice(w, "resubmit-error", "Failed to create pull request. Try again later.")
···
2038
submission := np.Submissions[np.LastRoundNumber()]
2039
2040
// resubmit the old pull
2041
-
err := db.ResubmitPull(tx, op, submission.Patch, submission.SourceRev)
2042
2043
if err != nil {
2044
log.Println("failed to update pull", err, op.PullId)
···
142
stack, _ := r.Context().Value("stack").(models.Stack)
143
abandonedPulls, _ := r.Context().Value("abandonedPulls").([]*models.Pull)
144
145
mergeCheckResponse := s.mergeCheck(r, f, pull, stack)
146
branchDeleteStatus := s.branchDeleteStatus(r, f, pull)
147
resubmitResult := pages.Unknown
···
439
return
440
}
441
442
+
patch := pull.Submissions[roundIdInt].CombinedPatch()
443
diff := patchutil.AsNiceDiff(patch, pull.TargetBranch)
444
445
s.pages.RepoPullPatchPage(w, pages.RepoPullPatchParams{
···
490
return
491
}
492
493
+
currentPatch, err := patchutil.AsDiff(pull.Submissions[roundIdInt].CombinedPatch())
494
if err != nil {
495
log.Println("failed to interdiff; current patch malformed")
496
s.pages.Notice(w, fmt.Sprintf("interdiff-error-%d", roundIdInt), "Failed to calculate interdiff; current patch is invalid.")
497
return
498
}
499
500
+
previousPatch, err := patchutil.AsDiff(pull.Submissions[roundIdInt-1].CombinedPatch())
501
if err != nil {
502
log.Println("failed to interdiff; previous patch malformed")
503
s.pages.Notice(w, fmt.Sprintf("interdiff-error-%d", roundIdInt), "Failed to calculate interdiff; previous patch is invalid.")
···
699
700
createdAt := time.Now().Format(time.RFC3339)
701
702
client, err := s.oauth.AuthorizedClient(r)
703
if err != nil {
704
log.Println("failed to get authorized client", err)
···
711
Rkey: tid.TID(),
712
Record: &lexutil.LexiconTypeDecoder{
713
Val: &tangled.RepoPullComment{
714
+
Pull: pull.PullAt().String(),
715
Body: body,
716
CreatedAt: createdAt,
717
},
···
959
}
960
961
sourceRev := comparison.Rev2
962
+
patch := comparison.FormatPatchRaw
963
+
combined := comparison.CombinedPatchRaw
964
965
if !patchutil.IsPatchValid(patch) {
966
s.pages.Notice(w, "pull", "Invalid patch format. Please provide a valid diff.")
···
975
Sha: comparison.Rev2,
976
}
977
978
+
s.createPullRequest(w, r, f, user, title, body, targetBranch, patch, combined, sourceRev, pullSource, recordPullSource, isStacked)
979
}
980
981
func (s *Pulls) handlePatchBasedPull(w http.ResponseWriter, r *http.Request, f *reporesolver.ResolvedRepo, user *oauth.User, title, body, targetBranch, patch string, isStacked bool) {
···
984
return
985
}
986
987
+
s.createPullRequest(w, r, f, user, title, body, targetBranch, patch, "", "", nil, nil, isStacked)
988
}
989
990
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) {
···
1067
}
1068
1069
sourceRev := comparison.Rev2
1070
+
patch := comparison.FormatPatchRaw
1071
+
combined := comparison.CombinedPatchRaw
1072
1073
if !patchutil.IsPatchValid(patch) {
1074
s.pages.Notice(w, "pull", "Invalid patch format. Please provide a valid diff.")
···
1088
Sha: sourceRev,
1089
}
1090
1091
+
s.createPullRequest(w, r, f, user, title, body, targetBranch, patch, combined, sourceRev, pullSource, recordPullSource, isStacked)
1092
}
1093
1094
func (s *Pulls) createPullRequest(
···
1098
user *oauth.User,
1099
title, body, targetBranch string,
1100
patch string,
1101
+
combined string,
1102
sourceRev string,
1103
pullSource *models.PullSource,
1104
recordPullSource *tangled.RepoPull_Source,
···
1158
rkey := tid.TID()
1159
initialSubmission := models.PullSubmission{
1160
Patch: patch,
1161
+
Combined: combined,
1162
SourceRev: sourceRev,
1163
}
1164
pull := &models.Pull{
···
1588
1589
patch := r.FormValue("patch")
1590
1591
+
s.resubmitPullHelper(w, r, f, user, pull, patch, "", "")
1592
}
1593
1594
func (s *Pulls) resubmitBranch(w http.ResponseWriter, r *http.Request) {
···
1649
}
1650
1651
sourceRev := comparison.Rev2
1652
+
patch := comparison.FormatPatchRaw
1653
+
combined := comparison.CombinedPatchRaw
1654
1655
+
s.resubmitPullHelper(w, r, f, user, pull, patch, combined, sourceRev)
1656
}
1657
1658
func (s *Pulls) resubmitFork(w http.ResponseWriter, r *http.Request) {
···
1745
comparison := forkComparison
1746
1747
sourceRev := comparison.Rev2
1748
+
patch := comparison.FormatPatchRaw
1749
+
combined := comparison.CombinedPatchRaw
1750
1751
+
s.resubmitPullHelper(w, r, f, user, pull, patch, combined, sourceRev)
1752
}
1753
1754
// validate a resubmission against a pull request
···
1775
user *oauth.User,
1776
pull *models.Pull,
1777
patch string,
1778
+
combined string,
1779
sourceRev string,
1780
) {
1781
if pull.IsStacked() {
···
1805
}
1806
defer tx.Rollback()
1807
1808
+
err = db.ResubmitPull(tx, pull, patch, combined, sourceRev)
1809
if err != nil {
1810
log.Println("failed to create pull request", err)
1811
s.pages.Notice(w, "resubmit-error", "Failed to create pull request. Try again later.")
···
2021
submission := np.Submissions[np.LastRoundNumber()]
2022
2023
// resubmit the old pull
2024
+
err := db.ResubmitPull(tx, op, submission.Patch, submission.Combined, submission.SourceRev)
2025
2026
if err != nil {
2027
log.Println("failed to update pull", err, op.PullId)
+6
-1
appview/repo/repo.go
+6
-1
appview/repo/repo.go
···
2527
return
2528
}
2529
2530
+
var diff types.NiceDiff
2531
+
if formatPatch.CombinedPatchRaw != "" {
2532
+
diff = patchutil.AsNiceDiff(formatPatch.CombinedPatchRaw, base)
2533
+
} else {
2534
+
diff = patchutil.AsNiceDiff(formatPatch.FormatPatchRaw, base)
2535
+
}
2536
2537
repoinfo := f.RepoInfo(user)
2538
+20
-4
knotserver/xrpc/repo_compare.go
+20
-4
knotserver/xrpc/repo_compare.go
···
4
"fmt"
5
"net/http"
6
7
"tangled.org/core/knotserver/git"
8
"tangled.org/core/types"
9
xrpcerr "tangled.org/core/xrpc/errors"
···
71
return
72
}
73
74
response := types.RepoFormatPatchResponse{
75
-
Rev1: commit1.Hash.String(),
76
-
Rev2: commit2.Hash.String(),
77
-
FormatPatch: formatPatch,
78
-
Patch: rawPatch,
79
}
80
81
writeJson(w, response)
···
4
"fmt"
5
"net/http"
6
7
+
"github.com/bluekeyes/go-gitdiff/gitdiff"
8
"tangled.org/core/knotserver/git"
9
"tangled.org/core/types"
10
xrpcerr "tangled.org/core/xrpc/errors"
···
72
return
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
+
88
response := types.RepoFormatPatchResponse{
89
+
Rev1: commit1.Hash.String(),
90
+
Rev2: commit2.Hash.String(),
91
+
FormatPatch: formatPatch,
92
+
FormatPatchRaw: rawPatch,
93
+
CombinedPatch: combinedPatch,
94
+
CombinedPatchRaw: combinedPatchRaw,
95
}
96
97
writeJson(w, response)
+7
-5
types/repo.go
+7
-5
types/repo.go
···
1
package types
2
3
import (
4
"github.com/go-git/go-git/v5/plumbing/object"
5
)
6
···
33
}
34
35
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"`
41
}
42
43
type RepoTreeResponse struct {
···
1
package types
2
3
import (
4
+
"github.com/bluekeyes/go-gitdiff/gitdiff"
5
"github.com/go-git/go-git/v5/plumbing/object"
6
)
7
···
34
}
35
36
type RepoFormatPatchResponse struct {
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"`
43
}
44
45
type RepoTreeResponse struct {