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 7.5KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265
  1. // Copyright 2017 The Gitea Authors. All rights reserved.
  2. // SPDX-License-Identifier: MIT
  3. package repo
  4. import (
  5. "context"
  6. "fmt"
  7. "code.gitea.io/gitea/models/db"
  8. "code.gitea.io/gitea/models/unit"
  9. "code.gitea.io/gitea/modules/json"
  10. "code.gitea.io/gitea/modules/setting"
  11. "code.gitea.io/gitea/modules/timeutil"
  12. "code.gitea.io/gitea/modules/util"
  13. "xorm.io/xorm"
  14. "xorm.io/xorm/convert"
  15. )
  16. // ErrUnitTypeNotExist represents a "UnitTypeNotExist" kind of error.
  17. type ErrUnitTypeNotExist struct {
  18. UT unit.Type
  19. }
  20. // IsErrUnitTypeNotExist checks if an error is a ErrUnitNotExist.
  21. func IsErrUnitTypeNotExist(err error) bool {
  22. _, ok := err.(ErrUnitTypeNotExist)
  23. return ok
  24. }
  25. func (err ErrUnitTypeNotExist) Error() string {
  26. return fmt.Sprintf("Unit type does not exist: %s", err.UT.String())
  27. }
  28. func (err ErrUnitTypeNotExist) Unwrap() error {
  29. return util.ErrNotExist
  30. }
  31. // RepoUnit describes all units of a repository
  32. type RepoUnit struct { //revive:disable-line:exported
  33. ID int64
  34. RepoID int64 `xorm:"INDEX(s)"`
  35. Type unit.Type `xorm:"INDEX(s)"`
  36. Config convert.Conversion `xorm:"TEXT"`
  37. CreatedUnix timeutil.TimeStamp `xorm:"INDEX CREATED"`
  38. }
  39. func init() {
  40. db.RegisterModel(new(RepoUnit))
  41. }
  42. // UnitConfig describes common unit config
  43. type UnitConfig struct{}
  44. // FromDB fills up a UnitConfig from serialized format.
  45. func (cfg *UnitConfig) FromDB(bs []byte) error {
  46. return json.UnmarshalHandleDoubleEncode(bs, &cfg)
  47. }
  48. // ToDB exports a UnitConfig to a serialized format.
  49. func (cfg *UnitConfig) ToDB() ([]byte, error) {
  50. return json.Marshal(cfg)
  51. }
  52. // ExternalWikiConfig describes external wiki config
  53. type ExternalWikiConfig struct {
  54. ExternalWikiURL string
  55. }
  56. // FromDB fills up a ExternalWikiConfig from serialized format.
  57. func (cfg *ExternalWikiConfig) FromDB(bs []byte) error {
  58. return json.UnmarshalHandleDoubleEncode(bs, &cfg)
  59. }
  60. // ToDB exports a ExternalWikiConfig to a serialized format.
  61. func (cfg *ExternalWikiConfig) ToDB() ([]byte, error) {
  62. return json.Marshal(cfg)
  63. }
  64. // ExternalTrackerConfig describes external tracker config
  65. type ExternalTrackerConfig struct {
  66. ExternalTrackerURL string
  67. ExternalTrackerFormat string
  68. ExternalTrackerStyle string
  69. ExternalTrackerRegexpPattern string
  70. }
  71. // FromDB fills up a ExternalTrackerConfig from serialized format.
  72. func (cfg *ExternalTrackerConfig) FromDB(bs []byte) error {
  73. return json.UnmarshalHandleDoubleEncode(bs, &cfg)
  74. }
  75. // ToDB exports a ExternalTrackerConfig to a serialized format.
  76. func (cfg *ExternalTrackerConfig) ToDB() ([]byte, error) {
  77. return json.Marshal(cfg)
  78. }
  79. // IssuesConfig describes issues config
  80. type IssuesConfig struct {
  81. EnableTimetracker bool
  82. AllowOnlyContributorsToTrackTime bool
  83. EnableDependencies bool
  84. }
  85. // FromDB fills up a IssuesConfig from serialized format.
  86. func (cfg *IssuesConfig) FromDB(bs []byte) error {
  87. return json.UnmarshalHandleDoubleEncode(bs, &cfg)
  88. }
  89. // ToDB exports a IssuesConfig to a serialized format.
  90. func (cfg *IssuesConfig) ToDB() ([]byte, error) {
  91. return json.Marshal(cfg)
  92. }
  93. // PullRequestsConfig describes pull requests config
  94. type PullRequestsConfig struct {
  95. IgnoreWhitespaceConflicts bool
  96. AllowMerge bool
  97. AllowRebase bool
  98. AllowRebaseMerge bool
  99. AllowSquash bool
  100. AllowManualMerge bool
  101. AutodetectManualMerge bool
  102. AllowRebaseUpdate bool
  103. DefaultDeleteBranchAfterMerge bool
  104. DefaultMergeStyle MergeStyle
  105. }
  106. // FromDB fills up a PullRequestsConfig from serialized format.
  107. func (cfg *PullRequestsConfig) FromDB(bs []byte) error {
  108. // AllowRebaseUpdate = true as default for existing PullRequestConfig in DB
  109. cfg.AllowRebaseUpdate = true
  110. return json.UnmarshalHandleDoubleEncode(bs, &cfg)
  111. }
  112. // ToDB exports a PullRequestsConfig to a serialized format.
  113. func (cfg *PullRequestsConfig) ToDB() ([]byte, error) {
  114. return json.Marshal(cfg)
  115. }
  116. // IsMergeStyleAllowed returns if merge style is allowed
  117. func (cfg *PullRequestsConfig) IsMergeStyleAllowed(mergeStyle MergeStyle) bool {
  118. return mergeStyle == MergeStyleMerge && cfg.AllowMerge ||
  119. mergeStyle == MergeStyleRebase && cfg.AllowRebase ||
  120. mergeStyle == MergeStyleRebaseMerge && cfg.AllowRebaseMerge ||
  121. mergeStyle == MergeStyleSquash && cfg.AllowSquash ||
  122. mergeStyle == MergeStyleManuallyMerged && cfg.AllowManualMerge
  123. }
  124. // GetDefaultMergeStyle returns the default merge style for this pull request
  125. func (cfg *PullRequestsConfig) GetDefaultMergeStyle() MergeStyle {
  126. if len(cfg.DefaultMergeStyle) != 0 {
  127. return cfg.DefaultMergeStyle
  128. }
  129. if setting.Repository.PullRequest.DefaultMergeStyle != "" {
  130. return MergeStyle(setting.Repository.PullRequest.DefaultMergeStyle)
  131. }
  132. return MergeStyleMerge
  133. }
  134. // BeforeSet is invoked from XORM before setting the value of a field of this object.
  135. func (r *RepoUnit) BeforeSet(colName string, val xorm.Cell) {
  136. switch colName {
  137. case "type":
  138. switch unit.Type(db.Cell2Int64(val)) {
  139. case unit.TypeExternalWiki:
  140. r.Config = new(ExternalWikiConfig)
  141. case unit.TypeExternalTracker:
  142. r.Config = new(ExternalTrackerConfig)
  143. case unit.TypePullRequests:
  144. r.Config = new(PullRequestsConfig)
  145. case unit.TypeIssues:
  146. r.Config = new(IssuesConfig)
  147. case unit.TypeCode, unit.TypeReleases, unit.TypeWiki, unit.TypeProjects, unit.TypePackages, unit.TypeActions:
  148. fallthrough
  149. default:
  150. r.Config = new(UnitConfig)
  151. }
  152. }
  153. }
  154. // Unit returns Unit
  155. func (r *RepoUnit) Unit() unit.Unit {
  156. return unit.Units[r.Type]
  157. }
  158. // CodeConfig returns config for unit.TypeCode
  159. func (r *RepoUnit) CodeConfig() *UnitConfig {
  160. return r.Config.(*UnitConfig)
  161. }
  162. // PullRequestsConfig returns config for unit.TypePullRequests
  163. func (r *RepoUnit) PullRequestsConfig() *PullRequestsConfig {
  164. return r.Config.(*PullRequestsConfig)
  165. }
  166. // ReleasesConfig returns config for unit.TypeReleases
  167. func (r *RepoUnit) ReleasesConfig() *UnitConfig {
  168. return r.Config.(*UnitConfig)
  169. }
  170. // ExternalWikiConfig returns config for unit.TypeExternalWiki
  171. func (r *RepoUnit) ExternalWikiConfig() *ExternalWikiConfig {
  172. return r.Config.(*ExternalWikiConfig)
  173. }
  174. // IssuesConfig returns config for unit.TypeIssues
  175. func (r *RepoUnit) IssuesConfig() *IssuesConfig {
  176. return r.Config.(*IssuesConfig)
  177. }
  178. // ExternalTrackerConfig returns config for unit.TypeExternalTracker
  179. func (r *RepoUnit) ExternalTrackerConfig() *ExternalTrackerConfig {
  180. return r.Config.(*ExternalTrackerConfig)
  181. }
  182. func getUnitsByRepoID(ctx context.Context, repoID int64) (units []*RepoUnit, err error) {
  183. var tmpUnits []*RepoUnit
  184. if err := db.GetEngine(ctx).Where("repo_id = ?", repoID).Find(&tmpUnits); err != nil {
  185. return nil, err
  186. }
  187. for _, u := range tmpUnits {
  188. if !u.Type.UnitGlobalDisabled() {
  189. units = append(units, u)
  190. }
  191. }
  192. return units, nil
  193. }
  194. // UpdateRepoUnit updates the provided repo unit
  195. func UpdateRepoUnit(unit *RepoUnit) error {
  196. _, err := db.GetEngine(db.DefaultContext).ID(unit.ID).Update(unit)
  197. return err
  198. }
  199. // UpdateRepositoryUnits updates a repository's units
  200. func UpdateRepositoryUnits(repo *Repository, units []RepoUnit, deleteUnitTypes []unit.Type) (err error) {
  201. ctx, committer, err := db.TxContext(db.DefaultContext)
  202. if err != nil {
  203. return err
  204. }
  205. defer committer.Close()
  206. // Delete existing settings of units before adding again
  207. for _, u := range units {
  208. deleteUnitTypes = append(deleteUnitTypes, u.Type)
  209. }
  210. if _, err = db.GetEngine(ctx).Where("repo_id = ?", repo.ID).In("type", deleteUnitTypes).Delete(new(RepoUnit)); err != nil {
  211. return err
  212. }
  213. if len(units) > 0 {
  214. if err = db.Insert(ctx, units); err != nil {
  215. return err
  216. }
  217. }
  218. return committer.Commit()
  219. }