Something went wrong. Try again.
forked from tangled.org/core
Something went wrong. Try again.
Go
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400package db
import ( "database/sql" "fmt" "time"
"github.com/bluesky-social/indigo/atproto/syntax" securejoin "github.com/cyphar/filepath-securejoin" "tangled.sh/tangled.sh/core/api/tangled")
type Repo struct { Did string Name string Knot string Rkey string Created time.Time AtUri string Description string
// optionally, populate this when querying for reverse mappings RepoStats *RepoStats
// optional Source string}
func (r Repo) RepoAt() syntax.ATURI { return syntax.ATURI(fmt.Sprintf("at://%s/%s/%s", r.Did, tangled.RepoNSID, r.Rkey))}
func (r Repo) DidSlashRepo() string { p, _ := securejoin.SecureJoin(r.Did, r.Name) return p}
func GetAllRepos(e Execer, limit int) ([]Repo, error) { var repos []Repo
rows, err := e.Query( `select did, name, knot, rkey, description, created, source from repos order by created desc limit ? `, limit, ) if err != nil { return nil, err } defer rows.Close()
for rows.Next() { var repo Repo err := scanRepo( rows, &repo.Did, &repo.Name, &repo.Knot, &repo.Rkey, &repo.Description, &repo.Created, &repo.Source, ) if err != nil { return nil, err } repos = append(repos, repo) }
if err := rows.Err(); err != nil { return nil, err }
return repos, nil}
func GetAllReposByDid(e Execer, did string) ([]Repo, error) { var repos []Repo
rows, err := e.Query( `select r.did, r.name, r.knot, r.rkey, r.description, r.created, count(s.id) as star_count, r.source from repos r left join stars s on r.at_uri = s.repo_at where r.did = ? group by r.at_uri order by r.created desc`, did) if err != nil { return nil, err } defer rows.Close()
for rows.Next() { var repo Repo var repoStats RepoStats var createdAt string var nullableDescription sql.NullString var nullableSource sql.NullString
err := rows.Scan(&repo.Did, &repo.Name, &repo.Knot, &repo.Rkey, &nullableDescription, &createdAt, &repoStats.StarCount, &nullableSource) if err != nil { return nil, err }
if nullableDescription.Valid { repo.Description = nullableDescription.String }
if nullableSource.Valid { repo.Source = nullableSource.String }
createdAtTime, err := time.Parse(time.RFC3339, createdAt) if err != nil { repo.Created = time.Now() } else { repo.Created = createdAtTime }
repo.RepoStats = &repoStats
repos = append(repos, repo) }
if err := rows.Err(); err != nil { return nil, err }
return repos, nil}
func GetRepo(e Execer, did, name string) (*Repo, error) { var repo Repo var nullableDescription sql.NullString
row := e.QueryRow(`select did, name, knot, created, at_uri, description from repos where did = ? and name = ?`, did, name)
var createdAt string if err := row.Scan(&repo.Did, &repo.Name, &repo.Knot, &createdAt, &repo.AtUri, &nullableDescription); err != nil { return nil, err } createdAtTime, _ := time.Parse(time.RFC3339, createdAt) repo.Created = createdAtTime
if nullableDescription.Valid { repo.Description = nullableDescription.String } else { repo.Description = "" }
return &repo, nil}
func GetRepoByAtUri(e Execer, atUri string) (*Repo, error) { var repo Repo var nullableDescription sql.NullString
row := e.QueryRow(`select did, name, knot, created, at_uri, description from repos where at_uri = ?`, atUri)
var createdAt string if err := row.Scan(&repo.Did, &repo.Name, &repo.Knot, &createdAt, &repo.AtUri, &nullableDescription); err != nil { return nil, err } createdAtTime, _ := time.Parse(time.RFC3339, createdAt) repo.Created = createdAtTime
if nullableDescription.Valid { repo.Description = nullableDescription.String } else { repo.Description = "" }
return &repo, nil}
func AddRepo(e Execer, repo *Repo) error { _, err := e.Exec( `insert into repos (did, name, knot, rkey, at_uri, description, source) values (?, ?, ?, ?, ?, ?, ?)`, repo.Did, repo.Name, repo.Knot, repo.Rkey, repo.AtUri, repo.Description, repo.Source, ) return err}
func RemoveRepo(e Execer, did, name string) error { _, err := e.Exec(`delete from repos where did = ? and name = ?`, did, name) return err}
func GetRepoSource(e Execer, repoAt syntax.ATURI) (string, error) { var nullableSource sql.NullString err := e.QueryRow(`select source from repos where at_uri = ?`, repoAt).Scan(&nullableSource) if err != nil { return "", err } return nullableSource.String, nil}
func GetForksByDid(e Execer, did string) ([]Repo, error) { var repos []Repo
rows, err := e.Query( `select did, name, knot, rkey, description, created, at_uri, source from repos where did = ? and source is not null and source != '' order by created desc`, did, ) if err != nil { return nil, err } defer rows.Close()
for rows.Next() { var repo Repo var createdAt string var nullableDescription sql.NullString var nullableSource sql.NullString
err := rows.Scan(&repo.Did, &repo.Name, &repo.Knot, &repo.Rkey, &nullableDescription, &createdAt, &repo.AtUri, &nullableSource) if err != nil { return nil, err }
if nullableDescription.Valid { repo.Description = nullableDescription.String }
if nullableSource.Valid { repo.Source = nullableSource.String }
createdAtTime, err := time.Parse(time.RFC3339, createdAt) if err != nil { repo.Created = time.Now() } else { repo.Created = createdAtTime }
repos = append(repos, repo) }
if err := rows.Err(); err != nil { return nil, err }
return repos, nil}
func GetForkByDid(e Execer, did string, name string) (*Repo, error) { var repo Repo var createdAt string var nullableDescription sql.NullString var nullableSource sql.NullString
row := e.QueryRow( `select did, name, knot, rkey, description, created, at_uri, source from repos where did = ? and name = ? and source is not null and source != ''`, did, name, )
err := row.Scan(&repo.Did, &repo.Name, &repo.Knot, &repo.Rkey, &nullableDescription, &createdAt, &repo.AtUri, &nullableSource) if err != nil { return nil, err }
if nullableDescription.Valid { repo.Description = nullableDescription.String }
if nullableSource.Valid { repo.Source = nullableSource.String }
createdAtTime, err := time.Parse(time.RFC3339, createdAt) if err != nil { repo.Created = time.Now() } else { repo.Created = createdAtTime }
return &repo, nil}
func AddCollaborator(e Execer, collaborator, repoOwnerDid, repoName, repoKnot string) error { _, err := e.Exec( `insert into collaborators (did, repo) values (?, (select id from repos where did = ? and name = ? and knot = ?));`, collaborator, repoOwnerDid, repoName, repoKnot) return err}
func UpdateDescription(e Execer, repoAt, newDescription string) error { _, err := e.Exec( `update repos set description = ? where at_uri = ?`, newDescription, repoAt) return err}
func CollaboratingIn(e Execer, collaborator string) ([]Repo, error) { var repos []Repo
rows, err := e.Query( `select r.did, r.name, r.knot, r.rkey, r.description, r.created, count(s.id) as star_count from repos r join collaborators c on r.id = c.repo left join stars s on r.at_uri = s.repo_at where c.did = ? group by r.id;`, collaborator) if err != nil { return nil, err } defer rows.Close()
for rows.Next() { var repo Repo var repoStats RepoStats var createdAt string var nullableDescription sql.NullString
err := rows.Scan(&repo.Did, &repo.Name, &repo.Knot, &repo.Rkey, &nullableDescription, &createdAt, &repoStats.StarCount) if err != nil { return nil, err }
if nullableDescription.Valid { repo.Description = nullableDescription.String } else { repo.Description = "" }
createdAtTime, err := time.Parse(time.RFC3339, createdAt) if err != nil { repo.Created = time.Now() } else { repo.Created = createdAtTime }
repo.RepoStats = &repoStats
repos = append(repos, repo) }
if err := rows.Err(); err != nil { return nil, err }
return repos, nil}
type RepoStats struct { StarCount int IssueCount IssueCount PullCount PullCount}
func scanRepo(rows *sql.Rows, did, name, knot, rkey, description *string, created *time.Time, source *string) error { var createdAt string var nullableDescription sql.NullString var nullableSource sql.NullString if err := rows.Scan(did, name, knot, rkey, &nullableDescription, &createdAt, &nullableSource); err != nil { return err }
if nullableDescription.Valid { *description = nullableDescription.String } else { *description = "" }
createdAtTime, err := time.Parse(time.RFC3339, createdAt) if err != nil { *created = time.Now() } else { *created = createdAtTime }
if nullableSource.Valid { *source = nullableSource.String } else { *source = "" }
return nil}