this repo has no description
1package db
2
3import (
4 "database/sql"
5 "time"
6
7 "github.com/bluesky-social/indigo/atproto/syntax"
8)
9
10type PullState int
11
12const (
13 PullOpen PullState = iota
14 PullMerged
15 PullClosed
16)
17
18func (p PullState) String() string {
19 switch p {
20 case PullOpen:
21 return "open"
22 case PullMerged:
23 return "merged"
24 case PullClosed:
25 return "closed"
26 default:
27 return "closed"
28 }
29}
30
31func (p PullState) IsOpen() bool {
32 return p == PullOpen
33}
34func (p PullState) IsMerged() bool {
35 return p == PullMerged
36}
37func (p PullState) IsClosed() bool {
38 return p == PullClosed
39}
40
41type Pull struct {
42 ID int
43 OwnerDid string
44 RepoAt syntax.ATURI
45 PullAt syntax.ATURI
46 TargetBranch string
47 Patch string
48 PullId int
49 Title string
50 Body string
51 State PullState
52 Created time.Time
53 Rkey string
54}
55
56type PullComment struct {
57 ID int
58 OwnerDid string
59 PullId int
60 RepoAt string
61 CommentId int
62 CommentAt string
63 Body string
64 Created time.Time
65}
66
67func NewPull(tx *sql.Tx, pull *Pull) error {
68 defer tx.Rollback()
69
70 _, err := tx.Exec(`
71 insert or ignore into repo_pull_seqs (repo_at, next_pull_id)
72 values (?, 1)
73 `, pull.RepoAt)
74 if err != nil {
75 return err
76 }
77
78 var nextId int
79 err = tx.QueryRow(`
80 update repo_pull_seqs
81 set next_pull_id = next_pull_id + 1
82 where repo_at = ?
83 returning next_pull_id - 1
84 `, pull.RepoAt).Scan(&nextId)
85 if err != nil {
86 return err
87 }
88
89 pull.PullId = nextId
90
91 _, err = tx.Exec(`
92 insert into pulls (repo_at, owner_did, pull_id, title, target_branch, body, patch, rkey)
93 values (?, ?, ?, ?, ?, ?, ?, ?)
94 `, pull.RepoAt, pull.OwnerDid, pull.PullId, pull.Title, pull.TargetBranch, pull.Body, pull.Patch, pull.Rkey)
95 if err != nil {
96 return err
97 }
98
99 if err := tx.Commit(); err != nil {
100 return err
101 }
102
103 return nil
104}
105
106func SetPullAt(e Execer, repoAt syntax.ATURI, pullId int, pullAt string) error {
107 _, err := e.Exec(`update pulls set pull_at = ? where repo_at = ? and pull_id = ?`, pullAt, repoAt, pullId)
108 return err
109}
110
111func GetPullAt(e Execer, repoAt syntax.ATURI, pullId int) (string, error) {
112 var pullAt string
113 err := e.QueryRow(`select pull_at from pulls where repo_at = ? and pull_id = ?`, repoAt, pullId).Scan(&pullAt)
114 return pullAt, err
115}
116
117func NextPullId(e Execer, repoAt syntax.ATURI) (int, error) {
118 var pullId int
119 err := e.QueryRow(`select next_pull_id from repo_pull_seqs where repo_at = ?`, repoAt).Scan(&pullId)
120 return pullId - 1, err
121}
122
123func GetPulls(e Execer, repoAt syntax.ATURI, state PullState) ([]Pull, error) {
124 var pulls []Pull
125
126 rows, err := e.Query(`
127 select
128 owner_did,
129 pull_id,
130 created,
131 title,
132 state,
133 target_branch,
134 pull_at,
135 body,
136 patch,
137 rkey
138 from
139 pulls
140 where
141 repo_at = ? and state = ?
142 order by
143 created desc`, repoAt, state)
144 if err != nil {
145 return nil, err
146 }
147 defer rows.Close()
148
149 for rows.Next() {
150 var pull Pull
151 var createdAt string
152 err := rows.Scan(&pull.OwnerDid, &pull.PullId, &createdAt, &pull.Title, &pull.State, &pull.TargetBranch, &pull.PullAt, &pull.Body, &pull.Patch, &pull.Rkey)
153 if err != nil {
154 return nil, err
155 }
156
157 createdTime, err := time.Parse(time.RFC3339, createdAt)
158 if err != nil {
159 return nil, err
160 }
161 pull.Created = createdTime
162
163 pulls = append(pulls, pull)
164 }
165
166 if err := rows.Err(); err != nil {
167 return nil, err
168 }
169
170 return pulls, nil
171}
172
173func GetPull(e Execer, repoAt syntax.ATURI, pullId int) (*Pull, error) {
174 query := `select owner_did, created, title, state, target_branch, pull_at, body, patch, rkey from pulls where repo_at = ? and pull_id = ?`
175 row := e.QueryRow(query, repoAt, pullId)
176
177 var pull Pull
178 var createdAt string
179 err := row.Scan(&pull.OwnerDid, &createdAt, &pull.Title, &pull.State, &pull.TargetBranch, &pull.PullAt, &pull.Body, &pull.Patch, &pull.Rkey)
180 if err != nil {
181 return nil, err
182 }
183
184 createdTime, err := time.Parse(time.RFC3339, createdAt)
185 if err != nil {
186 return nil, err
187 }
188 pull.Created = createdTime
189
190 return &pull, nil
191}
192
193func GetPullWithComments(e Execer, repoAt syntax.ATURI, pullId int) (*Pull, []PullComment, error) {
194 query := `select owner_did, pull_id, created, title, state, target_branch, pull_at, body, patch, rkey from pulls where repo_at = ? and pull_id = ?`
195 row := e.QueryRow(query, repoAt, pullId)
196
197 var pull Pull
198 var createdAt string
199 err := row.Scan(&pull.OwnerDid, &pull.PullId, &createdAt, &pull.Title, &pull.State, &pull.TargetBranch, &pull.PullAt, &pull.Body, &pull.Patch, &pull.Rkey)
200 if err != nil {
201 return nil, nil, err
202 }
203
204 createdTime, err := time.Parse(time.RFC3339, createdAt)
205 if err != nil {
206 return nil, nil, err
207 }
208 pull.Created = createdTime
209
210 comments, err := GetPullComments(e, repoAt, pullId)
211 if err != nil {
212 return nil, nil, err
213 }
214
215 return &pull, comments, nil
216}
217
218func NewPullComment(e Execer, comment *PullComment) error {
219 query := `insert into pull_comments (owner_did, repo_at, comment_at, pull_id, comment_id, body) values (?, ?, ?, ?, ?, ?)`
220 _, err := e.Exec(
221 query,
222 comment.OwnerDid,
223 comment.RepoAt,
224 comment.CommentAt,
225 comment.PullId,
226 comment.CommentId,
227 comment.Body,
228 )
229 return err
230}
231
232func GetPullComments(e Execer, repoAt syntax.ATURI, pullId int) ([]PullComment, error) {
233 var comments []PullComment
234
235 rows, err := e.Query(`select owner_did, pull_id, comment_id, comment_at, body, created from pull_comments where repo_at = ? and pull_id = ? order by created asc`, repoAt, pullId)
236 if err == sql.ErrNoRows {
237 return []PullComment{}, nil
238 }
239 if err != nil {
240 return nil, err
241 }
242 defer rows.Close()
243
244 for rows.Next() {
245 var comment PullComment
246 var createdAt string
247 err := rows.Scan(&comment.OwnerDid, &comment.PullId, &comment.CommentId, &comment.CommentAt, &comment.Body, &createdAt)
248 if err != nil {
249 return nil, err
250 }
251
252 createdAtTime, err := time.Parse(time.RFC3339, createdAt)
253 if err != nil {
254 return nil, err
255 }
256 comment.Created = createdAtTime
257
258 comments = append(comments, comment)
259 }
260
261 if err := rows.Err(); err != nil {
262 return nil, err
263 }
264
265 return comments, nil
266}
267
268func SetPullState(e Execer, repoAt syntax.ATURI, pullId int, pullState PullState) error {
269 _, err := e.Exec(`update pulls set state = ? where repo_at = ? and pull_id = ?`, pullState, repoAt, pullId)
270 return err
271}
272
273func ClosePull(e Execer, repoAt syntax.ATURI, pullId int) error {
274 err := SetPullState(e, repoAt, pullId, PullClosed)
275 return err
276}
277
278func ReopenPull(e Execer, repoAt syntax.ATURI, pullId int) error {
279 err := SetPullState(e, repoAt, pullId, PullOpen)
280 return err
281}
282
283func MergePull(e Execer, repoAt syntax.ATURI, pullId int) error {
284 err := SetPullState(e, repoAt, pullId, PullMerged)
285 return err
286}
287
288type PullCount struct {
289 Open int
290 Merged int
291 Closed int
292}
293
294func GetPullCount(e Execer, repoAt syntax.ATURI) (PullCount, error) {
295 row := e.QueryRow(`
296 select
297 count(case when state = 0 then 1 end) as open_count,
298 count(case when state = 1 then 1 end) as merged_count,
299 count(case when state = 2 then 1 end) as closed_count
300 from pulls
301 where repo_at = ?`,
302 repoAt,
303 )
304
305 var count PullCount
306 if err := row.Scan(&count.Open, &count.Merged, &count.Closed); err != nil {
307 return PullCount{0, 0, 0}, err
308 }
309
310 return count, nil
311}
312
313func EditPatch(e Execer, repoAt syntax.ATURI, pullId int, patch string) error {
314 _, err := e.Exec(`update pulls set patch = ? where repo_at = ? and pull_id = ?`, patch, repoAt, pullId)
315 return err
316}