Skip to content

Commit 8acc7aa

Browse files
authored
Refactor topic Find functions and add more tests for pagination (#30127)
This also fixed #22238
1 parent dd8dde2 commit 8acc7aa

File tree

7 files changed

+70
-32
lines changed

7 files changed

+70
-32
lines changed

models/repo/topic.go

Lines changed: 13 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -178,7 +178,7 @@ type FindTopicOptions struct {
178178
Keyword string
179179
}
180180

181-
func (opts *FindTopicOptions) toConds() builder.Cond {
181+
func (opts *FindTopicOptions) ToConds() builder.Cond {
182182
cond := builder.NewCond()
183183
if opts.RepoID > 0 {
184184
cond = cond.And(builder.Eq{"repo_topic.repo_id": opts.RepoID})
@@ -191,29 +191,24 @@ func (opts *FindTopicOptions) toConds() builder.Cond {
191191
return cond
192192
}
193193

194-
// FindTopics retrieves the topics via FindTopicOptions
195-
func FindTopics(ctx context.Context, opts *FindTopicOptions) ([]*Topic, int64, error) {
196-
sess := db.GetEngine(ctx).Select("topic.*").Where(opts.toConds())
194+
func (opts *FindTopicOptions) ToOrders() string {
197195
orderBy := "topic.repo_count DESC"
198196
if opts.RepoID > 0 {
199-
sess.Join("INNER", "repo_topic", "repo_topic.topic_id = topic.id")
200197
orderBy = "topic.name" // when render topics for a repo, it's better to sort them by name, to get consistent result
201198
}
202-
if opts.PageSize != 0 && opts.Page != 0 {
203-
sess = db.SetSessionPagination(sess, opts)
204-
}
205-
topics := make([]*Topic, 0, 10)
206-
total, err := sess.OrderBy(orderBy).FindAndCount(&topics)
207-
return topics, total, err
199+
return orderBy
208200
}
209201

210-
// CountTopics counts the number of topics matching the FindTopicOptions
211-
func CountTopics(ctx context.Context, opts *FindTopicOptions) (int64, error) {
212-
sess := db.GetEngine(ctx).Where(opts.toConds())
213-
if opts.RepoID > 0 {
214-
sess.Join("INNER", "repo_topic", "repo_topic.topic_id = topic.id")
202+
func (opts *FindTopicOptions) ToJoins() []db.JoinFunc {
203+
if opts.RepoID <= 0 {
204+
return nil
205+
}
206+
return []db.JoinFunc{
207+
func(e db.Engine) error {
208+
e.Join("INNER", "repo_topic", "repo_topic.topic_id = topic.id")
209+
return nil
210+
},
215211
}
216-
return sess.Count(new(Topic))
217212
}
218213

219214
// GetRepoTopicByName retrieves topic from name for a repo if it exist
@@ -283,7 +278,7 @@ func DeleteTopic(ctx context.Context, repoID int64, topicName string) (*Topic, e
283278

284279
// SaveTopics save topics to a repository
285280
func SaveTopics(ctx context.Context, repoID int64, topicNames ...string) error {
286-
topics, _, err := FindTopics(ctx, &FindTopicOptions{
281+
topics, err := db.Find[Topic](ctx, &FindTopicOptions{
287282
RepoID: repoID,
288283
})
289284
if err != nil {

models/repo/topic_test.go

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -19,30 +19,30 @@ func TestAddTopic(t *testing.T) {
1919

2020
assert.NoError(t, unittest.PrepareTestDatabase())
2121

22-
topics, _, err := repo_model.FindTopics(db.DefaultContext, &repo_model.FindTopicOptions{})
22+
topics, err := db.Find[repo_model.Topic](db.DefaultContext, &repo_model.FindTopicOptions{})
2323
assert.NoError(t, err)
2424
assert.Len(t, topics, totalNrOfTopics)
2525

26-
topics, total, err := repo_model.FindTopics(db.DefaultContext, &repo_model.FindTopicOptions{
26+
topics, total, err := db.FindAndCount[repo_model.Topic](db.DefaultContext, &repo_model.FindTopicOptions{
2727
ListOptions: db.ListOptions{Page: 1, PageSize: 2},
2828
})
2929
assert.NoError(t, err)
3030
assert.Len(t, topics, 2)
3131
assert.EqualValues(t, 6, total)
3232

33-
topics, _, err = repo_model.FindTopics(db.DefaultContext, &repo_model.FindTopicOptions{
33+
topics, err = db.Find[repo_model.Topic](db.DefaultContext, &repo_model.FindTopicOptions{
3434
RepoID: 1,
3535
})
3636
assert.NoError(t, err)
3737
assert.Len(t, topics, repo1NrOfTopics)
3838

3939
assert.NoError(t, repo_model.SaveTopics(db.DefaultContext, 2, "golang"))
4040
repo2NrOfTopics := 1
41-
topics, _, err = repo_model.FindTopics(db.DefaultContext, &repo_model.FindTopicOptions{})
41+
topics, err = db.Find[repo_model.Topic](db.DefaultContext, &repo_model.FindTopicOptions{})
4242
assert.NoError(t, err)
4343
assert.Len(t, topics, totalNrOfTopics)
4444

45-
topics, _, err = repo_model.FindTopics(db.DefaultContext, &repo_model.FindTopicOptions{
45+
topics, err = db.Find[repo_model.Topic](db.DefaultContext, &repo_model.FindTopicOptions{
4646
RepoID: 2,
4747
})
4848
assert.NoError(t, err)
@@ -55,11 +55,11 @@ func TestAddTopic(t *testing.T) {
5555
assert.NoError(t, err)
5656
assert.EqualValues(t, 1, topic.RepoCount)
5757

58-
topics, _, err = repo_model.FindTopics(db.DefaultContext, &repo_model.FindTopicOptions{})
58+
topics, err = db.Find[repo_model.Topic](db.DefaultContext, &repo_model.FindTopicOptions{})
5959
assert.NoError(t, err)
6060
assert.Len(t, topics, totalNrOfTopics)
6161

62-
topics, _, err = repo_model.FindTopics(db.DefaultContext, &repo_model.FindTopicOptions{
62+
topics, err = db.Find[repo_model.Topic](db.DefaultContext, &repo_model.FindTopicOptions{
6363
RepoID: 2,
6464
})
6565
assert.NoError(t, err)

routers/api/v1/repo/topic.go

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import (
77
"net/http"
88
"strings"
99

10+
"code.gitea.io/gitea/models/db"
1011
repo_model "code.gitea.io/gitea/models/repo"
1112
"code.gitea.io/gitea/modules/log"
1213
api "code.gitea.io/gitea/modules/structs"
@@ -53,7 +54,7 @@ func ListTopics(ctx *context.APIContext) {
5354
RepoID: ctx.Repo.Repository.ID,
5455
}
5556

56-
topics, total, err := repo_model.FindTopics(ctx, opts)
57+
topics, total, err := db.FindAndCount[repo_model.Topic](ctx, opts)
5758
if err != nil {
5859
ctx.InternalServerError(err)
5960
return
@@ -172,7 +173,7 @@ func AddTopic(ctx *context.APIContext) {
172173
}
173174

174175
// Prevent adding more topics than allowed to repo
175-
count, err := repo_model.CountTopics(ctx, &repo_model.FindTopicOptions{
176+
count, err := db.Count[repo_model.Topic](ctx, &repo_model.FindTopicOptions{
176177
RepoID: ctx.Repo.Repository.ID,
177178
})
178179
if err != nil {
@@ -287,7 +288,7 @@ func TopicSearch(ctx *context.APIContext) {
287288
ListOptions: utils.GetListOptions(ctx),
288289
}
289290

290-
topics, total, err := repo_model.FindTopics(ctx, opts)
291+
topics, total, err := db.FindAndCount[repo_model.Topic](ctx, opts)
291292
if err != nil {
292293
ctx.InternalServerError(err)
293294
return

routers/web/explore/topic.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ func TopicSearch(ctx *context.Context) {
2323
},
2424
}
2525

26-
topics, total, err := repo_model.FindTopics(ctx, opts)
26+
topics, total, err := db.FindAndCount[repo_model.Topic](ctx, opts)
2727
if err != nil {
2828
ctx.Error(http.StatusInternalServerError)
2929
return

routers/web/repo/view.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -899,7 +899,7 @@ func renderLanguageStats(ctx *context.Context) {
899899
}
900900

901901
func renderRepoTopics(ctx *context.Context) {
902-
topics, _, err := repo_model.FindTopics(ctx, &repo_model.FindTopicOptions{
902+
topics, err := db.Find[repo_model.Topic](ctx, &repo_model.FindTopicOptions{
903903
RepoID: ctx.Repo.Repository.ID,
904904
})
905905
if err != nil {

tests/integration/api_repo_topic_test.go

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,14 +26,34 @@ func TestAPITopicSearch(t *testing.T) {
2626
TopicNames []*api.TopicResponse `json:"topics"`
2727
}
2828

29+
// search all topics
30+
res := MakeRequest(t, NewRequest(t, "GET", searchURL.String()), http.StatusOK)
31+
DecodeJSON(t, res, &topics)
32+
assert.Len(t, topics.TopicNames, 6)
33+
assert.EqualValues(t, "6", res.Header().Get("x-total-count"))
34+
35+
// pagination search topics first page
36+
topics.TopicNames = nil
2937
query := url.Values{"page": []string{"1"}, "limit": []string{"4"}}
3038

3139
searchURL.RawQuery = query.Encode()
32-
res := MakeRequest(t, NewRequest(t, "GET", searchURL.String()), http.StatusOK)
40+
res = MakeRequest(t, NewRequest(t, "GET", searchURL.String()), http.StatusOK)
3341
DecodeJSON(t, res, &topics)
3442
assert.Len(t, topics.TopicNames, 4)
3543
assert.EqualValues(t, "6", res.Header().Get("x-total-count"))
3644

45+
// pagination search topics second page
46+
topics.TopicNames = nil
47+
query = url.Values{"page": []string{"2"}, "limit": []string{"4"}}
48+
49+
searchURL.RawQuery = query.Encode()
50+
res = MakeRequest(t, NewRequest(t, "GET", searchURL.String()), http.StatusOK)
51+
DecodeJSON(t, res, &topics)
52+
assert.Len(t, topics.TopicNames, 2)
53+
assert.EqualValues(t, "6", res.Header().Get("x-total-count"))
54+
55+
// add keyword search
56+
query = url.Values{"page": []string{"1"}, "limit": []string{"4"}}
3757
query.Add("q", "topic")
3858
searchURL.RawQuery = query.Encode()
3959
res = MakeRequest(t, NewRequest(t, "GET", searchURL.String()), http.StatusOK)

tests/integration/repo_topic_test.go

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,20 +21,42 @@ func TestTopicSearch(t *testing.T) {
2121
TopicNames []*api.TopicResponse `json:"topics"`
2222
}
2323

24+
// search all topics
25+
res := MakeRequest(t, NewRequest(t, "GET", searchURL.String()), http.StatusOK)
26+
DecodeJSON(t, res, &topics)
27+
assert.Len(t, topics.TopicNames, 6)
28+
assert.EqualValues(t, "6", res.Header().Get("x-total-count"))
29+
30+
// pagination search topics
31+
topics.TopicNames = nil
2432
query := url.Values{"page": []string{"1"}, "limit": []string{"4"}}
2533

2634
searchURL.RawQuery = query.Encode()
27-
res := MakeRequest(t, NewRequest(t, "GET", searchURL.String()), http.StatusOK)
35+
res = MakeRequest(t, NewRequest(t, "GET", searchURL.String()), http.StatusOK)
2836
DecodeJSON(t, res, &topics)
2937
assert.Len(t, topics.TopicNames, 4)
3038
assert.EqualValues(t, "6", res.Header().Get("x-total-count"))
3139

40+
// second page
41+
topics.TopicNames = nil
42+
query = url.Values{"page": []string{"2"}, "limit": []string{"4"}}
43+
44+
searchURL.RawQuery = query.Encode()
45+
res = MakeRequest(t, NewRequest(t, "GET", searchURL.String()), http.StatusOK)
46+
DecodeJSON(t, res, &topics)
47+
assert.Len(t, topics.TopicNames, 2)
48+
assert.EqualValues(t, "6", res.Header().Get("x-total-count"))
49+
50+
// add keyword search
51+
topics.TopicNames = nil
52+
query = url.Values{"page": []string{"1"}, "limit": []string{"4"}}
3253
query.Add("q", "topic")
3354
searchURL.RawQuery = query.Encode()
3455
res = MakeRequest(t, NewRequest(t, "GET", searchURL.String()), http.StatusOK)
3556
DecodeJSON(t, res, &topics)
3657
assert.Len(t, topics.TopicNames, 2)
3758

59+
topics.TopicNames = nil
3860
query.Set("q", "database")
3961
searchURL.RawQuery = query.Encode()
4062
res = MakeRequest(t, NewRequest(t, "GET", searchURL.String()), http.StatusOK)

0 commit comments

Comments
 (0)