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
92 err := rows.Scan(&repo.Did, &repo.Name, &repo.Knot, &repo.Rkey, &nullableDescription, &createdAt, &repoStats.StarCount)
93 if err != nil {
94 return nil, err
95 }
96
97 if nullableDescription.Valid {
98 repo.Description = nullableDescription.String
99 } else {
100 repo.Description = ""
101 }
102
103 createdAtTime, err := time.Parse(time.RFC3339, createdAt)
104 if err != nil {
105 repo.Created = time.Now()
106 } else {
107 repo.Created = createdAtTime
108 }
109
110 repo.RepoStats = &repoStats
111
112 repos = append(repos, repo)
113 }
114
115 if err := rows.Err(); err != nil {
116 return nil, err
117 }
118
119 return repos, nil
120}
121
122func GetRepo(e Execer, did, name string) (*Repo, error) {
123 var repo Repo
124 var nullableDescription sql.NullString
125
126 row := e.QueryRow(`select did, name, knot, created, at_uri, description from repos where did = ? and name = ?`, did, name)
127
128 var createdAt string
129 if err := row.Scan(&repo.Did, &repo.Name, &repo.Knot, &createdAt, &repo.AtUri, &nullableDescription); err != nil {
130 return nil, err
131 }
132 createdAtTime, _ := time.Parse(time.RFC3339, createdAt)
133 repo.Created = createdAtTime
134
135 if nullableDescription.Valid {
136 repo.Description = nullableDescription.String
137 } else {
138 repo.Description = ""
139 }
140
141 return &repo, nil
142}
143
144func GetRepoByAtUri(e Execer, atUri string) (*Repo, error) {
145 var repo Repo
146 var nullableDescription sql.NullString
147
148 row := e.QueryRow(`select did, name, knot, created, at_uri, description from repos where at_uri = ?`, atUri)
149
150 var createdAt string
151 if err := row.Scan(&repo.Did, &repo.Name, &repo.Knot, &createdAt, &repo.AtUri, &nullableDescription); err != nil {
152 return nil, err
153 }
154 createdAtTime, _ := time.Parse(time.RFC3339, createdAt)
155 repo.Created = createdAtTime
156
157 if nullableDescription.Valid {
158 repo.Description = nullableDescription.String
159 } else {
160 repo.Description = ""
161 }
162
163 return &repo, nil
164}
165
166func AddRepo(e Execer, repo *Repo) error {
167 _, err := e.Exec(
168 `insert into repos
169 (did, name, knot, rkey, at_uri, description, source)
170 values (?, ?, ?, ?, ?, ?, ?)`,
171 repo.Did, repo.Name, repo.Knot, repo.Rkey, repo.AtUri, repo.Description, repo.Source,
172 )
173 return err
174}
175
176func RemoveRepo(e Execer, did, name, rkey string) error {
177 _, err := e.Exec(`delete from repos where did = ? and name = ? and rkey = ?`, did, name, rkey)
178 return err
179}
180
181func GetRepoSource(e Execer, repoAt syntax.ATURI) (string, error) {
182 var source string
183 err := e.QueryRow(`select source from repos where at_uri = ?`, repoAt).Scan(&source)
184 if err != nil {
185 return "", err
186 }
187 return source, nil
188}
189
190func AddCollaborator(e Execer, collaborator, repoOwnerDid, repoName, repoKnot string) error {
191 _, err := e.Exec(
192 `insert into collaborators (did, repo)
193 values (?, (select id from repos where did = ? and name = ? and knot = ?));`,
194 collaborator, repoOwnerDid, repoName, repoKnot)
195 return err
196}
197
198func UpdateDescription(e Execer, repoAt, newDescription string) error {
199 _, err := e.Exec(
200 `update repos set description = ? where at_uri = ?`, newDescription, repoAt)
201 return err
202}
203
204func CollaboratingIn(e Execer, collaborator string) ([]Repo, error) {
205 var repos []Repo
206
207 rows, err := e.Query(
208 `select
209 r.did, r.name, r.knot, r.rkey, r.description, r.created, count(s.id) as star_count
210 from
211 repos r
212 join
213 collaborators c on r.id = c.repo
214 left join
215 stars s on r.at_uri = s.repo_at
216 where
217 c.did = ?
218 group by
219 r.id;`, collaborator)
220 if err != nil {
221 return nil, err
222 }
223 defer rows.Close()
224
225 for rows.Next() {
226 var repo Repo
227 var repoStats RepoStats
228 var createdAt string
229 var nullableDescription sql.NullString
230
231 err := rows.Scan(&repo.Did, &repo.Name, &repo.Knot, &repo.Rkey, &nullableDescription, &createdAt, &repoStats.StarCount)
232 if err != nil {
233 return nil, err
234 }
235
236 if nullableDescription.Valid {
237 repo.Description = nullableDescription.String
238 } else {
239 repo.Description = ""
240 }
241
242 createdAtTime, err := time.Parse(time.RFC3339, createdAt)
243 if err != nil {
244 repo.Created = time.Now()
245 } else {
246 repo.Created = createdAtTime
247 }
248
249 repo.RepoStats = &repoStats
250
251 repos = append(repos, repo)
252 }
253
254 if err := rows.Err(); err != nil {
255 return nil, err
256 }
257
258 return repos, nil
259}
260
261type RepoStats struct {
262 StarCount int
263 IssueCount IssueCount
264 PullCount PullCount
265}
266
267func scanRepo(rows *sql.Rows, did, name, knot, rkey, description *string, created *time.Time, source *string) error {
268 var createdAt string
269 var nullableDescription sql.NullString
270 var nullableSource sql.NullString
271 if err := rows.Scan(did, name, knot, rkey, &nullableDescription, &createdAt, &nullableSource); err != nil {
272 return err
273 }
274
275 if nullableDescription.Valid {
276 *description = nullableDescription.String
277 } else {
278 *description = ""
279 }
280
281 createdAtTime, err := time.Parse(time.RFC3339, createdAt)
282 if err != nil {
283 *created = time.Now()
284 } else {
285 *created = createdAtTime
286 }
287
288 if nullableSource.Valid {
289 *source = nullableSource.String
290 } else {
291 *source = ""
292 }
293
294 return nil
295}