package store import ( "context" "database/sql" "fmt" "strings" "time" ) type BlockedPackage struct { ID int64 RepoID int64 Name string Location string CreatedAt time.Time } type BlockedPackageStore interface { BlockPackages(ctx context.Context, repoID int64, pkgs []BlockedPackage) error UnblockPackages(ctx context.Context, repoID int64, ids []int64) error ListBlocked(ctx context.Context, repoID int64) ([]BlockedPackage, error) } type SQLiteBlockedPackageStore struct { db *sql.DB } func NewBlockedPackageStore(db *sql.DB) *SQLiteBlockedPackageStore { return &SQLiteBlockedPackageStore{db: db} } func (s *SQLiteBlockedPackageStore) BlockPackages(ctx context.Context, repoID int64, pkgs []BlockedPackage) error { for _, p := range pkgs { _, err := s.db.ExecContext(ctx, `INSERT OR IGNORE INTO blocked_packages (repo_id, name, location) VALUES (?, ?, ?)`, repoID, p.Name, p.Location) if err != nil { return err } } return nil } func (s *SQLiteBlockedPackageStore) UnblockPackages(ctx context.Context, repoID int64, ids []int64) error { if len(ids) == 0 { return nil } placeholders := strings.Join(strings.Fields(strings.Repeat("? ", len(ids))), ", ") query := fmt.Sprintf("DELETE FROM blocked_packages WHERE repo_id = ? AND id IN (%s)", placeholders) args := make([]any, 0, len(ids)+1) args = append(args, repoID) for _, id := range ids { args = append(args, id) } _, err := s.db.ExecContext(ctx, query, args...) return err } func (s *SQLiteBlockedPackageStore) ListBlocked(ctx context.Context, repoID int64) ([]BlockedPackage, error) { rows, err := s.db.QueryContext(ctx, `SELECT id, repo_id, name, location, created_at FROM blocked_packages WHERE repo_id = ? ORDER BY id ASC`, repoID) if err != nil { return nil, err } defer rows.Close() var pkgs []BlockedPackage for rows.Next() { var p BlockedPackage if err := rows.Scan(&p.ID, &p.RepoID, &p.Name, &p.Location, &p.CreatedAt); err != nil { return nil, err } pkgs = append(pkgs, p) } return pkgs, rows.Err() }