+15
appview/db/pulls.go
+15
appview/db/pulls.go
···
10
10
11
11
"github.com/bluekeyes/go-gitdiff/gitdiff"
12
12
"github.com/bluesky-social/indigo/atproto/syntax"
13
+
"tangled.sh/tangled.sh/core/patchutil"
13
14
"tangled.sh/tangled.sh/core/types"
14
15
)
15
16
···
188
189
nd.Stat.FilesChanged = len(diffs)
189
190
190
191
return nd
192
+
}
193
+
194
+
func (s PullSubmission) IsFormatPatch() bool {
195
+
return patchutil.IsFormatPatch(s.Patch)
196
+
}
197
+
198
+
func (s PullSubmission) AsFormatPatch() []patchutil.FormatPatch {
199
+
patches, err := patchutil.ExtractPatches(s.Patch)
200
+
if err != nil {
201
+
log.Println("error extracting patches from submission:", err)
202
+
return []patchutil.FormatPatch{}
203
+
}
204
+
205
+
return patches
191
206
}
192
207
193
208
func NewPull(tx *sql.Tx, pull *Pull) error {
+29
-41
appview/state/pull.go
+29
-41
appview/state/pull.go
···
10
10
"net/http"
11
11
"net/url"
12
12
"strconv"
13
-
"strings"
14
13
"time"
15
14
16
15
"github.com/go-chi/chi/v5"
···
18
17
"tangled.sh/tangled.sh/core/appview/auth"
19
18
"tangled.sh/tangled.sh/core/appview/db"
20
19
"tangled.sh/tangled.sh/core/appview/pages"
20
+
"tangled.sh/tangled.sh/core/patchutil"
21
21
"tangled.sh/tangled.sh/core/types"
22
22
23
23
comatproto "github.com/bluesky-social/indigo/api/atproto"
···
254
254
255
255
latestSubmission := pull.Submissions[pull.LastRoundNumber()]
256
256
if latestSubmission.SourceRev != result.Branch.Hash {
257
+
fmt.Println(latestSubmission.SourceRev, result.Branch.Hash)
257
258
return pages.ShouldResubmit
258
259
}
259
260
···
635
636
return
636
637
}
637
638
638
-
diffTreeResponse, err := ksClient.Compare(f.OwnerDid(), f.RepoName, targetBranch, sourceBranch)
639
+
comparison, err := ksClient.Compare(f.OwnerDid(), f.RepoName, targetBranch, sourceBranch)
639
640
if err != nil {
640
641
log.Println("failed to compare", err)
641
642
s.pages.Notice(w, "pull", err.Error())
642
643
return
643
644
}
644
645
645
-
sourceRev := diffTreeResponse.DiffTree.Rev2
646
-
patch := diffTreeResponse.DiffTree.Patch
646
+
sourceRev := comparison.Rev2
647
+
patch := comparison.Patch
647
648
648
-
if !isPatchValid(patch) {
649
+
if !patchutil.IsPatchValid(patch) {
649
650
s.pages.Notice(w, "pull", "Invalid patch format. Please provide a valid diff.")
650
651
return
651
652
}
···
654
655
}
655
656
656
657
func (s *State) handlePatchBasedPull(w http.ResponseWriter, r *http.Request, f *FullyResolvedRepo, user *auth.User, title, body, targetBranch, patch string) {
657
-
if !isPatchValid(patch) {
658
+
if !patchutil.IsPatchValid(patch) {
658
659
s.pages.Notice(w, "pull", "Invalid patch format. Please provide a valid diff.")
659
660
return
660
661
}
···
714
715
// hiddenRef: hidden/feature-1/main (on repo-fork)
715
716
// targetBranch: main (on repo-1)
716
717
// sourceBranch: feature-1 (on repo-fork)
717
-
diffTreeResponse, err := us.Compare(user.Did, fork.Name, hiddenRef, sourceBranch)
718
+
comparison, err := us.Compare(user.Did, fork.Name, hiddenRef, sourceBranch)
718
719
if err != nil {
719
720
log.Println("failed to compare across branches", err)
720
721
s.pages.Notice(w, "pull", err.Error())
721
722
return
722
723
}
723
724
724
-
sourceRev := diffTreeResponse.DiffTree.Rev2
725
-
patch := diffTreeResponse.DiffTree.Patch
725
+
sourceRev := comparison.Rev2
726
+
patch := comparison.Patch
726
727
727
-
if !isPatchValid(patch) {
728
+
if patchutil.IsPatchValid(patch) {
728
729
s.pages.Notice(w, "pull", "Invalid patch format. Please provide a valid diff.")
729
730
return
730
731
}
···
742
743
}, &tangled.RepoPull_Source{Branch: sourceBranch, Repo: &fork.AtUri})
743
744
}
744
745
745
-
func (s *State) createPullRequest(w http.ResponseWriter, r *http.Request, f *FullyResolvedRepo, user *auth.User, title, body, targetBranch, patch, sourceRev string, pullSource *db.PullSource, recordPullSource *tangled.RepoPull_Source) {
746
+
func (s *State) createPullRequest(
747
+
w http.ResponseWriter,
748
+
r *http.Request,
749
+
f *FullyResolvedRepo,
750
+
user *auth.User,
751
+
title, body, targetBranch string,
752
+
patch string,
753
+
sourceRev string,
754
+
pullSource *db.PullSource,
755
+
recordPullSource *tangled.RepoPull_Source,
756
+
) {
746
757
tx, err := s.db.BeginTx(r.Context(), nil)
747
758
if err != nil {
748
759
log.Println("failed to start tx")
···
1112
1123
return
1113
1124
}
1114
1125
1115
-
diffTreeResponse, err := ksClient.Compare(f.OwnerDid(), f.RepoName, pull.TargetBranch, pull.PullSource.Branch)
1126
+
comparison, err := ksClient.Compare(f.OwnerDid(), f.RepoName, pull.TargetBranch, pull.PullSource.Branch)
1116
1127
if err != nil {
1117
1128
log.Printf("compare request failed: %s", err)
1118
1129
s.pages.Notice(w, "resubmit-error", err.Error())
1119
1130
return
1120
1131
}
1121
1132
1122
-
sourceRev := diffTreeResponse.DiffTree.Rev2
1123
-
patch := diffTreeResponse.DiffTree.Patch
1133
+
sourceRev := comparison.Rev2
1134
+
patch := comparison.Patch
1124
1135
1125
1136
if err = validateResubmittedPatch(pull, patch); err != nil {
1126
1137
s.pages.Notice(w, "resubmit-error", err.Error())
···
1249
1260
}
1250
1261
1251
1262
hiddenRef := url.QueryEscape(fmt.Sprintf("hidden/%s/%s", pull.PullSource.Branch, pull.TargetBranch))
1252
-
diffTreeResponse, err := ksClient.Compare(forkRepo.Did, forkRepo.Name, hiddenRef, pull.PullSource.Branch)
1263
+
comparison, err := ksClient.Compare(forkRepo.Did, forkRepo.Name, hiddenRef, pull.PullSource.Branch)
1253
1264
if err != nil {
1254
1265
log.Printf("failed to compare branches: %s", err)
1255
1266
s.pages.Notice(w, "resubmit-error", err.Error())
1256
1267
return
1257
1268
}
1258
1269
1259
-
sourceRev := diffTreeResponse.DiffTree.Rev2
1260
-
patch := diffTreeResponse.DiffTree.Patch
1270
+
sourceRev := comparison.Rev2
1271
+
patch := comparison.Patch
1261
1272
1262
1273
if err = validateResubmittedPatch(pull, patch); err != nil {
1263
1274
s.pages.Notice(w, "resubmit-error", err.Error())
···
1338
1349
return fmt.Errorf("Patch is identical to previous submission.")
1339
1350
}
1340
1351
1341
-
if !isPatchValid(patch) {
1352
+
if patchutil.IsPatchValid(patch) {
1342
1353
return fmt.Errorf("Invalid patch format. Please provide a valid diff.")
1343
1354
}
1344
1355
···
1516
1527
s.pages.HxLocation(w, fmt.Sprintf("/%s/pulls/%d", f.OwnerSlashRepo(), pull.PullId))
1517
1528
return
1518
1529
}
1519
-
1520
-
// Very basic validation to check if it looks like a diff/patch
1521
-
// A valid patch usually starts with diff or --- lines
1522
-
func isPatchValid(patch string) bool {
1523
-
// Basic validation to check if it looks like a diff/patch
1524
-
// A valid patch usually starts with diff or --- lines
1525
-
if len(patch) == 0 {
1526
-
return false
1527
-
}
1528
-
1529
-
lines := strings.Split(patch, "\n")
1530
-
if len(lines) < 2 {
1531
-
return false
1532
-
}
1533
-
1534
-
// Check for common patch format markers
1535
-
firstLine := strings.TrimSpace(lines[0])
1536
-
return strings.HasPrefix(firstLine, "diff ") ||
1537
-
strings.HasPrefix(firstLine, "--- ") ||
1538
-
strings.HasPrefix(firstLine, "Index: ") ||
1539
-
strings.HasPrefix(firstLine, "+++ ") ||
1540
-
strings.HasPrefix(firstLine, "@@ ")
1541
-
}
+6
-6
appview/state/signer.go
+6
-6
appview/state/signer.go
···
378
378
return &capabilities, nil
379
379
}
380
380
381
-
func (us *UnsignedClient) Compare(ownerDid, repoName, rev1, rev2 string) (*types.RepoDiffTreeResponse, error) {
381
+
func (us *UnsignedClient) Compare(ownerDid, repoName, rev1, rev2 string) (*types.RepoFormatPatchResponse, error) {
382
382
const (
383
383
Method = "GET"
384
384
)
···
409
409
}
410
410
defer compareResp.Body.Close()
411
411
412
-
var diffTreeResponse types.RepoDiffTreeResponse
413
-
err = json.Unmarshal(respBody, &diffTreeResponse)
412
+
var formatPatchResponse types.RepoFormatPatchResponse
413
+
err = json.Unmarshal(respBody, &formatPatchResponse)
414
414
if err != nil {
415
-
log.Println("failed to unmarshal diff tree response", err)
416
-
return nil, fmt.Errorf("Failed to compare branches.")
415
+
log.Println("failed to unmarshal format-patch response", err)
416
+
return nil, fmt.Errorf("failed to compare branches.")
417
417
}
418
418
419
-
return &diffTreeResponse, nil
419
+
return &formatPatchResponse, nil
420
420
}
+6
-2
types/repo.go
+6
-2
types/repo.go
···
2
2
3
3
import (
4
4
"github.com/go-git/go-git/v5/plumbing/object"
5
+
"tangled.sh/tangled.sh/core/patchutil"
5
6
)
6
7
7
8
type RepoIndexResponse struct {
···
32
33
Diff *NiceDiff `json:"diff,omitempty"`
33
34
}
34
35
35
-
type RepoDiffTreeResponse struct {
36
-
DiffTree *DiffTree `json:"difftree,omitempty"`
36
+
type RepoFormatPatchResponse struct {
37
+
Rev1 string `json:"rev1,omitempty"`
38
+
Rev2 string `json:"rev2,omitempty"`
39
+
FormatPatch []patchutil.FormatPatch `json:"format_patch,omitempty"`
40
+
Patch string `json:"patch,omitempty"`
37
41
}
38
42
39
43
type RepoTreeResponse struct {