Skip to content

Commit ea20ada

Browse files
authored
feat(repo): support search repository by topic name (#4505)
* feat(repo): support search repository by topic name
1 parent 7dd93b2 commit ea20ada

File tree

17 files changed

+134
-26
lines changed

17 files changed

+134
-26
lines changed

integrations/api_admin_test.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,10 @@ import (
99
"net/http"
1010
"testing"
1111

12-
"github.com/stretchr/testify/assert"
13-
1412
"code.gitea.io/gitea/models"
1513
api "code.gitea.io/sdk/gitea"
14+
15+
"github.com/stretchr/testify/assert"
1616
)
1717

1818
func TestAPIAdminCreateAndDeleteSSHKey(t *testing.T) {

integrations/api_issue_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,13 @@
55
package integrations
66

77
import (
8+
"fmt"
89
"net/http"
910
"testing"
1011

1112
"code.gitea.io/gitea/models"
1213
api "code.gitea.io/sdk/gitea"
1314

14-
"fmt"
1515
"github.com/stretchr/testify/assert"
1616
)
1717

integrations/api_repo_test.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -67,9 +67,9 @@ func TestAPISearchRepo(t *testing.T) {
6767
expectedResults
6868
}{
6969
{name: "RepositoriesMax50", requestURL: "/api/v1/repos/search?limit=50", expectedResults: expectedResults{
70-
nil: {count: 17},
71-
user: {count: 17},
72-
user2: {count: 17}},
70+
nil: {count: 19},
71+
user: {count: 19},
72+
user2: {count: 19}},
7373
},
7474
{name: "RepositoriesMax10", requestURL: "/api/v1/repos/search?limit=10", expectedResults: expectedResults{
7575
nil: {count: 10},

models/fixtures/repo_topic.yml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,3 +9,11 @@
99
-
1010
repo_id: 1
1111
topic_id: 3
12+
13+
-
14+
repo_id: 33
15+
topic_id: 1
16+
17+
-
18+
repo_id: 33
19+
topic_id: 4

models/fixtures/repository.yml

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -407,3 +407,25 @@
407407
lower_name: utf8
408408
name: utf8
409409
is_private: false
410+
411+
-
412+
id: 34
413+
owner_id: 21
414+
lower_name: golang
415+
name: golang
416+
is_private: false
417+
num_stars: 0
418+
num_forks: 0
419+
num_issues: 0
420+
is_mirror: false
421+
422+
-
423+
id: 35
424+
owner_id: 21
425+
lower_name: graphql
426+
name: graphql
427+
is_private: false
428+
num_stars: 0
429+
num_forks: 0
430+
num_issues: 0
431+
is_mirror: false

models/fixtures/topic.yml

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
-
22
id: 1
33
name: golang
4-
repo_count: 1
4+
repo_count: 2
55

66
-
77
id: 2
@@ -11,3 +11,7 @@
1111
- id: 3
1212
name: SQL
1313
repo_count: 1
14+
15+
- id: 4
16+
name: graphql
17+
repo_count: 1

models/fixtures/user.yml

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -314,3 +314,18 @@
314314
avatar_email: [email protected]
315315
num_repos: 4
316316
is_active: true
317+
318+
-
319+
id: 21
320+
lower_name: user21
321+
name: user21
322+
full_name: User 21
323+
324+
passwd: 7d93daa0d1e6f2305cc8fa496847d61dc7320bb16262f9c55dd753480207234cdd96a93194e408341971742f4701772a025a # password
325+
type: 0 # individual
326+
salt: ZogKvWdyEx
327+
is_admin: false
328+
avatar: avatar21
329+
avatar_email: [email protected]
330+
num_repos: 2
331+
is_active: true

models/repo_list.go

Lines changed: 30 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,8 @@ type SearchRepoOptions struct {
131131
// True -> include just mirrors
132132
// False -> include just non-mirrors
133133
Mirror util.OptionalBool
134+
// only search topic name
135+
TopicOnly bool
134136
}
135137

136138
//SearchOrderBy is used to sort the result
@@ -184,7 +186,7 @@ func SearchRepositoryByName(opts *SearchRepoOptions) (RepositoryList, int64, err
184186

185187
if opts.Collaborate != util.OptionalBoolFalse {
186188
collaborateCond := builder.And(
187-
builder.Expr("id IN (SELECT repo_id FROM `access` WHERE access.user_id = ?)", opts.OwnerID),
189+
builder.Expr("repository.id IN (SELECT repo_id FROM `access` WHERE access.user_id = ?)", opts.OwnerID),
188190
builder.Neq{"owner_id": opts.OwnerID})
189191
if !opts.Private {
190192
collaborateCond = collaborateCond.And(builder.Expr("owner_id NOT IN (SELECT org_id FROM org_user WHERE org_user.uid = ? AND org_user.is_public = ?)", opts.OwnerID, false))
@@ -202,7 +204,14 @@ func SearchRepositoryByName(opts *SearchRepoOptions) (RepositoryList, int64, err
202204
}
203205

204206
if opts.Keyword != "" {
205-
cond = cond.And(builder.Like{"lower_name", strings.ToLower(opts.Keyword)})
207+
var keywordCond = builder.NewCond()
208+
if opts.TopicOnly {
209+
keywordCond = keywordCond.Or(builder.Like{"topic.name", strings.ToLower(opts.Keyword)})
210+
} else {
211+
keywordCond = keywordCond.Or(builder.Like{"lower_name", strings.ToLower(opts.Keyword)})
212+
keywordCond = keywordCond.Or(builder.Like{"topic.name", strings.ToLower(opts.Keyword)})
213+
}
214+
cond = cond.And(keywordCond)
206215
}
207216

208217
if opts.Fork != util.OptionalBoolNone {
@@ -224,9 +233,15 @@ func SearchRepositoryByName(opts *SearchRepoOptions) (RepositoryList, int64, err
224233
sess.Join("INNER", "star", "star.repo_id = repository.id")
225234
}
226235

236+
if opts.Keyword != "" {
237+
sess.Join("LEFT", "repo_topic", "repo_topic.repo_id = repository.id")
238+
sess.Join("LEFT", "topic", "repo_topic.topic_id = topic.id")
239+
}
240+
227241
count, err := sess.
228242
Where(cond).
229243
Count(new(Repository))
244+
230245
if err != nil {
231246
return nil, 0, fmt.Errorf("Count: %v", err)
232247
}
@@ -236,11 +251,23 @@ func SearchRepositoryByName(opts *SearchRepoOptions) (RepositoryList, int64, err
236251
sess.Join("INNER", "star", "star.repo_id = repository.id")
237252
}
238253

254+
if opts.Keyword != "" {
255+
sess.Join("LEFT", "repo_topic", "repo_topic.repo_id = repository.id")
256+
sess.Join("LEFT", "topic", "repo_topic.topic_id = topic.id")
257+
}
258+
259+
if opts.Keyword != "" {
260+
sess.Select("repository.*")
261+
sess.GroupBy("repository.id")
262+
sess.OrderBy("repository." + opts.OrderBy.String())
263+
} else {
264+
sess.OrderBy(opts.OrderBy.String())
265+
}
266+
239267
repos := make(RepositoryList, 0, opts.PageSize)
240268
if err = sess.
241269
Where(cond).
242270
Limit(opts.PageSize, (opts.Page-1)*opts.PageSize).
243-
OrderBy(opts.OrderBy.String()).
244271
Find(&repos); err != nil {
245272
return nil, 0, fmt.Errorf("Repo: %v", err)
246273
}

models/repo_list_test.go

Lines changed: 28 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -147,10 +147,10 @@ func TestSearchRepositoryByName(t *testing.T) {
147147
count: 14},
148148
{name: "AllPublic/PublicRepositoriesOfUserIncludingCollaborative",
149149
opts: &SearchRepoOptions{Page: 1, PageSize: 10, OwnerID: 15, AllPublic: true},
150-
count: 17},
150+
count: 19},
151151
{name: "AllPublic/PublicAndPrivateRepositoriesOfUserIncludingCollaborative",
152152
opts: &SearchRepoOptions{Page: 1, PageSize: 10, OwnerID: 15, Private: true, AllPublic: true},
153-
count: 21},
153+
count: 23},
154154
{name: "AllPublic/PublicAndPrivateRepositoriesOfUserIncludingCollaborativeByName",
155155
opts: &SearchRepoOptions{Keyword: "test", Page: 1, PageSize: 10, OwnerID: 15, Private: true, AllPublic: true},
156156
count: 13},
@@ -159,7 +159,7 @@ func TestSearchRepositoryByName(t *testing.T) {
159159
count: 11},
160160
{name: "AllPublic/PublicRepositoriesOfOrganization",
161161
opts: &SearchRepoOptions{Page: 1, PageSize: 10, OwnerID: 17, AllPublic: true, Collaborate: util.OptionalBoolFalse},
162-
count: 17},
162+
count: 19},
163163
}
164164

165165
for _, testCase := range testCases {
@@ -222,3 +222,28 @@ func TestSearchRepositoryByName(t *testing.T) {
222222
})
223223
}
224224
}
225+
226+
func TestSearchRepositoryByTopicName(t *testing.T) {
227+
assert.NoError(t, PrepareTestDatabase())
228+
229+
testCases := []struct {
230+
name string
231+
opts *SearchRepoOptions
232+
count int
233+
}{
234+
{name: "AllPublic/SearchPublicRepositoriesFromTopicAndName",
235+
opts: &SearchRepoOptions{OwnerID: 21, AllPublic: true, Keyword: "graphql"},
236+
count: 2},
237+
{name: "AllPublic/OnlySearchPublicRepositoriesFromTopic",
238+
opts: &SearchRepoOptions{OwnerID: 21, AllPublic: true, Keyword: "graphql", TopicOnly: true},
239+
count: 1},
240+
}
241+
242+
for _, testCase := range testCases {
243+
t.Run(testCase.name, func(t *testing.T) {
244+
_, count, err := SearchRepositoryByName(testCase.opts)
245+
assert.NoError(t, err)
246+
assert.Equal(t, int64(testCase.count), count)
247+
})
248+
}
249+
}

models/ssh_key.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,14 +18,14 @@ import (
1818
"sync"
1919
"time"
2020

21-
"github.com/Unknwon/com"
22-
"github.com/go-xorm/xorm"
23-
"golang.org/x/crypto/ssh"
24-
2521
"code.gitea.io/gitea/modules/log"
2622
"code.gitea.io/gitea/modules/process"
2723
"code.gitea.io/gitea/modules/setting"
2824
"code.gitea.io/gitea/modules/util"
25+
26+
"github.com/Unknwon/com"
27+
"github.com/go-xorm/xorm"
28+
"golang.org/x/crypto/ssh"
2929
)
3030

3131
const (

0 commit comments

Comments
 (0)