Go · 15571 bytes Raw Blame History
1 // Code generated by sqlc. DO NOT EDIT.
2 // versions:
3 // sqlc v1.31.1
4 // source: lifecycle.sql
5
6 package reposdb
7
8 import (
9 "context"
10
11 "github.com/jackc/pgx/v5/pgtype"
12 )
13
14 const acceptTransferRequest = `-- name: AcceptTransferRequest :exec
15 UPDATE repo_transfer_requests
16 SET status = 'accepted', accepted_at = now()
17 WHERE id = $1 AND status = 'pending'
18 `
19
20 func (q *Queries) AcceptTransferRequest(ctx context.Context, db DBTX, id int64) error {
21 _, err := db.Exec(ctx, acceptTransferRequest, id)
22 return err
23 }
24
25 const archiveRepo = `-- name: ArchiveRepo :exec
26 UPDATE repos SET is_archived = true, archived_at = now(), updated_at = now() WHERE id = $1
27 `
28
29 func (q *Queries) ArchiveRepo(ctx context.Context, db DBTX, id int64) error {
30 _, err := db.Exec(ctx, archiveRepo, id)
31 return err
32 }
33
34 const cancelTransferRequest = `-- name: CancelTransferRequest :exec
35 UPDATE repo_transfer_requests
36 SET status = 'canceled', canceled_at = now()
37 WHERE id = $1 AND status = 'pending'
38 `
39
40 func (q *Queries) CancelTransferRequest(ctx context.Context, db DBTX, id int64) error {
41 _, err := db.Exec(ctx, cancelTransferRequest, id)
42 return err
43 }
44
45 const countRecentRedirectsForRepo = `-- name: CountRecentRedirectsForRepo :one
46
47 SELECT count(*)::int AS recent_count
48 FROM repo_redirects
49 WHERE repo_id = $1 AND redirected_at > now() - interval '30 days'
50 `
51
52 // ─── rename rate limit support ─────────────────────────────────────────
53 // Used to enforce the 5-per-30-days rename rate limit. The redirect
54 // row is the audit trail for renames; counting them per repo gives a
55 // reliable cap.
56 func (q *Queries) CountRecentRedirectsForRepo(ctx context.Context, db DBTX, repoID int64) (int32, error) {
57 row := db.QueryRow(ctx, countRecentRedirectsForRepo, repoID)
58 var recent_count int32
59 err := row.Scan(&recent_count)
60 return recent_count, err
61 }
62
63 const declineTransferRequest = `-- name: DeclineTransferRequest :exec
64 UPDATE repo_transfer_requests
65 SET status = 'declined', declined_at = now()
66 WHERE id = $1 AND status = 'pending'
67 `
68
69 func (q *Queries) DeclineTransferRequest(ctx context.Context, db DBTX, id int64) error {
70 _, err := db.Exec(ctx, declineTransferRequest, id)
71 return err
72 }
73
74 const deleteRedirectByUserOwnerOldName = `-- name: DeleteRedirectByUserOwnerOldName :exec
75 DELETE FROM repo_redirects
76 WHERE repo_id = $1 AND old_owner_user_id = $2 AND old_name = $3
77 `
78
79 type DeleteRedirectByUserOwnerOldNameParams struct {
80 RepoID int64
81 OldOwnerUserID pgtype.Int8
82 OldName string
83 }
84
85 // Used by the rename compensator: drop a single redirect row when
86 // the rename has to be rolled back due to a filesystem failure. We
87 // avoided raw SQL here at the audit's request (S00-S25, M).
88 func (q *Queries) DeleteRedirectByUserOwnerOldName(ctx context.Context, db DBTX, arg DeleteRedirectByUserOwnerOldNameParams) error {
89 _, err := db.Exec(ctx, deleteRedirectByUserOwnerOldName, arg.RepoID, arg.OldOwnerUserID, arg.OldName)
90 return err
91 }
92
93 const deleteRedirectsForRepo = `-- name: DeleteRedirectsForRepo :exec
94 DELETE FROM repo_redirects WHERE repo_id = $1
95 `
96
97 // Used by hard-delete: drop the redirect rows pointing at this repo
98 // (they would dangle once the repos row is gone; the FK ON DELETE
99 // CASCADE would handle it, but explicit is auditable).
100 func (q *Queries) DeleteRedirectsForRepo(ctx context.Context, db DBTX, repoID int64) error {
101 _, err := db.Exec(ctx, deleteRedirectsForRepo, repoID)
102 return err
103 }
104
105 const expirePendingTransfers = `-- name: ExpirePendingTransfers :execrows
106 UPDATE repo_transfer_requests
107 SET status = 'expired'
108 WHERE status = 'pending' AND expires_at < now()
109 `
110
111 // Called by the periodic worker (transfers:expire) — flips pending
112 // offers past their expires_at to the expired terminal state.
113 func (q *Queries) ExpirePendingTransfers(ctx context.Context, db DBTX) (int64, error) {
114 result, err := db.Exec(ctx, expirePendingTransfers)
115 if err != nil {
116 return 0, err
117 }
118 return result.RowsAffected(), nil
119 }
120
121 const getTransferRequest = `-- name: GetTransferRequest :one
122 SELECT id, repo_id, from_user_id, to_principal_kind, to_principal_id,
123 created_by, created_at, expires_at, status,
124 accepted_at, declined_at, canceled_at
125 FROM repo_transfer_requests
126 WHERE id = $1
127 `
128
129 func (q *Queries) GetTransferRequest(ctx context.Context, db DBTX, id int64) (RepoTransferRequest, error) {
130 row := db.QueryRow(ctx, getTransferRequest, id)
131 var i RepoTransferRequest
132 err := row.Scan(
133 &i.ID,
134 &i.RepoID,
135 &i.FromUserID,
136 &i.ToPrincipalKind,
137 &i.ToPrincipalID,
138 &i.CreatedBy,
139 &i.CreatedAt,
140 &i.ExpiresAt,
141 &i.Status,
142 &i.AcceptedAt,
143 &i.DeclinedAt,
144 &i.CanceledAt,
145 )
146 return i, err
147 }
148
149 const hardDeleteRepo = `-- name: HardDeleteRepo :exec
150 DELETE FROM repos WHERE id = $1
151 `
152
153 func (q *Queries) HardDeleteRepo(ctx context.Context, db DBTX, id int64) error {
154 _, err := db.Exec(ctx, hardDeleteRepo, id)
155 return err
156 }
157
158 const insertRepoRedirect = `-- name: InsertRepoRedirect :exec
159
160 INSERT INTO repo_redirects (old_owner_user_id, old_owner_org_id, old_name, repo_id)
161 VALUES ($3::bigint, $4::bigint, $1, $2)
162 ON CONFLICT DO NOTHING
163 `
164
165 type InsertRepoRedirectParams struct {
166 OldName string
167 RepoID int64
168 OldOwnerUserID pgtype.Int8
169 OldOwnerOrgID pgtype.Int8
170 }
171
172 // ─── redirects ─────────────────────────────────────────────────────────
173 // Both old-owner FKs are nullable; pass exactly one. The CHECK
174 // constraint on the table enforces the xor shape.
175 func (q *Queries) InsertRepoRedirect(ctx context.Context, db DBTX, arg InsertRepoRedirectParams) error {
176 _, err := db.Exec(ctx, insertRepoRedirect,
177 arg.OldName,
178 arg.RepoID,
179 arg.OldOwnerUserID,
180 arg.OldOwnerOrgID,
181 )
182 return err
183 }
184
185 const insertTransferRequest = `-- name: InsertTransferRequest :one
186
187 INSERT INTO repo_transfer_requests (
188 repo_id, from_user_id, to_principal_kind, to_principal_id,
189 created_by, expires_at
190 ) VALUES (
191 $1, $2, $3, $4, $5, $6
192 )
193 RETURNING id, repo_id, from_user_id, to_principal_kind, to_principal_id,
194 created_by, created_at, expires_at, status,
195 accepted_at, declined_at, canceled_at
196 `
197
198 type InsertTransferRequestParams struct {
199 RepoID int64
200 FromUserID int64
201 ToPrincipalKind TransferPrincipalKind
202 ToPrincipalID int64
203 CreatedBy int64
204 ExpiresAt pgtype.Timestamptz
205 }
206
207 // ─── transfer requests ─────────────────────────────────────────────────
208 func (q *Queries) InsertTransferRequest(ctx context.Context, db DBTX, arg InsertTransferRequestParams) (RepoTransferRequest, error) {
209 row := db.QueryRow(ctx, insertTransferRequest,
210 arg.RepoID,
211 arg.FromUserID,
212 arg.ToPrincipalKind,
213 arg.ToPrincipalID,
214 arg.CreatedBy,
215 arg.ExpiresAt,
216 )
217 var i RepoTransferRequest
218 err := row.Scan(
219 &i.ID,
220 &i.RepoID,
221 &i.FromUserID,
222 &i.ToPrincipalKind,
223 &i.ToPrincipalID,
224 &i.CreatedBy,
225 &i.CreatedAt,
226 &i.ExpiresAt,
227 &i.Status,
228 &i.AcceptedAt,
229 &i.DeclinedAt,
230 &i.CanceledAt,
231 )
232 return i, err
233 }
234
235 const listPendingTransfersForUser = `-- name: ListPendingTransfersForUser :many
236 SELECT id, repo_id, from_user_id, to_principal_kind, to_principal_id,
237 created_by, created_at, expires_at, status,
238 accepted_at, declined_at, canceled_at
239 FROM repo_transfer_requests
240 WHERE to_principal_kind = 'user' AND to_principal_id = $1 AND status = 'pending'
241 ORDER BY created_at DESC
242 `
243
244 // Inbox view: pending offers a user can act on.
245 func (q *Queries) ListPendingTransfersForUser(ctx context.Context, db DBTX, toPrincipalID int64) ([]RepoTransferRequest, error) {
246 rows, err := db.Query(ctx, listPendingTransfersForUser, toPrincipalID)
247 if err != nil {
248 return nil, err
249 }
250 defer rows.Close()
251 items := []RepoTransferRequest{}
252 for rows.Next() {
253 var i RepoTransferRequest
254 if err := rows.Scan(
255 &i.ID,
256 &i.RepoID,
257 &i.FromUserID,
258 &i.ToPrincipalKind,
259 &i.ToPrincipalID,
260 &i.CreatedBy,
261 &i.CreatedAt,
262 &i.ExpiresAt,
263 &i.Status,
264 &i.AcceptedAt,
265 &i.DeclinedAt,
266 &i.CanceledAt,
267 ); err != nil {
268 return nil, err
269 }
270 items = append(items, i)
271 }
272 if err := rows.Err(); err != nil {
273 return nil, err
274 }
275 return items, nil
276 }
277
278 const listRepoIDsPastSoftDeleteGrace = `-- name: ListRepoIDsPastSoftDeleteGrace :many
279
280 SELECT id FROM repos
281 WHERE deleted_at IS NOT NULL AND deleted_at < now() - interval '7 days'
282 ORDER BY deleted_at ASC
283 `
284
285 // ─── soft-delete sweep query ───────────────────────────────────────────
286 // The repo:hard_delete enqueuer queries this to find rows ready for
287 // destruction. The 7-day grace is hard-coded here; if we add a config
288 // knob later, change this to a parameter.
289 func (q *Queries) ListRepoIDsPastSoftDeleteGrace(ctx context.Context, db DBTX) ([]int64, error) {
290 rows, err := db.Query(ctx, listRepoIDsPastSoftDeleteGrace)
291 if err != nil {
292 return nil, err
293 }
294 defer rows.Close()
295 items := []int64{}
296 for rows.Next() {
297 var id int64
298 if err := rows.Scan(&id); err != nil {
299 return nil, err
300 }
301 items = append(items, id)
302 }
303 if err := rows.Err(); err != nil {
304 return nil, err
305 }
306 return items, nil
307 }
308
309 const listSoftDeletedReposForOwner = `-- name: ListSoftDeletedReposForOwner :many
310 SELECT id, owner_user_id, name, deleted_at
311 FROM repos
312 WHERE owner_user_id = $1 AND deleted_at IS NOT NULL
313 ORDER BY deleted_at DESC
314 `
315
316 type ListSoftDeletedReposForOwnerRow struct {
317 ID int64
318 OwnerUserID pgtype.Int8
319 Name string
320 DeletedAt pgtype.Timestamptz
321 }
322
323 // /settings/repositories/restore page lists these.
324 func (q *Queries) ListSoftDeletedReposForOwner(ctx context.Context, db DBTX, ownerUserID pgtype.Int8) ([]ListSoftDeletedReposForOwnerRow, error) {
325 rows, err := db.Query(ctx, listSoftDeletedReposForOwner, ownerUserID)
326 if err != nil {
327 return nil, err
328 }
329 defer rows.Close()
330 items := []ListSoftDeletedReposForOwnerRow{}
331 for rows.Next() {
332 var i ListSoftDeletedReposForOwnerRow
333 if err := rows.Scan(
334 &i.ID,
335 &i.OwnerUserID,
336 &i.Name,
337 &i.DeletedAt,
338 ); err != nil {
339 return nil, err
340 }
341 items = append(items, i)
342 }
343 if err := rows.Err(); err != nil {
344 return nil, err
345 }
346 return items, nil
347 }
348
349 const listTransfersForRepo = `-- name: ListTransfersForRepo :many
350 SELECT id, repo_id, from_user_id, to_principal_kind, to_principal_id,
351 created_by, created_at, expires_at, status,
352 accepted_at, declined_at, canceled_at
353 FROM repo_transfer_requests
354 WHERE repo_id = $1
355 ORDER BY created_at DESC
356 `
357
358 // Sender / repo-settings view.
359 func (q *Queries) ListTransfersForRepo(ctx context.Context, db DBTX, repoID int64) ([]RepoTransferRequest, error) {
360 rows, err := db.Query(ctx, listTransfersForRepo, repoID)
361 if err != nil {
362 return nil, err
363 }
364 defer rows.Close()
365 items := []RepoTransferRequest{}
366 for rows.Next() {
367 var i RepoTransferRequest
368 if err := rows.Scan(
369 &i.ID,
370 &i.RepoID,
371 &i.FromUserID,
372 &i.ToPrincipalKind,
373 &i.ToPrincipalID,
374 &i.CreatedBy,
375 &i.CreatedAt,
376 &i.ExpiresAt,
377 &i.Status,
378 &i.AcceptedAt,
379 &i.DeclinedAt,
380 &i.CanceledAt,
381 ); err != nil {
382 return nil, err
383 }
384 items = append(items, i)
385 }
386 if err := rows.Err(); err != nil {
387 return nil, err
388 }
389 return items, nil
390 }
391
392 const lookupRedirectByUserOwner = `-- name: LookupRedirectByUserOwner :one
393 SELECT repo_id FROM repo_redirects
394 WHERE old_owner_user_id = $1 AND old_name = $2
395 `
396
397 type LookupRedirectByUserOwnerParams struct {
398 OldOwnerUserID pgtype.Int8
399 OldName string
400 }
401
402 // Returns the current repo_id when (old_owner_user_id, old_name) hits
403 // a redirect row.
404 func (q *Queries) LookupRedirectByUserOwner(ctx context.Context, db DBTX, arg LookupRedirectByUserOwnerParams) (int64, error) {
405 row := db.QueryRow(ctx, lookupRedirectByUserOwner, arg.OldOwnerUserID, arg.OldName)
406 var repo_id int64
407 err := row.Scan(&repo_id)
408 return repo_id, err
409 }
410
411 const orphanForksOf = `-- name: OrphanForksOf :execrows
412
413 UPDATE repos SET fork_of_repo_id = NULL WHERE fork_of_repo_id = $1
414 `
415
416 // ─── fork-anchor cleanup on hard delete ────────────────────────────────
417 // Children pointing at this repo lose their fork-of pointer. Mirrors
418 // GitHub's behavior when an upstream is deleted.
419 func (q *Queries) OrphanForksOf(ctx context.Context, db DBTX, forkOfRepoID pgtype.Int8) (int64, error) {
420 result, err := db.Exec(ctx, orphanForksOf, forkOfRepoID)
421 if err != nil {
422 return 0, err
423 }
424 return result.RowsAffected(), nil
425 }
426
427 const renameRepo = `-- name: RenameRepo :exec
428
429
430 UPDATE repos SET name = $2, updated_at = now() WHERE id = $1
431 `
432
433 type RenameRepoParams struct {
434 ID int64
435 Name string
436 }
437
438 // SPDX-License-Identifier: AGPL-3.0-or-later
439 //
440 // S16 lifecycle queries. Kept in a separate file from repos.sql so the
441 // mainline CRUD stays easy to read.
442 // ─── repo mutations ────────────────────────────────────────────────────
443 // Same-owner rename. The handler validates the new name shape and the
444 // redirect row is INSERTed in the same tx.
445 func (q *Queries) RenameRepo(ctx context.Context, db DBTX, arg RenameRepoParams) error {
446 _, err := db.Exec(ctx, renameRepo, arg.ID, arg.Name)
447 return err
448 }
449
450 const restoreRepo = `-- name: RestoreRepo :exec
451 UPDATE repos SET deleted_at = NULL, updated_at = now() WHERE id = $1
452 `
453
454 func (q *Queries) RestoreRepo(ctx context.Context, db DBTX, id int64) error {
455 _, err := db.Exec(ctx, restoreRepo, id)
456 return err
457 }
458
459 const setRepoVisibility = `-- name: SetRepoVisibility :exec
460 UPDATE repos SET visibility = $2, updated_at = now() WHERE id = $1
461 `
462
463 type SetRepoVisibilityParams struct {
464 ID int64
465 Visibility RepoVisibility
466 }
467
468 func (q *Queries) SetRepoVisibility(ctx context.Context, db DBTX, arg SetRepoVisibilityParams) error {
469 _, err := db.Exec(ctx, setRepoVisibility, arg.ID, arg.Visibility)
470 return err
471 }
472
473 const softDeleteRepoLifecycle = `-- name: SoftDeleteRepoLifecycle :exec
474 UPDATE repos SET deleted_at = now(), updated_at = now() WHERE id = $1
475 `
476
477 // Distinct name from S11's SoftDeleteRepo so future code that wants to
478 // preserve the lifecycle audit-emission shape can find this one.
479 func (q *Queries) SoftDeleteRepoLifecycle(ctx context.Context, db DBTX, id int64) error {
480 _, err := db.Exec(ctx, softDeleteRepoLifecycle, id)
481 return err
482 }
483
484 const transferRepoOwner = `-- name: TransferRepoOwner :exec
485 UPDATE repos
486 SET owner_user_id = $3::bigint,
487 owner_org_id = $4::bigint,
488 name = $2,
489 updated_at = now()
490 WHERE id = $1
491 `
492
493 type TransferRepoOwnerParams struct {
494 ID int64
495 Name string
496 OwnerUserID pgtype.Int8
497 OwnerOrgID pgtype.Int8
498 }
499
500 // Sets owner_user_id (or owner_org_id post-S31) on accept. The xor
501 // check on the table enforces the shape. Also clears the other side
502 // so a user→org transfer flips both columns atomically.
503 func (q *Queries) TransferRepoOwner(ctx context.Context, db DBTX, arg TransferRepoOwnerParams) error {
504 _, err := db.Exec(ctx, transferRepoOwner,
505 arg.ID,
506 arg.Name,
507 arg.OwnerUserID,
508 arg.OwnerOrgID,
509 )
510 return err
511 }
512
513 const unarchiveRepo = `-- name: UnarchiveRepo :exec
514 UPDATE repos SET is_archived = false, archived_at = NULL, updated_at = now() WHERE id = $1
515 `
516
517 func (q *Queries) UnarchiveRepo(ctx context.Context, db DBTX, id int64) error {
518 _, err := db.Exec(ctx, unarchiveRepo, id)
519 return err
520 }
521