code.gitea.io/gitea@v1.22.3/models/repo/repo_unit.go (about) 1 // Copyright 2017 The Gitea Authors. All rights reserved. 2 // SPDX-License-Identifier: MIT 3 4 package repo 5 6 import ( 7 "context" 8 "fmt" 9 "slices" 10 "strings" 11 12 "code.gitea.io/gitea/models/db" 13 "code.gitea.io/gitea/models/perm" 14 "code.gitea.io/gitea/models/unit" 15 "code.gitea.io/gitea/modules/json" 16 "code.gitea.io/gitea/modules/setting" 17 "code.gitea.io/gitea/modules/timeutil" 18 "code.gitea.io/gitea/modules/util" 19 20 "xorm.io/xorm" 21 "xorm.io/xorm/convert" 22 ) 23 24 // ErrUnitTypeNotExist represents a "UnitTypeNotExist" kind of error. 25 type ErrUnitTypeNotExist struct { 26 UT unit.Type 27 } 28 29 // IsErrUnitTypeNotExist checks if an error is a ErrUnitNotExist. 30 func IsErrUnitTypeNotExist(err error) bool { 31 _, ok := err.(ErrUnitTypeNotExist) 32 return ok 33 } 34 35 func (err ErrUnitTypeNotExist) Error() string { 36 return fmt.Sprintf("Unit type does not exist: %s", err.UT.String()) 37 } 38 39 func (err ErrUnitTypeNotExist) Unwrap() error { 40 return util.ErrNotExist 41 } 42 43 // RepoUnit describes all units of a repository 44 type RepoUnit struct { //revive:disable-line:exported 45 ID int64 46 RepoID int64 `xorm:"INDEX(s)"` 47 Type unit.Type `xorm:"INDEX(s)"` 48 Config convert.Conversion `xorm:"TEXT"` 49 CreatedUnix timeutil.TimeStamp `xorm:"INDEX CREATED"` 50 EveryoneAccessMode perm.AccessMode `xorm:"NOT NULL DEFAULT 0"` 51 } 52 53 func init() { 54 db.RegisterModel(new(RepoUnit)) 55 } 56 57 // UnitConfig describes common unit config 58 type UnitConfig struct{} 59 60 // FromDB fills up a UnitConfig from serialized format. 61 func (cfg *UnitConfig) FromDB(bs []byte) error { 62 return json.UnmarshalHandleDoubleEncode(bs, &cfg) 63 } 64 65 // ToDB exports a UnitConfig to a serialized format. 66 func (cfg *UnitConfig) ToDB() ([]byte, error) { 67 return json.Marshal(cfg) 68 } 69 70 // ExternalWikiConfig describes external wiki config 71 type ExternalWikiConfig struct { 72 ExternalWikiURL string 73 } 74 75 // FromDB fills up a ExternalWikiConfig from serialized format. 76 func (cfg *ExternalWikiConfig) FromDB(bs []byte) error { 77 return json.UnmarshalHandleDoubleEncode(bs, &cfg) 78 } 79 80 // ToDB exports a ExternalWikiConfig to a serialized format. 81 func (cfg *ExternalWikiConfig) ToDB() ([]byte, error) { 82 return json.Marshal(cfg) 83 } 84 85 // ExternalTrackerConfig describes external tracker config 86 type ExternalTrackerConfig struct { 87 ExternalTrackerURL string 88 ExternalTrackerFormat string 89 ExternalTrackerStyle string 90 ExternalTrackerRegexpPattern string 91 } 92 93 // FromDB fills up a ExternalTrackerConfig from serialized format. 94 func (cfg *ExternalTrackerConfig) FromDB(bs []byte) error { 95 return json.UnmarshalHandleDoubleEncode(bs, &cfg) 96 } 97 98 // ToDB exports a ExternalTrackerConfig to a serialized format. 99 func (cfg *ExternalTrackerConfig) ToDB() ([]byte, error) { 100 return json.Marshal(cfg) 101 } 102 103 // IssuesConfig describes issues config 104 type IssuesConfig struct { 105 EnableTimetracker bool 106 AllowOnlyContributorsToTrackTime bool 107 EnableDependencies bool 108 } 109 110 // FromDB fills up a IssuesConfig from serialized format. 111 func (cfg *IssuesConfig) FromDB(bs []byte) error { 112 return json.UnmarshalHandleDoubleEncode(bs, &cfg) 113 } 114 115 // ToDB exports a IssuesConfig to a serialized format. 116 func (cfg *IssuesConfig) ToDB() ([]byte, error) { 117 return json.Marshal(cfg) 118 } 119 120 // PullRequestsConfig describes pull requests config 121 type PullRequestsConfig struct { 122 IgnoreWhitespaceConflicts bool 123 AllowMerge bool 124 AllowRebase bool 125 AllowRebaseMerge bool 126 AllowSquash bool 127 AllowFastForwardOnly bool 128 AllowManualMerge bool 129 AutodetectManualMerge bool 130 AllowRebaseUpdate bool 131 DefaultDeleteBranchAfterMerge bool 132 DefaultMergeStyle MergeStyle 133 DefaultAllowMaintainerEdit bool 134 } 135 136 // FromDB fills up a PullRequestsConfig from serialized format. 137 func (cfg *PullRequestsConfig) FromDB(bs []byte) error { 138 // AllowRebaseUpdate = true as default for existing PullRequestConfig in DB 139 cfg.AllowRebaseUpdate = true 140 return json.UnmarshalHandleDoubleEncode(bs, &cfg) 141 } 142 143 // ToDB exports a PullRequestsConfig to a serialized format. 144 func (cfg *PullRequestsConfig) ToDB() ([]byte, error) { 145 return json.Marshal(cfg) 146 } 147 148 // IsMergeStyleAllowed returns if merge style is allowed 149 func (cfg *PullRequestsConfig) IsMergeStyleAllowed(mergeStyle MergeStyle) bool { 150 return mergeStyle == MergeStyleMerge && cfg.AllowMerge || 151 mergeStyle == MergeStyleRebase && cfg.AllowRebase || 152 mergeStyle == MergeStyleRebaseMerge && cfg.AllowRebaseMerge || 153 mergeStyle == MergeStyleSquash && cfg.AllowSquash || 154 mergeStyle == MergeStyleFastForwardOnly && cfg.AllowFastForwardOnly || 155 mergeStyle == MergeStyleManuallyMerged && cfg.AllowManualMerge 156 } 157 158 // GetDefaultMergeStyle returns the default merge style for this pull request 159 func (cfg *PullRequestsConfig) GetDefaultMergeStyle() MergeStyle { 160 if len(cfg.DefaultMergeStyle) != 0 { 161 return cfg.DefaultMergeStyle 162 } 163 164 if setting.Repository.PullRequest.DefaultMergeStyle != "" { 165 return MergeStyle(setting.Repository.PullRequest.DefaultMergeStyle) 166 } 167 168 return MergeStyleMerge 169 } 170 171 type ActionsConfig struct { 172 DisabledWorkflows []string 173 } 174 175 func (cfg *ActionsConfig) EnableWorkflow(file string) { 176 cfg.DisabledWorkflows = util.SliceRemoveAll(cfg.DisabledWorkflows, file) 177 } 178 179 func (cfg *ActionsConfig) ToString() string { 180 return strings.Join(cfg.DisabledWorkflows, ",") 181 } 182 183 func (cfg *ActionsConfig) IsWorkflowDisabled(file string) bool { 184 return slices.Contains(cfg.DisabledWorkflows, file) 185 } 186 187 func (cfg *ActionsConfig) DisableWorkflow(file string) { 188 for _, workflow := range cfg.DisabledWorkflows { 189 if file == workflow { 190 return 191 } 192 } 193 194 cfg.DisabledWorkflows = append(cfg.DisabledWorkflows, file) 195 } 196 197 // FromDB fills up a ActionsConfig from serialized format. 198 func (cfg *ActionsConfig) FromDB(bs []byte) error { 199 return json.UnmarshalHandleDoubleEncode(bs, &cfg) 200 } 201 202 // ToDB exports a ActionsConfig to a serialized format. 203 func (cfg *ActionsConfig) ToDB() ([]byte, error) { 204 return json.Marshal(cfg) 205 } 206 207 // ProjectsMode represents the projects enabled for a repository 208 type ProjectsMode string 209 210 const ( 211 // ProjectsModeRepo allows only repo-level projects 212 ProjectsModeRepo ProjectsMode = "repo" 213 // ProjectsModeOwner allows only owner-level projects 214 ProjectsModeOwner ProjectsMode = "owner" 215 // ProjectsModeAll allows both kinds of projects 216 ProjectsModeAll ProjectsMode = "all" 217 // ProjectsModeNone doesn't allow projects 218 ProjectsModeNone ProjectsMode = "none" 219 ) 220 221 // ProjectsConfig describes projects config 222 type ProjectsConfig struct { 223 ProjectsMode ProjectsMode 224 } 225 226 // FromDB fills up a ProjectsConfig from serialized format. 227 func (cfg *ProjectsConfig) FromDB(bs []byte) error { 228 return json.UnmarshalHandleDoubleEncode(bs, &cfg) 229 } 230 231 // ToDB exports a ProjectsConfig to a serialized format. 232 func (cfg *ProjectsConfig) ToDB() ([]byte, error) { 233 return json.Marshal(cfg) 234 } 235 236 func (cfg *ProjectsConfig) GetProjectsMode() ProjectsMode { 237 if cfg.ProjectsMode != "" { 238 return cfg.ProjectsMode 239 } 240 241 return ProjectsModeAll 242 } 243 244 func (cfg *ProjectsConfig) IsProjectsAllowed(m ProjectsMode) bool { 245 projectsMode := cfg.GetProjectsMode() 246 247 if m == ProjectsModeNone { 248 return true 249 } 250 251 return projectsMode == m || projectsMode == ProjectsModeAll 252 } 253 254 // BeforeSet is invoked from XORM before setting the value of a field of this object. 255 func (r *RepoUnit) BeforeSet(colName string, val xorm.Cell) { 256 switch colName { 257 case "type": 258 switch unit.Type(db.Cell2Int64(val)) { 259 case unit.TypeExternalWiki: 260 r.Config = new(ExternalWikiConfig) 261 case unit.TypeExternalTracker: 262 r.Config = new(ExternalTrackerConfig) 263 case unit.TypePullRequests: 264 r.Config = new(PullRequestsConfig) 265 case unit.TypeIssues: 266 r.Config = new(IssuesConfig) 267 case unit.TypeActions: 268 r.Config = new(ActionsConfig) 269 case unit.TypeProjects: 270 r.Config = new(ProjectsConfig) 271 case unit.TypeCode, unit.TypeReleases, unit.TypeWiki, unit.TypePackages: 272 fallthrough 273 default: 274 r.Config = new(UnitConfig) 275 } 276 } 277 } 278 279 // Unit returns Unit 280 func (r *RepoUnit) Unit() unit.Unit { 281 return unit.Units[r.Type] 282 } 283 284 // CodeConfig returns config for unit.TypeCode 285 func (r *RepoUnit) CodeConfig() *UnitConfig { 286 return r.Config.(*UnitConfig) 287 } 288 289 // PullRequestsConfig returns config for unit.TypePullRequests 290 func (r *RepoUnit) PullRequestsConfig() *PullRequestsConfig { 291 return r.Config.(*PullRequestsConfig) 292 } 293 294 // ReleasesConfig returns config for unit.TypeReleases 295 func (r *RepoUnit) ReleasesConfig() *UnitConfig { 296 return r.Config.(*UnitConfig) 297 } 298 299 // ExternalWikiConfig returns config for unit.TypeExternalWiki 300 func (r *RepoUnit) ExternalWikiConfig() *ExternalWikiConfig { 301 return r.Config.(*ExternalWikiConfig) 302 } 303 304 // IssuesConfig returns config for unit.TypeIssues 305 func (r *RepoUnit) IssuesConfig() *IssuesConfig { 306 return r.Config.(*IssuesConfig) 307 } 308 309 // ExternalTrackerConfig returns config for unit.TypeExternalTracker 310 func (r *RepoUnit) ExternalTrackerConfig() *ExternalTrackerConfig { 311 return r.Config.(*ExternalTrackerConfig) 312 } 313 314 // ActionsConfig returns config for unit.ActionsConfig 315 func (r *RepoUnit) ActionsConfig() *ActionsConfig { 316 return r.Config.(*ActionsConfig) 317 } 318 319 // ProjectsConfig returns config for unit.ProjectsConfig 320 func (r *RepoUnit) ProjectsConfig() *ProjectsConfig { 321 return r.Config.(*ProjectsConfig) 322 } 323 324 func getUnitsByRepoID(ctx context.Context, repoID int64) (units []*RepoUnit, err error) { 325 var tmpUnits []*RepoUnit 326 if err := db.GetEngine(ctx).Where("repo_id = ?", repoID).Find(&tmpUnits); err != nil { 327 return nil, err 328 } 329 330 for _, u := range tmpUnits { 331 if !u.Type.UnitGlobalDisabled() { 332 units = append(units, u) 333 } 334 } 335 336 return units, nil 337 } 338 339 // UpdateRepoUnit updates the provided repo unit 340 func UpdateRepoUnit(ctx context.Context, unit *RepoUnit) error { 341 _, err := db.GetEngine(ctx).ID(unit.ID).Update(unit) 342 return err 343 }