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.

consistency.go 9.2KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269
  1. // Copyright 2017 The Gitea Authors. All rights reserved.
  2. // Use of this source code is governed by a MIT-style
  3. // license that can be found in the LICENSE file.
  4. package models
  5. import (
  6. admin_model "code.gitea.io/gitea/models/admin"
  7. "code.gitea.io/gitea/models/db"
  8. repo_model "code.gitea.io/gitea/models/repo"
  9. user_model "code.gitea.io/gitea/models/user"
  10. "code.gitea.io/gitea/modules/setting"
  11. "xorm.io/builder"
  12. )
  13. // CountOrphanedLabels return count of labels witch are broken and not accessible via ui anymore
  14. func CountOrphanedLabels() (int64, error) {
  15. noref, err := db.GetEngine(db.DefaultContext).Table("label").Where("repo_id=? AND org_id=?", 0, 0).Count("label.id")
  16. if err != nil {
  17. return 0, err
  18. }
  19. norepo, err := db.GetEngine(db.DefaultContext).Table("label").
  20. Where(builder.And(
  21. builder.Gt{"repo_id": 0},
  22. builder.NotIn("repo_id", builder.Select("id").From("repository")),
  23. )).
  24. Count()
  25. if err != nil {
  26. return 0, err
  27. }
  28. noorg, err := db.GetEngine(db.DefaultContext).Table("label").
  29. Where(builder.And(
  30. builder.Gt{"org_id": 0},
  31. builder.NotIn("org_id", builder.Select("id").From("user")),
  32. )).
  33. Count()
  34. if err != nil {
  35. return 0, err
  36. }
  37. return noref + norepo + noorg, nil
  38. }
  39. // DeleteOrphanedLabels delete labels witch are broken and not accessible via ui anymore
  40. func DeleteOrphanedLabels() error {
  41. // delete labels with no reference
  42. if _, err := db.GetEngine(db.DefaultContext).Table("label").Where("repo_id=? AND org_id=?", 0, 0).Delete(new(Label)); err != nil {
  43. return err
  44. }
  45. // delete labels with none existing repos
  46. if _, err := db.GetEngine(db.DefaultContext).
  47. Where(builder.And(
  48. builder.Gt{"repo_id": 0},
  49. builder.NotIn("repo_id", builder.Select("id").From("repository")),
  50. )).
  51. Delete(Label{}); err != nil {
  52. return err
  53. }
  54. // delete labels with none existing orgs
  55. if _, err := db.GetEngine(db.DefaultContext).
  56. Where(builder.And(
  57. builder.Gt{"org_id": 0},
  58. builder.NotIn("org_id", builder.Select("id").From("user")),
  59. )).
  60. Delete(Label{}); err != nil {
  61. return err
  62. }
  63. return nil
  64. }
  65. // CountOrphanedIssueLabels return count of IssueLabels witch have no label behind anymore
  66. func CountOrphanedIssueLabels() (int64, error) {
  67. return db.GetEngine(db.DefaultContext).Table("issue_label").
  68. NotIn("label_id", builder.Select("id").From("label")).
  69. Count()
  70. }
  71. // DeleteOrphanedIssueLabels delete IssueLabels witch have no label behind anymore
  72. func DeleteOrphanedIssueLabels() error {
  73. _, err := db.GetEngine(db.DefaultContext).
  74. NotIn("label_id", builder.Select("id").From("label")).
  75. Delete(IssueLabel{})
  76. return err
  77. }
  78. // CountOrphanedIssues count issues without a repo
  79. func CountOrphanedIssues() (int64, error) {
  80. return db.GetEngine(db.DefaultContext).Table("issue").
  81. Join("LEFT", "repository", "issue.repo_id=repository.id").
  82. Where(builder.IsNull{"repository.id"}).
  83. Count("id")
  84. }
  85. // DeleteOrphanedIssues delete issues without a repo
  86. func DeleteOrphanedIssues() error {
  87. ctx, committer, err := db.TxContext()
  88. if err != nil {
  89. return err
  90. }
  91. defer committer.Close()
  92. var ids []int64
  93. if err := db.GetEngine(ctx).Table("issue").Distinct("issue.repo_id").
  94. Join("LEFT", "repository", "issue.repo_id=repository.id").
  95. Where(builder.IsNull{"repository.id"}).GroupBy("issue.repo_id").
  96. Find(&ids); err != nil {
  97. return err
  98. }
  99. var attachmentPaths []string
  100. for i := range ids {
  101. paths, err := deleteIssuesByRepoID(ctx, ids[i])
  102. if err != nil {
  103. return err
  104. }
  105. attachmentPaths = append(attachmentPaths, paths...)
  106. }
  107. if err := committer.Commit(); err != nil {
  108. return err
  109. }
  110. committer.Close()
  111. // Remove issue attachment files.
  112. for i := range attachmentPaths {
  113. admin_model.RemoveAllWithNotice(db.DefaultContext, "Delete issue attachment", attachmentPaths[i])
  114. }
  115. return nil
  116. }
  117. // CountOrphanedObjects count subjects with have no existing refobject anymore
  118. func CountOrphanedObjects(subject, refobject, joinCond string) (int64, error) {
  119. return db.GetEngine(db.DefaultContext).Table("`"+subject+"`").
  120. Join("LEFT", "`"+refobject+"`", joinCond).
  121. Where(builder.IsNull{"`" + refobject + "`.id"}).
  122. Count("id")
  123. }
  124. // DeleteOrphanedObjects delete subjects with have no existing refobject anymore
  125. func DeleteOrphanedObjects(subject, refobject, joinCond string) error {
  126. subQuery := builder.Select("`"+subject+"`.id").
  127. From("`"+subject+"`").
  128. Join("LEFT", "`"+refobject+"`", joinCond).
  129. Where(builder.IsNull{"`" + refobject + "`.id"})
  130. sql, args, err := builder.Delete(builder.In("id", subQuery)).From("`" + subject + "`").ToSQL()
  131. if err != nil {
  132. return err
  133. }
  134. _, err = db.GetEngine(db.DefaultContext).Exec(append([]interface{}{sql}, args...)...)
  135. return err
  136. }
  137. // CountNullArchivedRepository counts the number of repositories with is_archived is null
  138. func CountNullArchivedRepository() (int64, error) {
  139. return db.GetEngine(db.DefaultContext).Where(builder.IsNull{"is_archived"}).Count(new(repo_model.Repository))
  140. }
  141. // FixNullArchivedRepository sets is_archived to false where it is null
  142. func FixNullArchivedRepository() (int64, error) {
  143. return db.GetEngine(db.DefaultContext).Where(builder.IsNull{"is_archived"}).Cols("is_archived").NoAutoTime().Update(&repo_model.Repository{
  144. IsArchived: false,
  145. })
  146. }
  147. // CountWrongUserType count OrgUser who have wrong type
  148. func CountWrongUserType() (int64, error) {
  149. return db.GetEngine(db.DefaultContext).Where(builder.Eq{"type": 0}.And(builder.Neq{"num_teams": 0})).Count(new(user_model.User))
  150. }
  151. // FixWrongUserType fix OrgUser who have wrong type
  152. func FixWrongUserType() (int64, error) {
  153. return db.GetEngine(db.DefaultContext).Where(builder.Eq{"type": 0}.And(builder.Neq{"num_teams": 0})).Cols("type").NoAutoTime().Update(&user_model.User{Type: 1})
  154. }
  155. // CountCommentTypeLabelWithEmptyLabel count label comments with empty label
  156. func CountCommentTypeLabelWithEmptyLabel() (int64, error) {
  157. return db.GetEngine(db.DefaultContext).Where(builder.Eq{"type": CommentTypeLabel, "label_id": 0}).Count(new(Comment))
  158. }
  159. // FixCommentTypeLabelWithEmptyLabel count label comments with empty label
  160. func FixCommentTypeLabelWithEmptyLabel() (int64, error) {
  161. return db.GetEngine(db.DefaultContext).Where(builder.Eq{"type": CommentTypeLabel, "label_id": 0}).Delete(new(Comment))
  162. }
  163. // CountCommentTypeLabelWithOutsideLabels count label comments with outside label
  164. func CountCommentTypeLabelWithOutsideLabels() (int64, error) {
  165. return db.GetEngine(db.DefaultContext).Where("comment.type = ? AND ((label.org_id = 0 AND issue.repo_id != label.repo_id) OR (label.repo_id = 0 AND label.org_id != repository.owner_id))", CommentTypeLabel).
  166. Table("comment").
  167. Join("inner", "label", "label.id = comment.label_id").
  168. Join("inner", "issue", "issue.id = comment.issue_id ").
  169. Join("inner", "repository", "issue.repo_id = repository.id").
  170. Count(new(Comment))
  171. }
  172. // FixCommentTypeLabelWithOutsideLabels count label comments with outside label
  173. func FixCommentTypeLabelWithOutsideLabels() (int64, error) {
  174. res, err := db.GetEngine(db.DefaultContext).Exec(`DELETE FROM comment WHERE comment.id IN (
  175. SELECT il_too.id FROM (
  176. SELECT com.id
  177. FROM comment AS com
  178. INNER JOIN label ON com.label_id = label.id
  179. INNER JOIN issue on issue.id = com.issue_id
  180. INNER JOIN repository ON issue.repo_id = repository.id
  181. WHERE
  182. com.type = ? AND ((label.org_id = 0 AND issue.repo_id != label.repo_id) OR (label.repo_id = 0 AND label.org_id != repository.owner_id))
  183. ) AS il_too)`, CommentTypeLabel)
  184. if err != nil {
  185. return 0, err
  186. }
  187. return res.RowsAffected()
  188. }
  189. // CountIssueLabelWithOutsideLabels count label comments with outside label
  190. func CountIssueLabelWithOutsideLabels() (int64, error) {
  191. return db.GetEngine(db.DefaultContext).Where(builder.Expr("(label.org_id = 0 AND issue.repo_id != label.repo_id) OR (label.repo_id = 0 AND label.org_id != repository.owner_id)")).
  192. Table("issue_label").
  193. Join("inner", "label", "issue_label.label_id = label.id ").
  194. Join("inner", "issue", "issue.id = issue_label.issue_id ").
  195. Join("inner", "repository", "issue.repo_id = repository.id").
  196. Count(new(IssueLabel))
  197. }
  198. // FixIssueLabelWithOutsideLabels fix label comments with outside label
  199. func FixIssueLabelWithOutsideLabels() (int64, error) {
  200. res, err := db.GetEngine(db.DefaultContext).Exec(`DELETE FROM issue_label WHERE issue_label.id IN (
  201. SELECT il_too.id FROM (
  202. SELECT il_too_too.id
  203. FROM issue_label AS il_too_too
  204. INNER JOIN label ON il_too_too.label_id = label.id
  205. INNER JOIN issue on issue.id = il_too_too.issue_id
  206. INNER JOIN repository on repository.id = issue.repo_id
  207. WHERE
  208. (label.org_id = 0 AND issue.repo_id != label.repo_id) OR (label.repo_id = 0 AND label.org_id != repository.owner_id)
  209. ) AS il_too )`)
  210. if err != nil {
  211. return 0, err
  212. }
  213. return res.RowsAffected()
  214. }
  215. // CountActionCreatedUnixString count actions where created_unix is an empty string
  216. func CountActionCreatedUnixString() (int64, error) {
  217. if setting.Database.UseSQLite3 {
  218. return db.GetEngine(db.DefaultContext).Where(`created_unix = ""`).Count(new(Action))
  219. }
  220. return 0, nil
  221. }
  222. // FixActionCreatedUnixString set created_unix to zero if it is an empty string
  223. func FixActionCreatedUnixString() (int64, error) {
  224. if setting.Database.UseSQLite3 {
  225. res, err := db.GetEngine(db.DefaultContext).Exec(`UPDATE action SET created_unix = 0 WHERE created_unix = ""`)
  226. if err != nil {
  227. return 0, err
  228. }
  229. return res.RowsAffected()
  230. }
  231. return 0, nil
  232. }