Skip to content

Commit c9546d4

Browse files
davidsvantessonlafriks
authored andcommitted
Include description in repository search. (#7942)
* Add description in repository search. Signed-off-by: David Svantesson <[email protected]> * Refactor SearchRepositoryByName with a general function SearchRepository Signed-off-by: David Svantesson <[email protected]> * Allow to specify if description shall be included in API repo search. Signed-off-by: David Svantesson <[email protected]> * Add new app.ini setting for whether to search within repo description. Signed-off-by: David Svantesson <[email protected]> * Search keyword in description (if setting enabled) on: - Explore page - Organization profile page - User profile page - Admin repo page Do not search keyword in description on: - Any non-keyword search (not relevant) - Incremental search (uses API) Signed-off-by: David Svantesson <[email protected]> * Put parameters related to keyword directly after it Signed-off-by: David Svantesson <[email protected]> * Add test cases for including (and not including) repository description in search. Signed-off-by: David Svantesson <[email protected]> * Rename test function from TestSearchRepositoryByName to TestSearchRepository. Signed-off-by: David Svantesson <[email protected]> * Make setting SEARCH_REPO_DESCRIPTION default to true Signed-off-by: David Svantesson <[email protected]>
1 parent 8c24bb9 commit c9546d4

File tree

11 files changed

+134
-73
lines changed

11 files changed

+134
-73
lines changed

custom/conf/app.ini.sample

+2
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,8 @@ DEFAULT_THEME = gitea
116116
THEMES = gitea,arc-green
117117
; Whether the full name of the users should be shown where possible. If the full name isn't set, the username will be used.
118118
DEFAULT_SHOW_FULL_NAME = false
119+
; Whether to search within description at repository search on explore page.
120+
SEARCH_REPO_DESCRIPTION = true
119121

120122
[ui.admin]
121123
; Number of users that are displayed on one page

docs/content/doc/advanced/config-cheat-sheet.en-us.md

+1
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,7 @@ Values containing `#` or `;` must be quoted using `` ` `` or `"""`.
9696
- `THEMES`: **gitea,arc-green**: All available themes. Allow users select personalized themes
9797
regardless of the value of `DEFAULT_THEME`.
9898
- `DEFAULT_SHOW_FULL_NAME`: false: Whether the full name of the users should be shown where possible. If the full name isn't set, the username will be used.
99+
- `SEARCH_REPO_DESCRIPTION`: true: Whether to search within description at repository search on explore page.
99100

100101
### UI - Admin (`ui.admin`)
101102

models/fixtures/repository.yml

+1
Original file line numberDiff line numberDiff line change
@@ -165,6 +165,7 @@
165165
owner_id: 14
166166
lower_name: test_repo_14
167167
name: test_repo_14
168+
description: test_description_14
168169
is_private: false
169170
num_issues: 0
170171
num_closed_issues: 0

models/repo_list.go

+14-2
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,8 @@ type SearchRepoOptions struct {
136136
Mirror util.OptionalBool
137137
// only search topic name
138138
TopicOnly bool
139+
// include description in keyword search
140+
IncludeDescription bool
139141
}
140142

141143
//SearchOrderBy is used to sort the result
@@ -163,9 +165,9 @@ const (
163165
SearchOrderByForksReverse SearchOrderBy = "num_forks DESC"
164166
)
165167

166-
// SearchRepositoryByName takes keyword and part of repository name to search,
168+
// SearchRepository returns repositories based on search options,
167169
// it returns results in given range and number of total results.
168-
func SearchRepositoryByName(opts *SearchRepoOptions) (RepositoryList, int64, error) {
170+
func SearchRepository(opts *SearchRepoOptions) (RepositoryList, int64, error) {
169171
if opts.Page <= 0 {
170172
opts.Page = 1
171173
}
@@ -264,6 +266,9 @@ func SearchRepositoryByName(opts *SearchRepoOptions) (RepositoryList, int64, err
264266
var likes = builder.NewCond()
265267
for _, v := range strings.Split(opts.Keyword, ",") {
266268
likes = likes.Or(builder.Like{"lower_name", strings.ToLower(v)})
269+
if opts.IncludeDescription {
270+
likes = likes.Or(builder.Like{"LOWER(description)", strings.ToLower(v)})
271+
}
267272
}
268273
keywordCond = keywordCond.Or(likes)
269274
}
@@ -311,6 +316,13 @@ func SearchRepositoryByName(opts *SearchRepoOptions) (RepositoryList, int64, err
311316
return repos, count, nil
312317
}
313318

319+
// SearchRepositoryByName takes keyword and part of repository name to search,
320+
// it returns results in given range and number of total results.
321+
func SearchRepositoryByName(opts *SearchRepoOptions) (RepositoryList, int64, error) {
322+
opts.IncludeDescription = false
323+
return SearchRepository(opts)
324+
}
325+
314326
// FindUserAccessibleRepoIDs find all accessible repositories' ID by user's id
315327
func FindUserAccessibleRepoIDs(userID int64) ([]int64, error) {
316328
var accessCond builder.Cond = builder.Eq{"is_private": false}

models/repo_list_test.go

+29-1
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ import (
1212
"github.com/stretchr/testify/assert"
1313
)
1414

15-
func TestSearchRepositoryByName(t *testing.T) {
15+
func TestSearchRepository(t *testing.T) {
1616
assert.NoError(t, PrepareTestDatabase())
1717

1818
// test search public repository on explore page
@@ -74,6 +74,34 @@ func TestSearchRepositoryByName(t *testing.T) {
7474
assert.Empty(t, repos)
7575
assert.Equal(t, int64(0), count)
7676

77+
// Test search within description
78+
repos, count, err = SearchRepository(&SearchRepoOptions{
79+
Keyword: "description_14",
80+
Page: 1,
81+
PageSize: 10,
82+
Collaborate: util.OptionalBoolFalse,
83+
IncludeDescription: true,
84+
})
85+
86+
assert.NoError(t, err)
87+
if assert.Len(t, repos, 1) {
88+
assert.Equal(t, "test_repo_14", repos[0].Name)
89+
}
90+
assert.Equal(t, int64(1), count)
91+
92+
// Test NOT search within description
93+
repos, count, err = SearchRepository(&SearchRepoOptions{
94+
Keyword: "description_14",
95+
Page: 1,
96+
PageSize: 10,
97+
Collaborate: util.OptionalBoolFalse,
98+
IncludeDescription: false,
99+
})
100+
101+
assert.NoError(t, err)
102+
assert.Empty(t, repos)
103+
assert.Equal(t, int64(0), count)
104+
77105
testCases := []struct {
78106
name string
79107
opts *SearchRepoOptions

modules/setting/setting.go

+15-13
Original file line numberDiff line numberDiff line change
@@ -150,19 +150,20 @@ var (
150150

151151
// UI settings
152152
UI = struct {
153-
ExplorePagingNum int
154-
IssuePagingNum int
155-
RepoSearchPagingNum int
156-
FeedMaxCommitNum int
157-
GraphMaxCommitNum int
158-
CodeCommentLines int
159-
ReactionMaxUserNum int
160-
ThemeColorMetaTag string
161-
MaxDisplayFileSize int64
162-
ShowUserEmail bool
163-
DefaultShowFullName bool
164-
DefaultTheme string
165-
Themes []string
153+
ExplorePagingNum int
154+
IssuePagingNum int
155+
RepoSearchPagingNum int
156+
FeedMaxCommitNum int
157+
GraphMaxCommitNum int
158+
CodeCommentLines int
159+
ReactionMaxUserNum int
160+
ThemeColorMetaTag string
161+
MaxDisplayFileSize int64
162+
ShowUserEmail bool
163+
DefaultShowFullName bool
164+
DefaultTheme string
165+
Themes []string
166+
SearchRepoDescription bool
166167

167168
Admin struct {
168169
UserPagingNum int
@@ -942,6 +943,7 @@ func NewContext() {
942943

943944
UI.ShowUserEmail = Cfg.Section("ui").Key("SHOW_USER_EMAIL").MustBool(true)
944945
UI.DefaultShowFullName = Cfg.Section("ui").Key("DEFAULT_SHOW_FULL_NAME").MustBool(false)
946+
UI.SearchRepoDescription = Cfg.Section("ui").Key("SEARCH_REPO_DESCRIPTION").MustBool(true)
945947

946948
HasRobotsTxt = com.IsFile(path.Join(CustomPath, "robots.txt"))
947949

routers/api/v1/repo/repo.go

+16-11
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,10 @@ func Search(ctx *context.APIContext) {
5555
// in: query
5656
// description: Limit search to repositories with keyword as topic
5757
// type: boolean
58+
// - name: includeDesc
59+
// in: query
60+
// description: include search of keyword within repository description
61+
// type: boolean
5862
// - name: uid
5963
// in: query
6064
// description: search only for repos that the user with the given id owns or contributes to
@@ -103,16 +107,17 @@ func Search(ctx *context.APIContext) {
103107
// "422":
104108
// "$ref": "#/responses/validationError"
105109
opts := &models.SearchRepoOptions{
106-
Keyword: strings.Trim(ctx.Query("q"), " "),
107-
OwnerID: ctx.QueryInt64("uid"),
108-
Page: ctx.QueryInt("page"),
109-
PageSize: convert.ToCorrectPageSize(ctx.QueryInt("limit")),
110-
TopicOnly: ctx.QueryBool("topic"),
111-
Collaborate: util.OptionalBoolNone,
112-
Private: ctx.IsSigned && (ctx.Query("private") == "" || ctx.QueryBool("private")),
113-
UserIsAdmin: ctx.IsUserSiteAdmin(),
114-
UserID: ctx.Data["SignedUserID"].(int64),
115-
StarredByID: ctx.QueryInt64("starredBy"),
110+
Keyword: strings.Trim(ctx.Query("q"), " "),
111+
OwnerID: ctx.QueryInt64("uid"),
112+
Page: ctx.QueryInt("page"),
113+
PageSize: convert.ToCorrectPageSize(ctx.QueryInt("limit")),
114+
TopicOnly: ctx.QueryBool("topic"),
115+
Collaborate: util.OptionalBoolNone,
116+
Private: ctx.IsSigned && (ctx.Query("private") == "" || ctx.QueryBool("private")),
117+
UserIsAdmin: ctx.IsUserSiteAdmin(),
118+
UserID: ctx.Data["SignedUserID"].(int64),
119+
StarredByID: ctx.QueryInt64("starredBy"),
120+
IncludeDescription: ctx.QueryBool("includeDesc"),
116121
}
117122

118123
if ctx.QueryBool("exclusive") {
@@ -157,7 +162,7 @@ func Search(ctx *context.APIContext) {
157162
}
158163

159164
var err error
160-
repos, count, err := models.SearchRepositoryByName(opts)
165+
repos, count, err := models.SearchRepository(opts)
161166
if err != nil {
162167
ctx.JSON(500, api.SearchError{
163168
OK: false,

routers/home.go

+11-10
Original file line numberDiff line numberDiff line change
@@ -133,18 +133,19 @@ func RenderRepoSearch(ctx *context.Context, opts *RepoSearchOptions) {
133133
keyword := strings.Trim(ctx.Query("q"), " ")
134134
topicOnly := ctx.QueryBool("topic")
135135

136-
repos, count, err = models.SearchRepositoryByName(&models.SearchRepoOptions{
137-
Page: page,
138-
PageSize: opts.PageSize,
139-
OrderBy: orderBy,
140-
Private: opts.Private,
141-
Keyword: keyword,
142-
OwnerID: opts.OwnerID,
143-
AllPublic: true,
144-
TopicOnly: topicOnly,
136+
repos, count, err = models.SearchRepository(&models.SearchRepoOptions{
137+
Page: page,
138+
PageSize: opts.PageSize,
139+
OrderBy: orderBy,
140+
Private: opts.Private,
141+
Keyword: keyword,
142+
OwnerID: opts.OwnerID,
143+
AllPublic: true,
144+
TopicOnly: topicOnly,
145+
IncludeDescription: setting.UI.SearchRepoDescription,
145146
})
146147
if err != nil {
147-
ctx.ServerError("SearchRepositoryByName", err)
148+
ctx.ServerError("SearchRepository", err)
148149
return
149150
}
150151
ctx.Data["Keyword"] = keyword

routers/user/home.go

+12-11
Original file line numberDiff line numberDiff line change
@@ -499,19 +499,20 @@ func showOrgProfile(ctx *context.Context) {
499499
count int64
500500
err error
501501
)
502-
repos, count, err = models.SearchRepositoryByName(&models.SearchRepoOptions{
503-
Keyword: keyword,
504-
OwnerID: org.ID,
505-
OrderBy: orderBy,
506-
Private: ctx.IsSigned,
507-
UserIsAdmin: ctx.IsUserSiteAdmin(),
508-
UserID: ctx.Data["SignedUserID"].(int64),
509-
Page: page,
510-
IsProfile: true,
511-
PageSize: setting.UI.User.RepoPagingNum,
502+
repos, count, err = models.SearchRepository(&models.SearchRepoOptions{
503+
Keyword: keyword,
504+
OwnerID: org.ID,
505+
OrderBy: orderBy,
506+
Private: ctx.IsSigned,
507+
UserIsAdmin: ctx.IsUserSiteAdmin(),
508+
UserID: ctx.Data["SignedUserID"].(int64),
509+
Page: page,
510+
IsProfile: true,
511+
PageSize: setting.UI.User.RepoPagingNum,
512+
IncludeDescription: setting.UI.SearchRepoDescription,
512513
})
513514
if err != nil {
514-
ctx.ServerError("SearchRepositoryByName", err)
515+
ctx.ServerError("SearchRepository", err)
515516
return
516517
}
517518

routers/user/profile.go

+27-25
Original file line numberDiff line numberDiff line change
@@ -169,40 +169,42 @@ func Profile(ctx *context.Context) {
169169
}
170170
case "stars":
171171
ctx.Data["PageIsProfileStarList"] = true
172-
repos, count, err = models.SearchRepositoryByName(&models.SearchRepoOptions{
173-
Keyword: keyword,
174-
OrderBy: orderBy,
175-
Private: ctx.IsSigned,
176-
UserIsAdmin: ctx.IsUserSiteAdmin(),
177-
UserID: ctx.Data["SignedUserID"].(int64),
178-
Page: page,
179-
PageSize: setting.UI.User.RepoPagingNum,
180-
StarredByID: ctxUser.ID,
181-
Collaborate: util.OptionalBoolFalse,
182-
TopicOnly: topicOnly,
172+
repos, count, err = models.SearchRepository(&models.SearchRepoOptions{
173+
Keyword: keyword,
174+
OrderBy: orderBy,
175+
Private: ctx.IsSigned,
176+
UserIsAdmin: ctx.IsUserSiteAdmin(),
177+
UserID: ctx.Data["SignedUserID"].(int64),
178+
Page: page,
179+
PageSize: setting.UI.User.RepoPagingNum,
180+
StarredByID: ctxUser.ID,
181+
Collaborate: util.OptionalBoolFalse,
182+
TopicOnly: topicOnly,
183+
IncludeDescription: setting.UI.SearchRepoDescription,
183184
})
184185
if err != nil {
185-
ctx.ServerError("SearchRepositoryByName", err)
186+
ctx.ServerError("SearchRepository", err)
186187
return
187188
}
188189

189190
total = int(count)
190191
default:
191-
repos, count, err = models.SearchRepositoryByName(&models.SearchRepoOptions{
192-
Keyword: keyword,
193-
OwnerID: ctxUser.ID,
194-
OrderBy: orderBy,
195-
Private: ctx.IsSigned,
196-
UserIsAdmin: ctx.IsUserSiteAdmin(),
197-
UserID: ctx.Data["SignedUserID"].(int64),
198-
Page: page,
199-
IsProfile: true,
200-
PageSize: setting.UI.User.RepoPagingNum,
201-
Collaborate: util.OptionalBoolFalse,
202-
TopicOnly: topicOnly,
192+
repos, count, err = models.SearchRepository(&models.SearchRepoOptions{
193+
Keyword: keyword,
194+
OwnerID: ctxUser.ID,
195+
OrderBy: orderBy,
196+
Private: ctx.IsSigned,
197+
UserIsAdmin: ctx.IsUserSiteAdmin(),
198+
UserID: ctx.Data["SignedUserID"].(int64),
199+
Page: page,
200+
IsProfile: true,
201+
PageSize: setting.UI.User.RepoPagingNum,
202+
Collaborate: util.OptionalBoolFalse,
203+
TopicOnly: topicOnly,
204+
IncludeDescription: setting.UI.SearchRepoDescription,
203205
})
204206
if err != nil {
205-
ctx.ServerError("SearchRepositoryByName", err)
207+
ctx.ServerError("SearchRepository", err)
206208
return
207209
}
208210

templates/swagger/v1_json.tmpl

+6
Original file line numberDiff line numberDiff line change
@@ -1099,6 +1099,12 @@
10991099
"name": "topic",
11001100
"in": "query"
11011101
},
1102+
{
1103+
"type": "boolean",
1104+
"description": "include search of keyword within repository description",
1105+
"name": "includeDesc",
1106+
"in": "query"
1107+
},
11021108
{
11031109
"type": "integer",
11041110
"format": "int64",

0 commit comments

Comments
 (0)