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

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