You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

repo_unit.go 9.6KB

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