@@ -13,6 +13,7 @@ import (
1313 "strconv"
1414 "strings"
1515
16+ admin_model "code.gitea.io/gitea/models/admin"
1617 "code.gitea.io/gitea/models/db"
1718 "code.gitea.io/gitea/models/issues"
1819 "code.gitea.io/gitea/models/perm"
@@ -23,6 +24,7 @@ import (
2324 "code.gitea.io/gitea/modules/git"
2425 "code.gitea.io/gitea/modules/log"
2526 "code.gitea.io/gitea/modules/references"
27+ "code.gitea.io/gitea/modules/storage"
2628 api "code.gitea.io/gitea/modules/structs"
2729 "code.gitea.io/gitea/modules/timeutil"
2830 "code.gitea.io/gitea/modules/util"
@@ -1991,6 +1993,118 @@ func UpdateIssueDeadline(issue *Issue, deadlineUnix timeutil.TimeStamp, doer *us
19911993 return committer .Commit ()
19921994}
19931995
1996+ // DeleteIssue deletes the issue
1997+ func DeleteIssue (issue * Issue ) error {
1998+ ctx , committer , err := db .TxContext ()
1999+ if err != nil {
2000+ return err
2001+ }
2002+ defer committer .Close ()
2003+
2004+ if err := deleteIssue (ctx , issue ); err != nil {
2005+ return err
2006+ }
2007+
2008+ return committer .Commit ()
2009+ }
2010+
2011+ func deleteInIssue (e db.Engine , issueID int64 , beans ... interface {}) error {
2012+ for _ , bean := range beans {
2013+ if _ , err := e .In ("issue_id" , issueID ).Delete (bean ); err != nil {
2014+ return err
2015+ }
2016+ }
2017+ return nil
2018+ }
2019+
2020+ func deleteIssue (ctx context.Context , issue * Issue ) error {
2021+ e := db .GetEngine (ctx )
2022+ if _ , err := e .ID (issue .ID ).NoAutoCondition ().Delete (issue ); err != nil {
2023+ return err
2024+ }
2025+
2026+ if issue .IsPull {
2027+ if _ , err := e .ID (issue .RepoID ).Decr ("num_pulls" ).Update (new (repo_model.Repository )); err != nil {
2028+ return err
2029+ }
2030+ if issue .IsClosed {
2031+ if _ , err := e .ID (issue .RepoID ).Decr ("num_closed_pulls" ).Update (new (repo_model.Repository )); err != nil {
2032+ return err
2033+ }
2034+ }
2035+ } else {
2036+ if _ , err := e .ID (issue .RepoID ).Decr ("num_issues" ).Update (new (repo_model.Repository )); err != nil {
2037+ return err
2038+ }
2039+ if issue .IsClosed {
2040+ if _ , err := e .ID (issue .RepoID ).Decr ("num_closed_issues" ).Update (new (repo_model.Repository )); err != nil {
2041+ return err
2042+ }
2043+ }
2044+ }
2045+
2046+ // delete actions assigned to this issue
2047+ var comments []int64
2048+ if err := e .Table (new (Comment )).In ("issue_id" , issue .ID ).Cols ("id" ).Find (& comments ); err != nil {
2049+ return err
2050+ }
2051+ for i := range comments {
2052+ if _ , err := e .Where ("comment_id = ?" , comments [i ]).Delete (& Action {}); err != nil {
2053+ return err
2054+ }
2055+ }
2056+ if _ , err := e .Table ("action" ).Where ("repo_id = ?" , issue .RepoID ).In ("op_type" , ActionCreateIssue , ActionCreatePullRequest ).
2057+ Where ("content LIKE ?" , strconv .FormatInt (issue .ID , 10 )+ "|%" ).Delete (& Action {}); err != nil {
2058+ return err
2059+ }
2060+
2061+ // find attachments related to this issue and remove them
2062+ var attachments []* repo_model.Attachment
2063+ if err := e .In ("issue_id" , issue .ID ).Find (& attachments ); err != nil {
2064+ return err
2065+ }
2066+
2067+ for i := range attachments {
2068+ admin_model .RemoveStorageWithNotice (ctx , storage .Attachments , "Delete issue attachment" , attachments [i ].RelativePath ())
2069+ }
2070+
2071+ // delete all database data still assigned to this issue
2072+ if err := deleteInIssue (e , issue .ID ,
2073+ & issues.ContentHistory {},
2074+ & Comment {},
2075+ & IssueLabel {},
2076+ & IssueDependency {},
2077+ & IssueAssignees {},
2078+ & IssueUser {},
2079+ & Reaction {},
2080+ & IssueWatch {},
2081+ & Stopwatch {},
2082+ & TrackedTime {},
2083+ & ProjectIssue {},
2084+ & repo_model.Attachment {},
2085+ & PullRequest {},
2086+ ); err != nil {
2087+ return err
2088+ }
2089+
2090+ // References to this issue in other issues
2091+ if _ , err := e .In ("ref_issue_id" , issue .ID ).Delete (& Comment {}); err != nil {
2092+ return err
2093+ }
2094+
2095+ // Delete dependencies for issues in other repositories
2096+ if _ , err := e .In ("dependency_id" , issue .ID ).Delete (& IssueDependency {}); err != nil {
2097+ return err
2098+ }
2099+
2100+ // delete from dependent issues
2101+ if _ , err := e .In ("dependent_issue_id" , issue .ID ).Delete (& Comment {}); err != nil {
2102+ return err
2103+ }
2104+
2105+ return nil
2106+ }
2107+
19942108// DependencyInfo represents high level information about an issue which is a dependency of another issue.
19952109type DependencyInfo struct {
19962110 Issue `xorm:"extends"`
0 commit comments