github.com/covergates/covergates@v0.2.2-0.20201009050117-42ef8a19fb95/models/repo.go (about)

     1  package models
     2  
     3  import (
     4  	"encoding/json"
     5  	"errors"
     6  	"fmt"
     7  
     8  	"github.com/covergates/covergates/core"
     9  	"gorm.io/gorm"
    10  )
    11  
    12  var errEmptyRepoFiled = errors.New("repository must have SCM and URL filed")
    13  
    14  // Repo defines a repository
    15  type Repo struct {
    16  	gorm.Model
    17  	URL       string `gorm:"size:256;uniqueIndex;not null"`
    18  	ReportID  string
    19  	NameSpace string `gorm:"index;not null"`
    20  	Name      string `gorm:"index;not null"`
    21  	Branch    string
    22  	SCM       string `gorm:"index;not null"`
    23  	Creator   string
    24  	Private   bool
    25  }
    26  
    27  // RepoSetting defines user customization
    28  type RepoSetting struct {
    29  	gorm.Model
    30  	RepoID uint `gorm:"uniqueIndex"`
    31  	Config []byte
    32  }
    33  
    34  // RepoHook defines created hooks in a repository
    35  type RepoHook struct {
    36  	gorm.Model
    37  	RepoID uint `gorm:"index"`
    38  	Hook   string
    39  }
    40  
    41  // RepoStore repositories in storage
    42  type RepoStore struct {
    43  	DB core.DatabaseService
    44  }
    45  
    46  // ToCoreRepo object
    47  func (repo *Repo) ToCoreRepo() *core.Repo {
    48  	return &core.Repo{
    49  		ID:        repo.ID,
    50  		Name:      repo.Name,
    51  		NameSpace: repo.NameSpace,
    52  		ReportID:  repo.ReportID,
    53  		SCM:       core.SCMProvider(repo.SCM),
    54  		Branch:    repo.Branch,
    55  		URL:       repo.URL,
    56  		Private:   repo.Private,
    57  	}
    58  }
    59  
    60  // Update with a new setting
    61  func (setting *RepoSetting) Update(newSetting *core.RepoSetting) error {
    62  	data, err := json.Marshal(newSetting)
    63  	if err != nil {
    64  		return err
    65  	}
    66  	setting.Config = data
    67  	return nil
    68  }
    69  
    70  // Create a new repository
    71  func (store *RepoStore) Create(repo *core.Repo) error {
    72  	if repo.SCM == "" || repo.URL == "" {
    73  		return errEmptyRepoFiled
    74  	}
    75  	session := store.DB.Session()
    76  	r := &Repo{
    77  		URL:       repo.URL,
    78  		NameSpace: repo.NameSpace,
    79  		Name:      repo.Name,
    80  		SCM:       string(repo.SCM),
    81  		Branch:    repo.Branch,
    82  		Private:   repo.Private,
    83  	}
    84  	return session.Create(r).Error
    85  }
    86  
    87  // Update repository information
    88  func (store *RepoStore) Update(repo *core.Repo) error {
    89  	session := store.DB.Session()
    90  	r := &Repo{}
    91  	if err := session.Where(&Repo{URL: repo.URL}).First(r).Error; err != nil {
    92  		return err
    93  	}
    94  	copyRepo(r, repo)
    95  	return session.Save(r).Error
    96  }
    97  
    98  // UpdateOrCreate repository, notice that only below fields will be affected:
    99  // Name, NameSpace, URL, SCM, Branch, Private
   100  func (store *RepoStore) UpdateOrCreate(repo *core.Repo) error {
   101  	session := store.DB.Session()
   102  	return store.updateOrCreate(session, repo)
   103  }
   104  
   105  func (store *RepoStore) updateOrCreate(session *gorm.DB, repo *core.Repo) error {
   106  	if repo.URL == "" {
   107  		return errEmptyRepoFiled
   108  	}
   109  	r := &Repo{
   110  		URL:       repo.URL,
   111  		NameSpace: repo.NameSpace,
   112  		Name:      repo.Name,
   113  		SCM:       string(repo.SCM),
   114  		Branch:    repo.Branch,
   115  		Private:   repo.Private,
   116  	}
   117  	if err := session.FirstOrCreate(r, r).Error; err != nil {
   118  		return err
   119  	}
   120  	copyRepo(r, repo)
   121  	return session.Model(r).Select(
   122  		"URL",
   123  		"Name",
   124  		"NameSpace",
   125  		"SCM",
   126  		"Branch",
   127  		"Private",
   128  	).Updates(r).Error
   129  }
   130  
   131  // BatchUpdateOrCreate repositories
   132  func (store *RepoStore) BatchUpdateOrCreate(repos []*core.Repo) error {
   133  	session := store.DB.Session()
   134  	var err error
   135  	session.Transaction(func(tx *gorm.DB) error {
   136  		for _, repo := range repos {
   137  			if err = store.updateOrCreate(tx, repo); err != nil {
   138  				return err
   139  			}
   140  		}
   141  		return nil
   142  	})
   143  	return err
   144  }
   145  
   146  // Find Repo with seed. The non-empty filed of input will use as where condition
   147  func (store *RepoStore) Find(repo *core.Repo) (*core.Repo, error) {
   148  	session := store.DB.Session()
   149  	r := &Repo{}
   150  	if err := session.Where(repo).First(r).Error; err != nil {
   151  		return nil, err
   152  	}
   153  	return r.ToCoreRepo(), nil
   154  }
   155  
   156  // Creator user who activated the repository
   157  func (store *RepoStore) Creator(repo *core.Repo) (*core.User, error) {
   158  	session := store.DB.Session()
   159  	r := &Repo{}
   160  	if err := session.Where(repo).First(r).Error; err != nil {
   161  		return nil, err
   162  	}
   163  	user := &User{
   164  		Login: r.Creator,
   165  	}
   166  	if err := session.First(user, user).Error; err != nil {
   167  		return nil, err
   168  	}
   169  	return user.toCoreUser(), nil
   170  }
   171  
   172  // UpdateCreator of the repository
   173  func (store *RepoStore) UpdateCreator(repo *core.Repo, user *core.User) error {
   174  	session := store.DB.Session()
   175  	r := &Repo{}
   176  	if err := session.Where(repo).First(r).Error; err != nil {
   177  		return err
   178  	}
   179  	r.Creator = user.Login
   180  	return session.Save(r).Error
   181  }
   182  
   183  // Finds all repositories with URLs
   184  func (store *RepoStore) Finds(urls ...string) ([]*core.Repo, error) {
   185  	session := store.DB.Session()
   186  	var repositories []*Repo
   187  	session = session.Where("url in (?)", urls).Find(&repositories)
   188  	if err := session.Error; err != nil {
   189  		return nil, err
   190  	}
   191  	coreRepositories := make([]*core.Repo, len(repositories))
   192  	for i, repo := range repositories {
   193  		coreRepositories[i] = repo.ToCoreRepo()
   194  	}
   195  	return coreRepositories, nil
   196  }
   197  
   198  // Setting of the repository
   199  func (store *RepoStore) Setting(repo *core.Repo) (*core.RepoSetting, error) {
   200  	session := store.DB.Session()
   201  	setting := &RepoSetting{RepoID: repo.ID}
   202  	if err := session.Where(setting).First(setting).Error; err != nil {
   203  		return &core.RepoSetting{}, nil
   204  	}
   205  	coreSetting := &core.RepoSetting{}
   206  	if err := json.Unmarshal(setting.Config, coreSetting); err != nil {
   207  		return nil, err
   208  	}
   209  	return coreSetting, nil
   210  }
   211  
   212  // UpdateSetting for the repository
   213  func (store *RepoStore) UpdateSetting(repo *core.Repo, setting *core.RepoSetting) error {
   214  	session := store.DB.Session()
   215  	repoSetting := &RepoSetting{RepoID: repo.ID}
   216  	if err := session.Where(repoSetting).FirstOrCreate(repoSetting).Error; err != nil {
   217  		return err
   218  	}
   219  	if err := repoSetting.Update(setting); err != nil {
   220  		return err
   221  	}
   222  	return session.Save(repoSetting).Error
   223  }
   224  
   225  // UpdateHook of the repository
   226  func (store *RepoStore) UpdateHook(repo *core.Repo, hook *core.Hook) error {
   227  	if repo.ID <= 0 {
   228  		return fmt.Errorf("invalid repository")
   229  	}
   230  	if hook.ID == "" {
   231  		return fmt.Errorf("invalid hook")
   232  	}
   233  	session := store.DB.Session()
   234  	h := &RepoHook{}
   235  	if err := session.FirstOrCreate(h, &RepoHook{RepoID: repo.ID}).Error; err != nil {
   236  		return err
   237  	}
   238  	h.Hook = hook.ID
   239  	return session.Save(h).Error
   240  }
   241  
   242  // FindHook for the repository
   243  func (store *RepoStore) FindHook(repo *core.Repo) (*core.Hook, error) {
   244  	session := store.DB.Session()
   245  	h := &RepoHook{}
   246  	if err := session.First(h, &RepoHook{RepoID: repo.ID}).Error; err != nil {
   247  		return nil, err
   248  	}
   249  	return &core.Hook{
   250  		ID: h.Hook,
   251  	}, nil
   252  }
   253  
   254  func copyRepo(dst *Repo, src *core.Repo) {
   255  	dst.ReportID = src.ReportID
   256  	dst.Branch = src.Branch
   257  	dst.Private = src.Private
   258  }