forked from tangled.org/core
Monorepo for Tangled — https://tangled.org
1package db 2 3import ( 4 "database/sql" 5 "time" 6 7 "github.com/bluesky-social/indigo/atproto/syntax" 8) 9 10type Pull struct { 11 ID int 12 OwnerDid string 13 RepoAt syntax.ATURI 14 PullAt syntax.ATURI 15 TargetBranch string 16 Patch string 17 PullId int 18 Title string 19 Body string 20 Open int 21 Created time.Time 22 Rkey string 23} 24 25type PullComment struct { 26 ID int 27 OwnerDid string 28 PullId int 29 RepoAt string 30 CommentId int 31 CommentAt string 32 Body string 33 Created time.Time 34} 35 36func NewPull(tx *sql.Tx, pull *Pull) error { 37 defer tx.Rollback() 38 39 _, err := tx.Exec(` 40 insert or ignore into repo_pull_seqs (repo_at, next_pull_id) 41 values (?, 1) 42 `, pull.RepoAt) 43 if err != nil { 44 return err 45 } 46 47 var nextId int 48 err = tx.QueryRow(` 49 update repo_pull_seqs 50 set next_pull_id = next_pull_id + 1 51 where repo_at = ? 52 returning next_pull_id - 1 53 `, pull.RepoAt).Scan(&nextId) 54 if err != nil { 55 return err 56 } 57 58 pull.PullId = nextId 59 60 _, err = tx.Exec(` 61 insert into pulls (repo_at, owner_did, pull_id, title, target_branch, body, patch, rkey) 62 values (?, ?, ?, ?, ?, ?, ?, ?) 63 `, pull.RepoAt, pull.OwnerDid, pull.PullId, pull.Title, pull.TargetBranch, pull.Body, pull.Patch, pull.Rkey) 64 if err != nil { 65 return err 66 } 67 68 if err := tx.Commit(); err != nil { 69 return err 70 } 71 72 return nil 73} 74 75func SetPullAt(e Execer, repoAt syntax.ATURI, pullId int, pullAt string) error { 76 _, err := e.Exec(`update pulls set pull_at = ? where repo_at = ? and pull_id = ?`, pullAt, repoAt, pullId) 77 return err 78} 79 80func GetPullAt(e Execer, repoAt syntax.ATURI, pullId int) (string, error) { 81 var pullAt string 82 err := e.QueryRow(`select pull_at from pulls where repo_at = ? and pull_id = ?`, repoAt, pullId).Scan(&pullAt) 83 return pullAt, err 84} 85 86func NextPullId(e Execer, repoAt syntax.ATURI) (int, error) { 87 var pullId int 88 err := e.QueryRow(`select next_pull_id from repo_pull_seqs where repo_at = ?`, repoAt).Scan(&pullId) 89 return pullId - 1, err 90} 91 92func GetPulls(e Execer, repoAt syntax.ATURI) ([]Pull, error) { 93 var pulls []Pull 94 95 rows, err := e.Query(`select owner_did, pull_id, created, title, open, target_branch, pull_at, body, patch, rkey from pulls where repo_at = ? order by created desc`, repoAt) 96 if err != nil { 97 return nil, err 98 } 99 defer rows.Close() 100 101 for rows.Next() { 102 var pull Pull 103 var createdAt string 104 err := rows.Scan(&pull.OwnerDid, &pull.PullId, &createdAt, &pull.Title, &pull.Open, &pull.TargetBranch, &pull.PullAt, &pull.Body, &pull.Patch, &pull.Rkey) 105 if err != nil { 106 return nil, err 107 } 108 109 createdTime, err := time.Parse(time.RFC3339, createdAt) 110 if err != nil { 111 return nil, err 112 } 113 pull.Created = createdTime 114 115 pulls = append(pulls, pull) 116 } 117 118 if err := rows.Err(); err != nil { 119 return nil, err 120 } 121 122 return pulls, nil 123} 124 125func GetPull(e Execer, repoAt syntax.ATURI, pullId int) (*Pull, error) { 126 query := `select owner_did, created, title, open, target_branch, pull_at, body, patch, rkey from pulls where repo_at = ? and pull_id = ?` 127 row := e.QueryRow(query, repoAt, pullId) 128 129 var pull Pull 130 var createdAt string 131 err := row.Scan(&pull.OwnerDid, &createdAt, &pull.Title, &pull.Open, &pull.TargetBranch, &pull.PullAt, &pull.Body, &pull.Patch, &pull.Rkey) 132 if err != nil { 133 return nil, err 134 } 135 136 createdTime, err := time.Parse(time.RFC3339, createdAt) 137 if err != nil { 138 return nil, err 139 } 140 pull.Created = createdTime 141 142 return &pull, nil 143} 144 145func GetPullWithComments(e Execer, repoAt syntax.ATURI, pullId int) (*Pull, []PullComment, error) { 146 query := `select owner_did, pull_id, created, title, open, target_branch, pull_at, body, patch, rkey from pulls where repo_at = ? and pull_id = ?` 147 row := e.QueryRow(query, repoAt, pullId) 148 149 var pull Pull 150 var createdAt string 151 err := row.Scan(&pull.OwnerDid, &pull.PullId, &createdAt, &pull.Title, &pull.Open, &pull.TargetBranch, &pull.PullAt, &pull.Body, &pull.Patch, &pull.Rkey) 152 if err != nil { 153 return nil, nil, err 154 } 155 156 createdTime, err := time.Parse(time.RFC3339, createdAt) 157 if err != nil { 158 return nil, nil, err 159 } 160 pull.Created = createdTime 161 162 comments, err := GetPullComments(e, repoAt, pullId) 163 if err != nil { 164 return nil, nil, err 165 } 166 167 return &pull, comments, nil 168} 169 170func NewPullComment(e Execer, comment *PullComment) error { 171 query := `insert into pull_comments (owner_did, repo_at, comment_at, pull_id, comment_id, body) values (?, ?, ?, ?, ?, ?)` 172 _, err := e.Exec( 173 query, 174 comment.OwnerDid, 175 comment.RepoAt, 176 comment.CommentAt, 177 comment.PullId, 178 comment.CommentId, 179 comment.Body, 180 ) 181 return err 182} 183 184func GetPullComments(e Execer, repoAt syntax.ATURI, pullId int) ([]PullComment, error) { 185 var comments []PullComment 186 187 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) 188 if err == sql.ErrNoRows { 189 return []PullComment{}, nil 190 } 191 if err != nil { 192 return nil, err 193 } 194 defer rows.Close() 195 196 for rows.Next() { 197 var comment PullComment 198 var createdAt string 199 err := rows.Scan(&comment.OwnerDid, &comment.PullId, &comment.CommentId, &comment.CommentAt, &comment.Body, &createdAt) 200 if err != nil { 201 return nil, err 202 } 203 204 createdAtTime, err := time.Parse(time.RFC3339, createdAt) 205 if err != nil { 206 return nil, err 207 } 208 comment.Created = createdAtTime 209 210 comments = append(comments, comment) 211 } 212 213 if err := rows.Err(); err != nil { 214 return nil, err 215 } 216 217 return comments, nil 218} 219 220func ClosePull(e Execer, repoAt syntax.ATURI, pullId int) error { 221 _, err := e.Exec(`update pulls set open = 0 where repo_at = ? and pull_id = ?`, repoAt, pullId) 222 return err 223} 224 225func ReopenPull(e Execer, repoAt syntax.ATURI, pullId int) error { 226 _, err := e.Exec(`update pulls set open = 1 where repo_at = ? and pull_id = ?`, repoAt, pullId) 227 return err 228} 229 230func MergePull(e Execer, repoAt syntax.ATURI, pullId int) error { 231 _, err := e.Exec(`update pulls set open = 2 where repo_at = ? and pull_id = ?`, repoAt, pullId) 232 return err 233} 234 235type PullCount struct { 236 Open int 237 Closed int 238} 239 240func GetPullCount(e Execer, repoAt syntax.ATURI) (PullCount, error) { 241 row := e.QueryRow(` 242 select 243 count(case when open = 1 then 1 end) as open_count, 244 count(case when open = 0 then 1 end) as closed_count 245 from pulls 246 where repo_at = ?`, 247 repoAt, 248 ) 249 250 var count PullCount 251 if err := row.Scan(&count.Open, &count.Closed); err != nil { 252 return PullCount{0, 0}, err 253 } 254 255 return count, nil 256}