* Update topics repo count when deleting repository * Add migration to fix incorrect data * Optimize to use single update to recalculate valuestags/v1.10.5
NewMigration("Add columns to user and repository", addUserRepoMissingColumns), | NewMigration("Add columns to user and repository", addUserRepoMissingColumns), | ||||
// v125 -> v126 | // v125 -> v126 | ||||
NewMigration("Add some columns on review for migration", addReviewMigrateInfo), | NewMigration("Add some columns on review for migration", addReviewMigrateInfo), | ||||
// v126 -> v127 | |||||
NewMigration("Fix topic repository count", fixTopicRepositoryCount), | |||||
} | } | ||||
// Migrate database to current version | // Migrate database to current version |
// Copyright 2020 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 ( | |||||
"xorm.io/builder" | |||||
"xorm.io/xorm" | |||||
) | |||||
func fixTopicRepositoryCount(x *xorm.Engine) error { | |||||
_, err := x.Exec(builder.Delete(builder.NotIn("`repo_id`", builder.Select("`id`").From("`repository`"))).From("`repo_topic`")) | |||||
if err != nil { | |||||
return err | |||||
} | |||||
_, err = x.Exec(builder.Update( | |||||
builder.Eq{ | |||||
"`repo_count`": builder.Select("count(*)").From("`repo_topic`").Where(builder.Eq{ | |||||
"`repo_topic`.`topic_id`": builder.Expr("`topic`.`id`"), | |||||
}), | |||||
}).From("`topic`").Where(builder.Eq{"'1'": "1"})) | |||||
return err | |||||
} |
return err | return err | ||||
} | } | ||||
if len(repo.Topics) > 0 { | |||||
if err = removeTopicsFromRepo(sess, repo.ID); err != nil { | |||||
return err | |||||
} | |||||
} | |||||
// FIXME: Remove repository files should be executed after transaction succeed. | // FIXME: Remove repository files should be executed after transaction succeed. | ||||
repoPath := repo.RepoPath() | repoPath := repo.RepoPath() | ||||
removeAllWithNotice(sess, "Delete repository files", repoPath) | removeAllWithNotice(sess, "Delete repository files", repoPath) |
} | } | ||||
// removeTopicFromRepo remove a topic from a repo and decrements the topic repo count | // removeTopicFromRepo remove a topic from a repo and decrements the topic repo count | ||||
func removeTopicFromRepo(repoID int64, topic *Topic, e Engine) error { | |||||
func removeTopicFromRepo(e Engine, repoID int64, topic *Topic) error { | |||||
topic.RepoCount-- | topic.RepoCount-- | ||||
if _, err := e.ID(topic.ID).Cols("repo_count").Update(topic); err != nil { | if _, err := e.ID(topic.ID).Cols("repo_count").Update(topic); err != nil { | ||||
return err | return err | ||||
return nil | return nil | ||||
} | } | ||||
// removeTopicsFromRepo remove all topics from the repo and decrements respective topics repo count | |||||
func removeTopicsFromRepo(e Engine, repoID int64) error { | |||||
_, err := e.Where( | |||||
builder.In("id", | |||||
builder.Select("topic_id").From("repo_topic").Where(builder.Eq{"repo_id": repoID}), | |||||
), | |||||
).Cols("repo_count").SetExpr("repo_count", "repo_count-1").Update(&Topic{}) | |||||
if err != nil { | |||||
return err | |||||
} | |||||
if _, err = e.Delete(&RepoTopic{RepoID: repoID}); err != nil { | |||||
return err | |||||
} | |||||
return nil | |||||
} | |||||
// FindTopicOptions represents the options when fdin topics | // FindTopicOptions represents the options when fdin topics | ||||
type FindTopicOptions struct { | type FindTopicOptions struct { | ||||
ListOptions | ListOptions | ||||
return nil, nil | return nil, nil | ||||
} | } | ||||
err = removeTopicFromRepo(repoID, topic, x) | |||||
err = removeTopicFromRepo(x, repoID, topic) | |||||
return topic, err | return topic, err | ||||
} | } | ||||
} | } | ||||
for _, topic := range removeTopics { | for _, topic := range removeTopics { | ||||
err := removeTopicFromRepo(repoID, topic, sess) | |||||
err := removeTopicFromRepo(sess, repoID, topic) | |||||
if err != nil { | if err != nil { | ||||
return err | return err | ||||
} | } |