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}