From edd8ea0b0d07f7fee0f8cf506975c8f3bec690ca Mon Sep 17 00:00:00 2001
From: Yarden Shoham <git@yardenshoham.com>
Date: Sun, 21 May 2023 12:03:20 +0300
Subject: [PATCH] Fix topics deleted via API not being deleted in org page
 (#24825)

The topics are saved in the `repo_topic` table.
They are also saved directly in the `repository` table.

Before this PR, only `AddTopic` and `SaveTopics` made sure the `topics`
field in the `repository` table was synced with the `repo_topic` table.

This PR makes sure `GenerateTopics` and `DeleteTopic`
also sync the `topics` in the repository table.

`RemoveTopicsFromRepo` doesn't need to sync the data
as it is only used to delete a repository.

Fixes #24820
---
 models/repo/topic.go | 45 ++++++++++++++++++++++++--------------------
 1 file changed, 25 insertions(+), 20 deletions(-)

diff --git a/models/repo/topic.go b/models/repo/topic.go
index 88fe532be9a..ec3de869d5b 100644
--- a/models/repo/topic.go
+++ b/models/repo/topic.go
@@ -253,16 +253,7 @@ func AddTopic(repoID int64, topicName string) (*Topic, error) {
 		return nil, err
 	}
 
-	topicNames := make([]string, 0, 25)
-	if err := sess.Select("name").Table("topic").
-		Join("INNER", "repo_topic", "repo_topic.topic_id = topic.id").
-		Where("repo_topic.repo_id = ?", repoID).Desc("topic.repo_count").Find(&topicNames); err != nil {
-		return nil, err
-	}
-
-	if _, err := sess.ID(repoID).Cols("topics").Update(&Repository{
-		Topics: topicNames,
-	}); err != nil {
+	if err = syncTopicsInRepository(sess, repoID); err != nil {
 		return nil, err
 	}
 
@@ -281,6 +272,11 @@ func DeleteTopic(repoID int64, topicName string) (*Topic, error) {
 	}
 
 	err = removeTopicFromRepo(db.DefaultContext, repoID, topic)
+	if err != nil {
+		return nil, err
+	}
+
+	err = syncTopicsInRepository(db.GetEngine(db.DefaultContext), repoID)
 
 	return topic, err
 }
@@ -347,16 +343,7 @@ func SaveTopics(repoID int64, topicNames ...string) error {
 		}
 	}
 
-	topicNames = make([]string, 0, 25)
-	if err := sess.Table("topic").Cols("name").
-		Join("INNER", "repo_topic", "repo_topic.topic_id = topic.id").
-		Where("repo_topic.repo_id = ?", repoID).Desc("topic.repo_count").Find(&topicNames); err != nil {
-		return err
-	}
-
-	if _, err := sess.ID(repoID).Cols("topics").Update(&Repository{
-		Topics: topicNames,
-	}); err != nil {
+	if err := syncTopicsInRepository(sess, repoID); err != nil {
 		return err
 	}
 
@@ -370,5 +357,23 @@ func GenerateTopics(ctx context.Context, templateRepo, generateRepo *Repository)
 			return err
 		}
 	}
+
+	return syncTopicsInRepository(db.GetEngine(ctx), generateRepo.ID)
+}
+
+// syncTopicsInRepository makes sure topics in the topics table are copied into the topics field of the repository
+func syncTopicsInRepository(sess db.Engine, repoID int64) error {
+	topicNames := make([]string, 0, 25)
+	if err := sess.Table("topic").Cols("name").
+		Join("INNER", "repo_topic", "repo_topic.topic_id = topic.id").
+		Where("repo_topic.repo_id = ?", repoID).Desc("topic.repo_count").Find(&topicNames); err != nil {
+		return err
+	}
+
+	if _, err := sess.ID(repoID).Cols("topics").Update(&Repository{
+		Topics: topicNames,
+	}); err != nil {
+		return err
+	}
 	return nil
 }