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 }