+202
-1
api/tangled/cbor_gen.go
+202
-1
api/tangled/cbor_gen.go
···
7420
7420
}
7421
7421
7422
7422
cw := cbg.NewCborWriter(w)
7423
-
fieldCount := 7
7423
+
fieldCount := 8
7424
7424
7425
7425
if t.Body == nil {
7426
7426
fieldCount--
7427
7427
}
7428
7428
7429
7429
if t.Source == nil {
7430
+
fieldCount--
7431
+
}
7432
+
7433
+
if t.StackInfo == nil {
7430
7434
fieldCount--
7431
7435
}
7432
7436
···
7588
7592
if _, err := cw.WriteString(string(t.CreatedAt)); err != nil {
7589
7593
return err
7590
7594
}
7595
+
7596
+
// t.StackInfo (tangled.RepoPull_StackInfo) (struct)
7597
+
if t.StackInfo != nil {
7598
+
7599
+
if len("stackInfo") > 1000000 {
7600
+
return xerrors.Errorf("Value in field \"stackInfo\" was too long")
7601
+
}
7602
+
7603
+
if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len("stackInfo"))); err != nil {
7604
+
return err
7605
+
}
7606
+
if _, err := cw.WriteString(string("stackInfo")); err != nil {
7607
+
return err
7608
+
}
7609
+
7610
+
if err := t.StackInfo.MarshalCBOR(cw); err != nil {
7611
+
return err
7612
+
}
7613
+
}
7591
7614
return nil
7592
7615
}
7593
7616
···
7737
7760
7738
7761
t.CreatedAt = string(sval)
7739
7762
}
7763
+
// t.StackInfo (tangled.RepoPull_StackInfo) (struct)
7764
+
case "stackInfo":
7765
+
7766
+
{
7767
+
7768
+
b, err := cr.ReadByte()
7769
+
if err != nil {
7770
+
return err
7771
+
}
7772
+
if b != cbg.CborNull[0] {
7773
+
if err := cr.UnreadByte(); err != nil {
7774
+
return err
7775
+
}
7776
+
t.StackInfo = new(RepoPull_StackInfo)
7777
+
if err := t.StackInfo.UnmarshalCBOR(cr); err != nil {
7778
+
return xerrors.Errorf("unmarshaling t.StackInfo pointer: %w", err)
7779
+
}
7780
+
}
7781
+
7782
+
}
7740
7783
7741
7784
default:
7742
7785
// Field doesn't exist on this type, so ignore it
···
7934
7977
}
7935
7978
7936
7979
t.CreatedAt = string(sval)
7980
+
}
7981
+
7982
+
default:
7983
+
// Field doesn't exist on this type, so ignore it
7984
+
if err := cbg.ScanForLinks(r, func(cid.Cid) {}); err != nil {
7985
+
return err
7986
+
}
7987
+
}
7988
+
}
7989
+
7990
+
return nil
7991
+
}
7992
+
func (t *RepoPull_StackInfo) MarshalCBOR(w io.Writer) error {
7993
+
if t == nil {
7994
+
_, err := w.Write(cbg.CborNull)
7995
+
return err
7996
+
}
7997
+
7998
+
cw := cbg.NewCborWriter(w)
7999
+
fieldCount := 2
8000
+
8001
+
if t.Parent == nil {
8002
+
fieldCount--
8003
+
}
8004
+
8005
+
if _, err := cw.Write(cbg.CborEncodeMajorType(cbg.MajMap, uint64(fieldCount))); err != nil {
8006
+
return err
8007
+
}
8008
+
8009
+
// t.Parent (string) (string)
8010
+
if t.Parent != nil {
8011
+
8012
+
if len("parent") > 1000000 {
8013
+
return xerrors.Errorf("Value in field \"parent\" was too long")
8014
+
}
8015
+
8016
+
if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len("parent"))); err != nil {
8017
+
return err
8018
+
}
8019
+
if _, err := cw.WriteString(string("parent")); err != nil {
8020
+
return err
8021
+
}
8022
+
8023
+
if t.Parent == nil {
8024
+
if _, err := cw.Write(cbg.CborNull); err != nil {
8025
+
return err
8026
+
}
8027
+
} else {
8028
+
if len(*t.Parent) > 1000000 {
8029
+
return xerrors.Errorf("Value in field t.Parent was too long")
8030
+
}
8031
+
8032
+
if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len(*t.Parent))); err != nil {
8033
+
return err
8034
+
}
8035
+
if _, err := cw.WriteString(string(*t.Parent)); err != nil {
8036
+
return err
8037
+
}
8038
+
}
8039
+
}
8040
+
8041
+
// t.ChangeId (string) (string)
8042
+
if len("changeId") > 1000000 {
8043
+
return xerrors.Errorf("Value in field \"changeId\" was too long")
8044
+
}
8045
+
8046
+
if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len("changeId"))); err != nil {
8047
+
return err
8048
+
}
8049
+
if _, err := cw.WriteString(string("changeId")); err != nil {
8050
+
return err
8051
+
}
8052
+
8053
+
if len(t.ChangeId) > 1000000 {
8054
+
return xerrors.Errorf("Value in field t.ChangeId was too long")
8055
+
}
8056
+
8057
+
if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len(t.ChangeId))); err != nil {
8058
+
return err
8059
+
}
8060
+
if _, err := cw.WriteString(string(t.ChangeId)); err != nil {
8061
+
return err
8062
+
}
8063
+
return nil
8064
+
}
8065
+
8066
+
func (t *RepoPull_StackInfo) UnmarshalCBOR(r io.Reader) (err error) {
8067
+
*t = RepoPull_StackInfo{}
8068
+
8069
+
cr := cbg.NewCborReader(r)
8070
+
8071
+
maj, extra, err := cr.ReadHeader()
8072
+
if err != nil {
8073
+
return err
8074
+
}
8075
+
defer func() {
8076
+
if err == io.EOF {
8077
+
err = io.ErrUnexpectedEOF
8078
+
}
8079
+
}()
8080
+
8081
+
if maj != cbg.MajMap {
8082
+
return fmt.Errorf("cbor input should be of type map")
8083
+
}
8084
+
8085
+
if extra > cbg.MaxLength {
8086
+
return fmt.Errorf("RepoPull_StackInfo: map struct too large (%d)", extra)
8087
+
}
8088
+
8089
+
n := extra
8090
+
8091
+
nameBuf := make([]byte, 8)
8092
+
for i := uint64(0); i < n; i++ {
8093
+
nameLen, ok, err := cbg.ReadFullStringIntoBuf(cr, nameBuf, 1000000)
8094
+
if err != nil {
8095
+
return err
8096
+
}
8097
+
8098
+
if !ok {
8099
+
// Field doesn't exist on this type, so ignore it
8100
+
if err := cbg.ScanForLinks(cr, func(cid.Cid) {}); err != nil {
8101
+
return err
8102
+
}
8103
+
continue
8104
+
}
8105
+
8106
+
switch string(nameBuf[:nameLen]) {
8107
+
// t.Parent (string) (string)
8108
+
case "parent":
8109
+
8110
+
{
8111
+
b, err := cr.ReadByte()
8112
+
if err != nil {
8113
+
return err
8114
+
}
8115
+
if b != cbg.CborNull[0] {
8116
+
if err := cr.UnreadByte(); err != nil {
8117
+
return err
8118
+
}
8119
+
8120
+
sval, err := cbg.ReadStringWithMax(cr, 1000000)
8121
+
if err != nil {
8122
+
return err
8123
+
}
8124
+
8125
+
t.Parent = (*string)(&sval)
8126
+
}
8127
+
}
8128
+
// t.ChangeId (string) (string)
8129
+
case "changeId":
8130
+
8131
+
{
8132
+
sval, err := cbg.ReadStringWithMax(cr, 1000000)
8133
+
if err != nil {
8134
+
return err
8135
+
}
8136
+
8137
+
t.ChangeId = string(sval)
7937
8138
}
7938
8139
7939
8140
default:
+16
-7
api/tangled/repopull.go
+16
-7
api/tangled/repopull.go
···
17
17
} //
18
18
// RECORDTYPE: RepoPull
19
19
type RepoPull struct {
20
-
LexiconTypeID string `json:"$type,const=sh.tangled.repo.pull" cborgen:"$type,const=sh.tangled.repo.pull"`
21
-
Body *string `json:"body,omitempty" cborgen:"body,omitempty"`
22
-
CreatedAt string `json:"createdAt" cborgen:"createdAt"`
23
-
Patch string `json:"patch" cborgen:"patch"`
24
-
Source *RepoPull_Source `json:"source,omitempty" cborgen:"source,omitempty"`
25
-
Target *RepoPull_Target `json:"target" cborgen:"target"`
26
-
Title string `json:"title" cborgen:"title"`
20
+
LexiconTypeID string `json:"$type,const=sh.tangled.repo.pull" cborgen:"$type,const=sh.tangled.repo.pull"`
21
+
Body *string `json:"body,omitempty" cborgen:"body,omitempty"`
22
+
CreatedAt string `json:"createdAt" cborgen:"createdAt"`
23
+
Patch string `json:"patch" cborgen:"patch"`
24
+
Source *RepoPull_Source `json:"source,omitempty" cborgen:"source,omitempty"`
25
+
StackInfo *RepoPull_StackInfo `json:"stackInfo,omitempty" cborgen:"stackInfo,omitempty"`
26
+
Target *RepoPull_Target `json:"target" cborgen:"target"`
27
+
Title string `json:"title" cborgen:"title"`
27
28
}
28
29
29
30
// RepoPull_Source is a "source" in the sh.tangled.repo.pull schema.
···
31
32
Branch string `json:"branch" cborgen:"branch"`
32
33
Repo *string `json:"repo,omitempty" cborgen:"repo,omitempty"`
33
34
Sha string `json:"sha" cborgen:"sha"`
35
+
}
36
+
37
+
// RepoPull_StackInfo is a "stackInfo" in the sh.tangled.repo.pull schema.
38
+
type RepoPull_StackInfo struct {
39
+
// changeId: Change ID of this commit/change.
40
+
ChangeId string `json:"changeId" cborgen:"changeId"`
41
+
// parent: AT-URI of the PR for the parent commit/change in the change stack.
42
+
Parent *string `json:"parent,omitempty" cborgen:"parent,omitempty"`
34
43
}
35
44
36
45
// RepoPull_Target is a "target" in the sh.tangled.repo.pull schema.
+7
appview/db/db.go
+7
appview/db/db.go
···
1094
1094
})
1095
1095
conn.ExecContext(ctx, "pragma foreign_keys = on;")
1096
1096
1097
+
runMigration(conn, "add-parent-at-for-stacks-to-pulls", func(tx *sql.Tx) error {
1098
+
_, err := tx.Exec(`
1099
+
alter table pulls add column parent_at text;
1100
+
`)
1101
+
return err
1102
+
})
1103
+
1097
1104
return &DB{db}, nil
1098
1105
}
1099
1106
+17
-4
appview/db/pulls.go
+17
-4
appview/db/pulls.go
···
47
47
}
48
48
}
49
49
50
-
var stackId, changeId, parentChangeId *string
50
+
var stackId, changeId, parentAt, parentChangeId *string
51
51
if pull.StackId != "" {
52
52
stackId = &pull.StackId
53
53
}
54
54
if pull.ChangeId != "" {
55
55
changeId = &pull.ChangeId
56
+
}
57
+
if pull.ParentAt != nil {
58
+
parentAt = (*string)(pull.ParentAt)
56
59
}
57
60
if pull.ParentChangeId != "" {
58
61
parentChangeId = &pull.ParentChangeId
···
61
64
result, err := tx.Exec(
62
65
`
63
66
insert into pulls (
64
-
repo_at, owner_did, pull_id, title, target_branch, body, rkey, state, source_branch, source_repo_at, stack_id, change_id, parent_change_id
67
+
repo_at, owner_did, pull_id, title, target_branch, body, rkey, state, source_branch, source_repo_at, stack_id, change_id, parent_at, parent_change_id
65
68
)
66
-
values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
69
+
values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
67
70
pull.RepoAt,
68
71
pull.OwnerDid,
69
72
pull.PullId,
···
76
79
sourceRepoAt,
77
80
stackId,
78
81
changeId,
82
+
parentAt,
79
83
parentChangeId,
80
84
)
81
85
if err != nil {
···
145
149
source_repo_at,
146
150
stack_id,
147
151
change_id,
152
+
parent_at,
148
153
parent_change_id
149
154
from
150
155
pulls
···
163
168
for rows.Next() {
164
169
var pull models.Pull
165
170
var createdAt string
166
-
var sourceBranch, sourceRepoAt, stackId, changeId, parentChangeId sql.NullString
171
+
var sourceBranch, sourceRepoAt, stackId, changeId, parentAt, parentChangeId sql.NullString
167
172
err := rows.Scan(
168
173
&pull.ID,
169
174
&pull.OwnerDid,
···
179
184
&sourceRepoAt,
180
185
&stackId,
181
186
&changeId,
187
+
&parentAt,
182
188
&parentChangeId,
183
189
)
184
190
if err != nil {
···
209
215
}
210
216
if changeId.Valid {
211
217
pull.ChangeId = changeId.String
218
+
}
219
+
if parentAt.Valid {
220
+
parentAtParsed, err := syntax.ParseATURI(parentAt.String)
221
+
if err != nil {
222
+
return nil, err
223
+
}
224
+
pull.ParentAt = &parentAtParsed
212
225
}
213
226
if parentChangeId.Valid {
214
227
pull.ParentChangeId = parentChangeId.String
+5
appview/models/pull.go
+5
appview/models/pull.go
···
70
70
// stacking
71
71
StackId string // nullable string
72
72
ChangeId string // nullable string
73
+
ParentAt *syntax.ATURI
73
74
ParentChangeId string // nullable string
74
75
75
76
// meta
···
99
100
},
100
101
Patch: p.LatestPatch(),
101
102
Source: source,
103
+
StackInfo: &tangled.RepoPull_StackInfo{
104
+
ChangeId: p.ChangeId,
105
+
Parent: (*string)(p.ParentAt),
106
+
},
102
107
}
103
108
return record
104
109
}
+24
-2
appview/pulls/pulls.go
+24
-2
appview/pulls/pulls.go
···
29
29
30
30
"github.com/bluekeyes/go-gitdiff/gitdiff"
31
31
comatproto "github.com/bluesky-social/indigo/api/atproto"
32
+
"github.com/bluesky-social/indigo/atproto/syntax"
32
33
lexutil "github.com/bluesky-social/indigo/lex/util"
33
34
indigoxrpc "github.com/bluesky-social/indigo/xrpc"
34
35
"github.com/go-chi/chi/v5"
···
1836
1837
newStack, err := newStack(f, user, targetBranch, patch, pull.PullSource, stackId)
1837
1838
if err != nil {
1838
1839
log.Println("failed to create resubmitted stack", err)
1839
-
s.pages.Notice(w, "pull-merge-error", "Failed to merge pull request. Try again later.")
1840
+
s.pages.Notice(w, "pull-resubmit-error", "Failed to merge pull request. Try again later.")
1840
1841
return
1841
1842
}
1842
1843
1843
1844
// find the diff between the stacks, first, map them by changeId
1845
+
1844
1846
origById := make(map[string]*models.Pull)
1845
1847
newById := make(map[string]*models.Pull)
1848
+
chIdToAtUri := make(map[string]*syntax.ATURI)
1849
+
1846
1850
for _, p := range origStack {
1847
1851
origById[p.ChangeId] = p
1852
+
1853
+
// build map from change id to existing at uris (ignore error as it shouldnt be possible here)
1854
+
pAtUri, _ := syntax.ParseATURI(fmt.Sprintf("at://%s/%s/%s", user.Did, tangled.RepoPullNSID, p.Rkey))
1855
+
chIdToAtUri[p.ChangeId] = &pAtUri
1848
1856
}
1849
1857
for _, p := range newStack {
1858
+
// if change id has already been given a PR use its at uri instead of the newly created (and thus incorrect)
1859
+
// one made by newStack
1860
+
if ppAt, ok := chIdToAtUri[p.ParentChangeId]; ok {
1861
+
p.ParentAt = ppAt
1862
+
}
1863
+
1850
1864
newById[p.ChangeId] = p
1851
1865
}
1852
1866
···
1894
1908
// we still need to update the hash in submission.Patch and submission.SourceRev
1895
1909
if patchutil.Equal(newFiles, origFiles) &&
1896
1910
origHeader.Title == newHeader.Title &&
1897
-
origHeader.Body == newHeader.Body {
1911
+
origHeader.Body == newHeader.Body &&
1912
+
op.ParentChangeId == np.ParentChangeId {
1898
1913
unchanged[op.ChangeId] = struct{}{}
1899
1914
} else {
1900
1915
updated[op.ChangeId] = struct{}{}
···
1978
1993
1979
1994
record := op.AsRecord()
1980
1995
record.Patch = submission.Patch
1996
+
record.StackInfo.Parent = (*string)(np.ParentAt)
1981
1997
1982
1998
writes = append(writes, &comatproto.RepoApplyWrites_Input_Writes_Elem{
1983
1999
RepoApplyWrites_Update: &comatproto.RepoApplyWrites_Update{
···
2343
2359
// the stack is identified by a UUID
2344
2360
var stack models.Stack
2345
2361
parentChangeId := ""
2362
+
var parentAt *syntax.ATURI = nil
2346
2363
for _, fp := range formatPatches {
2347
2364
// all patches must have a jj change-id
2348
2365
changeId, err := fp.ChangeId()
···
2373
2390
2374
2391
StackId: stackId,
2375
2392
ChangeId: changeId,
2393
+
ParentAt: parentAt,
2376
2394
ParentChangeId: parentChangeId,
2377
2395
}
2378
2396
2379
2397
stack = append(stack, &pull)
2380
2398
2381
2399
parentChangeId = changeId
2400
+
// this is a bit of an ugly way to create the ATURI but its the best we can do with the data flow here
2401
+
// (igore error as it shouldnt be possible here)
2402
+
parsedParentAt, _ := syntax.ParseATURI(fmt.Sprintf("at://%s/%s/%s", user.Did, tangled.RepoPullNSID, pull.Rkey));
2403
+
parentAt = &parsedParentAt
2382
2404
}
2383
2405
2384
2406
return stack, nil
+1
cmd/gen.go
+1
cmd/gen.go
+21
lexicons/pulls/pull.json
+21
lexicons/pulls/pull.json
···
29
29
"patch": {
30
30
"type": "string"
31
31
},
32
+
"stackInfo": {
33
+
"type": "ref",
34
+
"ref": "#stackInfo"
35
+
},
32
36
"source": {
33
37
"type": "ref",
34
38
"ref": "#source"
···
73
77
},
74
78
"repo": {
75
79
"type": "string",
80
+
"format": "at-uri"
81
+
}
82
+
}
83
+
},
84
+
"stackInfo": {
85
+
"type": "object",
86
+
"required": [
87
+
"changeId"
88
+
],
89
+
"properties": {
90
+
"changeId": {
91
+
"type": "string",
92
+
"description": "Change ID of this commit/change."
93
+
},
94
+
"parent": {
95
+
"type": "string",
96
+
"description": "AT-URI of the PR for the parent commit/change in the change stack.",
76
97
"format": "at-uri"
77
98
}
78
99
}