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.

issue_dependency.go 3.5KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131
  1. // Copyright 2018 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. "context"
  7. "code.gitea.io/gitea/models/db"
  8. user_model "code.gitea.io/gitea/models/user"
  9. "code.gitea.io/gitea/modules/timeutil"
  10. )
  11. // IssueDependency represents an issue dependency
  12. type IssueDependency struct {
  13. ID int64 `xorm:"pk autoincr"`
  14. UserID int64 `xorm:"NOT NULL"`
  15. IssueID int64 `xorm:"UNIQUE(issue_dependency) NOT NULL"`
  16. DependencyID int64 `xorm:"UNIQUE(issue_dependency) NOT NULL"`
  17. CreatedUnix timeutil.TimeStamp `xorm:"created"`
  18. UpdatedUnix timeutil.TimeStamp `xorm:"updated"`
  19. }
  20. func init() {
  21. db.RegisterModel(new(IssueDependency))
  22. }
  23. // DependencyType Defines Dependency Type Constants
  24. type DependencyType int
  25. // Define Dependency Types
  26. const (
  27. DependencyTypeBlockedBy DependencyType = iota
  28. DependencyTypeBlocking
  29. )
  30. // CreateIssueDependency creates a new dependency for an issue
  31. func CreateIssueDependency(user *user_model.User, issue, dep *Issue) error {
  32. ctx, committer, err := db.TxContext()
  33. if err != nil {
  34. return err
  35. }
  36. defer committer.Close()
  37. // Check if it aleready exists
  38. exists, err := issueDepExists(ctx, issue.ID, dep.ID)
  39. if err != nil {
  40. return err
  41. }
  42. if exists {
  43. return ErrDependencyExists{issue.ID, dep.ID}
  44. }
  45. // And if it would be circular
  46. circular, err := issueDepExists(ctx, dep.ID, issue.ID)
  47. if err != nil {
  48. return err
  49. }
  50. if circular {
  51. return ErrCircularDependency{issue.ID, dep.ID}
  52. }
  53. if err := db.Insert(ctx, &IssueDependency{
  54. UserID: user.ID,
  55. IssueID: issue.ID,
  56. DependencyID: dep.ID,
  57. }); err != nil {
  58. return err
  59. }
  60. // Add comment referencing the new dependency
  61. if err = createIssueDependencyComment(ctx, user, issue, dep, true); err != nil {
  62. return err
  63. }
  64. return committer.Commit()
  65. }
  66. // RemoveIssueDependency removes a dependency from an issue
  67. func RemoveIssueDependency(user *user_model.User, issue, dep *Issue, depType DependencyType) (err error) {
  68. ctx, committer, err := db.TxContext()
  69. if err != nil {
  70. return err
  71. }
  72. defer committer.Close()
  73. var issueDepToDelete IssueDependency
  74. switch depType {
  75. case DependencyTypeBlockedBy:
  76. issueDepToDelete = IssueDependency{IssueID: issue.ID, DependencyID: dep.ID}
  77. case DependencyTypeBlocking:
  78. issueDepToDelete = IssueDependency{IssueID: dep.ID, DependencyID: issue.ID}
  79. default:
  80. return ErrUnknownDependencyType{depType}
  81. }
  82. affected, err := db.GetEngine(ctx).Delete(&issueDepToDelete)
  83. if err != nil {
  84. return err
  85. }
  86. // If we deleted nothing, the dependency did not exist
  87. if affected <= 0 {
  88. return ErrDependencyNotExists{issue.ID, dep.ID}
  89. }
  90. // Add comment referencing the removed dependency
  91. if err = createIssueDependencyComment(ctx, user, issue, dep, false); err != nil {
  92. return err
  93. }
  94. return committer.Commit()
  95. }
  96. // Check if the dependency already exists
  97. func issueDepExists(ctx context.Context, issueID, depID int64) (bool, error) {
  98. return db.GetEngine(ctx).Where("(issue_id = ? AND dependency_id = ?)", issueID, depID).Exist(&IssueDependency{})
  99. }
  100. // IssueNoDependenciesLeft checks if issue can be closed
  101. func IssueNoDependenciesLeft(ctx context.Context, issue *Issue) (bool, error) {
  102. exists, err := db.GetEngine(ctx).
  103. Table("issue_dependency").
  104. Select("issue.*").
  105. Join("INNER", "issue", "issue.id = issue_dependency.dependency_id").
  106. Where("issue_dependency.issue_id = ?", issue.ID).
  107. And("issue.is_closed = ?", "0").
  108. Exist(&Issue{})
  109. return !exists, err
  110. }