mirror of
https://github.com/go-gitea/gitea.git
synced 2026-11-11 19:39:02 +00:00
fix(repo): rank exact repository name matches first (#39038)
The quick repository switcher orders results alphabetically, so a repository whose name exactly matches the query can appear below names that merely contain it. - Rank exact repository name matches first when no explicit sort order is requested - For "owner/repo" queries, rank the exact pair first, then the owner's other repositories - Match the owner of "owner/repo" queries case-insensitively, mixed-case owners were missed --------- Co-authored-by: silverwind <me@silverwind.io>
This commit is contained in:
1 parent
aa073fb1be
commit
e867cfbf0d
2 files changed
+26
-5
No files matched your search
@@ -475,7 +475,7 @@ func SearchRepositoryCondition(opts SearchRepoOptions) builder.Cond {
|
||||
pieces := strings.Split(opts.Keyword, "/")
|
||||
ownerName := pieces[0]
|
||||
repoName := pieces[1]
|
||||
likes = likes.Or(builder.And(builder.Like{"owner_name", strings.ToLower(ownerName)}, builder.Like{"lower_name", strings.ToLower(repoName)}))
|
||||
likes = likes.Or(builder.And(db.BuildCaseInsensitiveLike("owner_name", ownerName), builder.Like{"lower_name", strings.ToLower(repoName)}))
|
||||
}
|
||||
|
||||
if opts.IncludeDescription {
|
||||
@@ -609,10 +609,12 @@ func searchRepositoryByCondition(ctx context.Context, opts SearchRepoOptions, co
|
||||
orderBy = db.SearchOrderBy(fmt.Sprintf("CASE WHEN owner_id = ? THEN 0 ELSE owner_id END, %s", orderBy))
|
||||
args = append(args, opts.PriorityOwnerID)
|
||||
} else if strings.Count(opts.Keyword, "/") == 1 {
|
||||
// With "owner/repo" search times, prioritise results which match the owner field
|
||||
orgName, _, _ := strings.Cut(opts.Keyword, "/")
|
||||
orderBy = db.SearchOrderBy(fmt.Sprintf("CASE WHEN owner_name LIKE ? THEN 0 ELSE 1 END, %s", orderBy))
|
||||
args = append(args, orgName)
|
||||
ownerName, repoName, _ := strings.Cut(strings.ToLower(opts.Keyword), "/")
|
||||
orderBy = db.SearchOrderBy(fmt.Sprintf("CASE LOWER(owner_name) WHEN ? THEN CASE lower_name WHEN ? THEN 0 ELSE 1 END ELSE 2 END, %s", orderBy))
|
||||
args = append(args, ownerName, repoName)
|
||||
} else if len(opts.OrderBy) == 0 && opts.Keyword != "" && !strings.ContainsAny(opts.Keyword, ",/") { // unlike "owner/repo", a bare name never overrides an explicit sort
|
||||
orderBy = db.SearchOrderBy(fmt.Sprintf("CASE WHEN lower_name = ? THEN 0 ELSE 1 END, %s", orderBy))
|
||||
args = append(args, strings.ToLower(opts.Keyword))
|
||||
}
|
||||
|
||||
sess := db.GetEngine(ctx)
|
||||
|
||||
@@ -195,6 +195,25 @@ func TestSearchRepository(t *testing.T) {
|
||||
t.Run("SearchRepositoryWithInDescription", testSearchRepositoryWithInDescription)
|
||||
t.Run("SearchRepositoryNotInDescription", testSearchRepositoryNotInDescription)
|
||||
t.Run("SearchRepositoryCases", testSearchRepositoryCases)
|
||||
t.Run("SearchRepositoryRanksExactMatchesCaseInsensitivelyUnlessSorted", func(t *testing.T) {
|
||||
afoo := &repo_model.Repository{OwnerID: 2, OwnerName: "User2", LowerName: "afoo", Name: "afoo"}
|
||||
aafoo := &repo_model.Repository{OwnerID: 20, OwnerName: "user20", LowerName: "aafoo", Name: "aafoo"}
|
||||
foo := &repo_model.Repository{OwnerID: 2, OwnerName: "User2", LowerName: "foo", Name: "foo"}
|
||||
require.NoError(t, db.Insert(t.Context(), afoo, aafoo, foo))
|
||||
for _, tc := range []struct {
|
||||
keyword string
|
||||
orderBy db.SearchOrderBy
|
||||
want []int64
|
||||
}{
|
||||
{"Foo", "", []int64{foo.ID, aafoo.ID, afoo.ID}},
|
||||
{"Foo", db.SearchOrderByID, []int64{afoo.ID, aafoo.ID, foo.ID}},
|
||||
{"user2/foo", "", []int64{foo.ID, afoo.ID, aafoo.ID}},
|
||||
} {
|
||||
repos, _, err := repo_model.SearchRepositoryByName(t.Context(), repo_model.SearchRepoOptions{Keyword: tc.keyword, OrderBy: tc.orderBy})
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, tc.want, repoIDs(repos), "%s %s", tc.keyword, tc.orderBy)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func testSearchRepositoryPublic(t *testing.T) {
|
||||
|
||||
Reference in new issue
Block a user