Personal Git forge.
package dbimport ( "errors" "farga/db/types" "farga/lib" errs "farga/lib/errors" lib_git "farga/lib/git" "fmt" "strings" "github.com/go-git/go-git/v6" "github.com/google/uuid" "gorm.io/gorm/clause")// creates a new repo, both in-DB and on-disk.// it may fail with `errors.ErrRepoAlreadyExists` if the repo exists.// do not forget to close the git repo afterwards.func (db *DB) NewRepo(user types.User, repo types.Repo) (*git.Repository, error) { branch := user.Config.GitDefaultBranch if branch == "" { branch = lib.GitDefaultBranch } if repoMeta, err := db.Repo(repo); err == nil && repoMeta.ID != uuid.Nil { return nil, errs.ErrRepoAlreadyExists // check if it already exists on a DB level. } repo.Config = types.RepoConfig{ AllowAnonymousIssues: true, // default AllowNewIssues: true, // default } // create the record inside the db err := db.Create(&repo).Error if err != nil { if strings.Contains(err.Error(), "UNIQUE constraint") { return nil, errs.ErrRepoAlreadyExists // shouldn't happen but handle gracefully, just in case. } return nil, err } // create the actual git repo gitRepo, err := lib_git.InitRepo(user.ID, repo.ID) if err != nil { // cleanup suberr := db.Where(&repo).Delete(&repo).Error if suberr != nil { return nil, fmt.Errorf("init failed: %w; cleanup also failed: %w", err, suberr) } return nil, err } return gitRepo, nil}func (db *DB) Repo(repo types.Repo) (types.Repo, error) { err := db.Preload(clause.Associations).Where(&repo).Find(&repo).Error return repo, err}// gets a repo based off a user's handle and their repo's name.func (db *DB) RepoHandle(userHandle, repoName string) (types.Repo, error) { var repo types.Repo err := db. Preload(clause.Associations). Joins("JOIN users ON users.id = repos.user_id"). Where("users.handle = ? AND repos.name = ?", userHandle, repoName). First(&repo).Error return repo, err}// deletes a repofunc (db *DB) DeleteRepo(repoID uuid.UUID) error { err := db.Model(&types.Repo{}).Delete(&types.Repo{}, repoID).Error return err}// gets all repos from a given user.func (db *DB) UserRepos(userId *uuid.UUID) ([]types.Repo, error) { var repos []types.Repo err := db.Preload("User").Where(&types.Repo{UserID: userId}).Find(&repos).Error return repos, err}// updates a given repo's default branchfunc (db *DB) SetRepoDefaultBranch(repo types.Repo, branch string) error { return db.Model(&repo).Update("base_branch", branch).Error // be careful with other ways to update this since they get rid of EVERYTHING.}// gets a repo by its name and owner's ID.func (db *DB) RepoByName(ownerID *uuid.UUID, name string) (types.Repo, error) { var repo types.Repo err := db.Where(&types.Repo{UserID: ownerID, Name: name}).First(&repo).Error return repo, err}// assigns a hackatime project to a repo. use the hackatime project name. if fed "", it'll be set to NULL.func (db *DB) SetRepoHackatimeName(repoID uuid.UUID, name string) error { return db.Model(&types.Repo{}). Where("id = ?", repoID). Update("hackatime_name", name). Error}// sets a given repo's visibility, true being public and false being private.func (db *DB) SetRepoVisibility(repoID uuid.UUID, public bool) error { return db.Model(&types.Repo{}).Where(&types.Repo{UUID_ID: types.UUID_ID{ID: repoID}}).Update("is_private", !public).Error}var ErrEmptyArgument = errors.New("You fed an empty struct.")// updates a repo's configuration regarding Issues.func (db *DB) SetRepoIssueConfig(repoID uuid.UUID, allowAnonymousIssues bool, allowNewIssues bool) error { cfg := types.RepoConfig{RepoID: repoID} // if the repo does not have a config, insert one AND retrieve it. if err := db.Where(&cfg).FirstOrCreate(&cfg).Error; err != nil { return err } // perform the update return db.Model(&cfg).Updates(map[string]any{ "allow_anonymous_issues": allowAnonymousIssues, "allow_new_issues": allowNewIssues, }).Error}