Skip to content

Delete Labels & IssueLabels on Repo Delete too #15039

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 13 commits into from
Mar 19, 2021
17 changes: 17 additions & 0 deletions models/consistency.go
Original file line number Diff line number Diff line change
Expand Up @@ -224,6 +224,23 @@ func DeleteOrphanedLabels() error {
return nil
}

// CountOrphanedIssueLabels return count of IssueLabels witch have no label behind anymore
func CountOrphanedIssueLabels() (int64, error) {
return x.Table("issue_label").
Join("LEFT", "label", "issue_label.label_id = label.id").
Where(builder.IsNull{"label.id"}).Count()
}

// DeleteOrphanedIssueLabels delete IssueLabels witch have no label behind anymore
func DeleteOrphanedIssueLabels() error {
_, err := x.In("id", builder.Select("issue_label.id").From("issue_label").
Join("LEFT", "label", "issue_label.label_id = label.id").
Where(builder.IsNull{"label.id"})).
Delete(IssueLabel{})

return err
}

// CountOrphanedIssues count issues without a repo
func CountOrphanedIssues() (int64, error) {
return x.Table("issue").
Expand Down
12 changes: 12 additions & 0 deletions models/issue_label.go
Original file line number Diff line number Diff line change
Expand Up @@ -780,3 +780,15 @@ func DeleteIssueLabel(issue *Issue, label *Label, doer *User) (err error) {

return sess.Commit()
}

func deleteLabelsByRepoID(sess Engine, repoID int64) error {
deleteCond := builder.Select("id").From("label").Where(builder.Eq{"label.repo_id": repoID})

if _, err := sess.In("label_id", deleteCond).
Delete(&IssueLabel{}); err != nil {
return err
}

_, err := sess.Delete(&Label{RepoID: repoID})
return err
}
4 changes: 3 additions & 1 deletion models/migrations/migrations.go
Original file line number Diff line number Diff line change
Expand Up @@ -295,11 +295,13 @@ var migrations = []Migration{
// v173 -> v174
NewMigration("Add time_id column to Comment", addTimeIDCommentColumn),
// v174 -> v175
NewMigration("create repo transfer table", addRepoTransfer),
NewMigration("Create repo transfer table", addRepoTransfer),
// v175 -> v176
NewMigration("Fix Postgres ID Sequences broken by recreate-table", fixPostgresIDSequences),
// v176 -> v177
NewMigration("Remove invalid labels from comments", removeInvalidLabels),
// v177 -> v178
NewMigration("Delete orphaned IssueLabels", deleteOrphanedIssueLabels),
}

// GetCurrentDBVersion returns the current db version
Expand Down
14 changes: 13 additions & 1 deletion models/migrations/v174.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
package migrations

import (
"fmt"

"xorm.io/xorm"
)

Expand All @@ -19,5 +21,15 @@ func addRepoTransfer(x *xorm.Engine) error {
UpdatedUnix int64 `xorm:"INDEX NOT NULL updated"`
}

return x.Sync(new(RepoTransfer))
sess := x.NewSession()
defer sess.Close()
if err := sess.Begin(); err != nil {
return err
}

if err := sess.Sync2(new(RepoTransfer)); err != nil {
return fmt.Errorf("Sync2: %v", err)
}

return sess.Commit()
}
42 changes: 42 additions & 0 deletions models/migrations/v177.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
// Copyright 2021 The Gitea Authors. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.

package migrations

import (
"fmt"

"xorm.io/xorm"
)

func deleteOrphanedIssueLabels(x *xorm.Engine) error {
type IssueLabel struct {
ID int64 `xorm:"pk autoincr"`
IssueID int64 `xorm:"UNIQUE(s)"`
LabelID int64 `xorm:"UNIQUE(s)"`
}

sess := x.NewSession()
defer sess.Close()
if err := sess.Begin(); err != nil {
return err
}

if err := sess.Sync2(new(IssueLabel)); err != nil {
return fmt.Errorf("Sync2: %v", err)
}

if _, err := sess.Exec(`DELETE FROM issue_label WHERE issue_label.id IN (
SELECT ill.id FROM (
SELECT il.id
FROM issue_label AS il
LEFT JOIN label ON il.label_id = label.id
WHERE
label.id IS NULL
) AS ill)`); err != nil {
return err
}

return sess.Commit()
}
17 changes: 11 additions & 6 deletions models/repo.go
Original file line number Diff line number Diff line change
Expand Up @@ -1447,11 +1447,11 @@ func DeleteRepository(doer *User, uid, repoID int64) error {
releaseAttachments = append(releaseAttachments, attachments[i].RelativePath())
}

if _, err = sess.Exec("UPDATE `user` SET num_stars=num_stars-1 WHERE id IN (SELECT `uid` FROM `star` WHERE repo_id = ?)", repo.ID); err != nil {
if _, err := sess.Exec("UPDATE `user` SET num_stars=num_stars-1 WHERE id IN (SELECT `uid` FROM `star` WHERE repo_id = ?)", repo.ID); err != nil {
return err
}

if err = deleteBeans(sess,
if err := deleteBeans(sess,
&Access{RepoID: repo.ID},
&Action{RepoID: repo.ID},
&Watch{RepoID: repoID},
Expand All @@ -1475,28 +1475,33 @@ func DeleteRepository(doer *User, uid, repoID int64) error {
return fmt.Errorf("deleteBeans: %v", err)
}

// Delete Labels and related objects
if err := deleteLabelsByRepoID(sess, repoID); err != nil {
return err
}

// Delete Issues and related objects
var attachmentPaths []string
if attachmentPaths, err = deleteIssuesByRepoID(sess, repoID); err != nil {
return err
}

if _, err = sess.Where("repo_id = ?", repoID).Delete(new(RepoUnit)); err != nil {
if _, err := sess.Where("repo_id = ?", repoID).Delete(new(RepoUnit)); err != nil {
return err
}

if repo.IsFork {
if _, err = sess.Exec("UPDATE `repository` SET num_forks=num_forks-1 WHERE id=?", repo.ForkID); err != nil {
if _, err := sess.Exec("UPDATE `repository` SET num_forks=num_forks-1 WHERE id=?", repo.ForkID); err != nil {
return fmt.Errorf("decrease fork count: %v", err)
}
}

if _, err = sess.Exec("UPDATE `user` SET num_repos=num_repos-1 WHERE id=?", uid); err != nil {
if _, err := sess.Exec("UPDATE `user` SET num_repos=num_repos-1 WHERE id=?", uid); err != nil {
return err
}

if len(repo.Topics) > 0 {
if err = removeTopicsFromRepo(sess, repo.ID); err != nil {
if err := removeTopicsFromRepo(sess, repo.ID); err != nil {
return err
}
}
Expand Down
19 changes: 18 additions & 1 deletion modules/doctor/dbconsistency.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@ func checkDBConsistency(logger log.Logger, autofix bool) error {
logger.Critical("Error: %v whilst counting orphaned labels")
return err
}

if count > 0 {
if autofix {
if err = models.DeleteOrphanedLabels(); err != nil {
Expand All @@ -39,6 +38,24 @@ func checkDBConsistency(logger log.Logger, autofix bool) error {
}
}

// find IssueLabels without existing label
count, err = models.CountOrphanedIssueLabels()
if err != nil {
logger.Critical("Error: %v whilst counting orphaned issue_labels")
return err
}
if count > 0 {
if autofix {
if err = models.DeleteOrphanedIssueLabels(); err != nil {
logger.Critical("Error: %v whilst deleting orphaned issue_labels")
return err
}
logger.Info("%d issue_labels without existing label deleted", count)
} else {
logger.Warn("%d issue_labels without existing label", count)
}
}

// find issues without existing repository
count, err = models.CountOrphanedIssues()
if err != nil {
Expand Down