forked from tangled.org/core
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 Repo struct { 11 Did string 12 Name string 13 Knot string 14 Rkey string 15 Created time.Time 16 AtUri string 17 Description string 18 19 // optionally, populate this when querying for reverse mappings 20 RepoStats *RepoStats 21 22 // optional 23 Source string 24} 25 26func GetAllRepos(e Execer, limit int) ([]Repo, error) { 27 var repos []Repo 28 29 rows, err := e.Query( 30 `select did, name, knot, rkey, description, created, source 31 from repos 32 order by created desc 33 limit ? 34 `, 35 limit, 36 ) 37 if err != nil { 38 return nil, err 39 } 40 defer rows.Close() 41 42 for rows.Next() { 43 var repo Repo 44 err := scanRepo( 45 rows, &repo.Did, &repo.Name, &repo.Knot, &repo.Rkey, &repo.Description, &repo.Created, &repo.Source, 46 ) 47 if err != nil { 48 return nil, err 49 } 50 repos = append(repos, repo) 51 } 52 53 if err := rows.Err(); err != nil { 54 return nil, err 55 } 56 57 return repos, nil 58} 59 60func GetAllReposByDid(e Execer, did string) ([]Repo, error) { 61 var repos []Repo 62 63 rows, err := e.Query( 64 `select 65 r.did, 66 r.name, 67 r.knot, 68 r.rkey, 69 r.description, 70 r.created, 71 count(s.id) as star_count, 72 r.source 73 from 74 repos r 75 left join 76 stars s on r.at_uri = s.repo_at 77 where 78 r.did = ? 79 group by 80 r.at_uri`, did) 81 if err != nil { 82 return nil, err 83 } 84 defer rows.Close() 85 86 for rows.Next() { 87 var repo Repo 88 var repoStats RepoStats 89 var createdAt string 90 var nullableDescription sql.NullString 91 var nullableSource sql.NullString 92 93 err := rows.Scan(&repo.Did, &repo.Name, &repo.Knot, &repo.Rkey, &nullableDescription, &createdAt, &repoStats.StarCount, &nullableSource) 94 if err != nil { 95 return nil, err 96 } 97 98 if nullableDescription.Valid { 99 repo.Description = nullableDescription.String 100 } 101 102 if nullableSource.Valid { 103 repo.Source = nullableSource.String 104 } 105 106 createdAtTime, err := time.Parse(time.RFC3339, createdAt) 107 if err != nil { 108 repo.Created = time.Now() 109 } else { 110 repo.Created = createdAtTime 111 } 112 113 repo.RepoStats = &repoStats 114 115 repos = append(repos, repo) 116 } 117 118 if err := rows.Err(); err != nil { 119 return nil, err 120 } 121 122 return repos, nil 123} 124 125func GetRepo(e Execer, did, name string) (*Repo, error) { 126 var repo Repo 127 var nullableDescription sql.NullString 128 129 row := e.QueryRow(`select did, name, knot, created, at_uri, description from repos where did = ? and name = ?`, did, name) 130 131 var createdAt string 132 if err := row.Scan(&repo.Did, &repo.Name, &repo.Knot, &createdAt, &repo.AtUri, &nullableDescription); err != nil { 133 return nil, err 134 } 135 createdAtTime, _ := time.Parse(time.RFC3339, createdAt) 136 repo.Created = createdAtTime 137 138 if nullableDescription.Valid { 139 repo.Description = nullableDescription.String 140 } else { 141 repo.Description = "" 142 } 143 144 return &repo, nil 145} 146 147func GetRepoByAtUri(e Execer, atUri string) (*Repo, error) { 148 var repo Repo 149 var nullableDescription sql.NullString 150 151 row := e.QueryRow(`select did, name, knot, created, at_uri, description from repos where at_uri = ?`, atUri) 152 153 var createdAt string 154 if err := row.Scan(&repo.Did, &repo.Name, &repo.Knot, &createdAt, &repo.AtUri, &nullableDescription); err != nil { 155 return nil, err 156 } 157 createdAtTime, _ := time.Parse(time.RFC3339, createdAt) 158 repo.Created = createdAtTime 159 160 if nullableDescription.Valid { 161 repo.Description = nullableDescription.String 162 } else { 163 repo.Description = "" 164 } 165 166 return &repo, nil 167} 168 169func AddRepo(e Execer, repo *Repo) error { 170 _, err := e.Exec( 171 `insert into repos 172 (did, name, knot, rkey, at_uri, description, source) 173 values (?, ?, ?, ?, ?, ?, ?)`, 174 repo.Did, repo.Name, repo.Knot, repo.Rkey, repo.AtUri, repo.Description, repo.Source, 175 ) 176 return err 177} 178 179func RemoveRepo(e Execer, did, name, rkey string) error { 180 _, err := e.Exec(`delete from repos where did = ? and name = ? and rkey = ?`, did, name, rkey) 181 return err 182} 183 184func GetRepoSource(e Execer, repoAt syntax.ATURI) (string, error) { 185 var nullableSource sql.NullString 186 err := e.QueryRow(`select source from repos where at_uri = ?`, repoAt).Scan(&nullableSource) 187 if err != nil { 188 return "", err 189 } 190 return nullableSource.String, nil 191} 192 193func GetForksByDid(e Execer, did string) ([]Repo, error) { 194 var repos []Repo 195 196 rows, err := e.Query( 197 `select did, name, knot, rkey, description, created, at_uri, source 198 from repos 199 where did = ? and source is not null and source != '' 200 order by created desc`, 201 did, 202 ) 203 if err != nil { 204 return nil, err 205 } 206 defer rows.Close() 207 208 for rows.Next() { 209 var repo Repo 210 var createdAt string 211 var nullableDescription sql.NullString 212 var nullableSource sql.NullString 213 214 err := rows.Scan(&repo.Did, &repo.Name, &repo.Knot, &repo.Rkey, &nullableDescription, &createdAt, &repo.AtUri, &nullableSource) 215 if err != nil { 216 return nil, err 217 } 218 219 if nullableDescription.Valid { 220 repo.Description = nullableDescription.String 221 } 222 223 if nullableSource.Valid { 224 repo.Source = nullableSource.String 225 } 226 227 createdAtTime, err := time.Parse(time.RFC3339, createdAt) 228 if err != nil { 229 repo.Created = time.Now() 230 } else { 231 repo.Created = createdAtTime 232 } 233 234 repos = append(repos, repo) 235 } 236 237 if err := rows.Err(); err != nil { 238 return nil, err 239 } 240 241 return repos, nil 242} 243 244func GetForkByDid(e Execer, did string, name string) (*Repo, error) { 245 var repo Repo 246 var createdAt string 247 var nullableDescription sql.NullString 248 var nullableSource sql.NullString 249 250 row := e.QueryRow( 251 `select did, name, knot, rkey, description, created, at_uri, source 252 from repos 253 where did = ? and name = ? and source is not null and source != ''`, 254 did, name, 255 ) 256 257 err := row.Scan(&repo.Did, &repo.Name, &repo.Knot, &repo.Rkey, &nullableDescription, &createdAt, &repo.AtUri, &nullableSource) 258 if err != nil { 259 return nil, err 260 } 261 262 if nullableDescription.Valid { 263 repo.Description = nullableDescription.String 264 } 265 266 if nullableSource.Valid { 267 repo.Source = nullableSource.String 268 } 269 270 createdAtTime, err := time.Parse(time.RFC3339, createdAt) 271 if err != nil { 272 repo.Created = time.Now() 273 } else { 274 repo.Created = createdAtTime 275 } 276 277 return &repo, nil 278} 279 280func AddCollaborator(e Execer, collaborator, repoOwnerDid, repoName, repoKnot string) error { 281 _, err := e.Exec( 282 `insert into collaborators (did, repo) 283 values (?, (select id from repos where did = ? and name = ? and knot = ?));`, 284 collaborator, repoOwnerDid, repoName, repoKnot) 285 return err 286} 287 288func UpdateDescription(e Execer, repoAt, newDescription string) error { 289 _, err := e.Exec( 290 `update repos set description = ? where at_uri = ?`, newDescription, repoAt) 291 return err 292} 293 294func CollaboratingIn(e Execer, collaborator string) ([]Repo, error) { 295 var repos []Repo 296 297 rows, err := e.Query( 298 `select 299 r.did, r.name, r.knot, r.rkey, r.description, r.created, count(s.id) as star_count 300 from 301 repos r 302 join 303 collaborators c on r.id = c.repo 304 left join 305 stars s on r.at_uri = s.repo_at 306 where 307 c.did = ? 308 group by 309 r.id;`, collaborator) 310 if err != nil { 311 return nil, err 312 } 313 defer rows.Close() 314 315 for rows.Next() { 316 var repo Repo 317 var repoStats RepoStats 318 var createdAt string 319 var nullableDescription sql.NullString 320 321 err := rows.Scan(&repo.Did, &repo.Name, &repo.Knot, &repo.Rkey, &nullableDescription, &createdAt, &repoStats.StarCount) 322 if err != nil { 323 return nil, err 324 } 325 326 if nullableDescription.Valid { 327 repo.Description = nullableDescription.String 328 } else { 329 repo.Description = "" 330 } 331 332 createdAtTime, err := time.Parse(time.RFC3339, createdAt) 333 if err != nil { 334 repo.Created = time.Now() 335 } else { 336 repo.Created = createdAtTime 337 } 338 339 repo.RepoStats = &repoStats 340 341 repos = append(repos, repo) 342 } 343 344 if err := rows.Err(); err != nil { 345 return nil, err 346 } 347 348 return repos, nil 349} 350 351type RepoStats struct { 352 StarCount int 353 IssueCount IssueCount 354 PullCount PullCount 355} 356 357func scanRepo(rows *sql.Rows, did, name, knot, rkey, description *string, created *time.Time, source *string) error { 358 var createdAt string 359 var nullableDescription sql.NullString 360 var nullableSource sql.NullString 361 if err := rows.Scan(did, name, knot, rkey, &nullableDescription, &createdAt, &nullableSource); err != nil { 362 return err 363 } 364 365 if nullableDescription.Valid { 366 *description = nullableDescription.String 367 } else { 368 *description = "" 369 } 370 371 createdAtTime, err := time.Parse(time.RFC3339, createdAt) 372 if err != nil { 373 *created = time.Now() 374 } else { 375 *created = createdAtTime 376 } 377 378 if nullableSource.Valid { 379 *source = nullableSource.String 380 } else { 381 *source = "" 382 } 383 384 return nil 385}