Skip to content

Commit

Permalink
Add user/organization code search (#19977)
Browse files Browse the repository at this point in the history
  • Loading branch information
lafriks authored Oct 10, 2022
1 parent 3ccebf7 commit b59b0ca
Show file tree
Hide file tree
Showing 19 changed files with 341 additions and 145 deletions.
30 changes: 20 additions & 10 deletions models/repo/repo_list.go
Original file line number Diff line number Diff line change
Expand Up @@ -593,6 +593,16 @@ func searchRepositoryByCondition(ctx context.Context, opts *SearchRepoOptions, c
return sess, count, nil
}

// SearchRepositoryIDsByCondition search repository IDs by given condition.
func SearchRepositoryIDsByCondition(ctx context.Context, cond builder.Cond) ([]int64, error) {
repoIDs := make([]int64, 0, 10)
return repoIDs, db.GetEngine(ctx).
Table("repository").
Cols("id").
Where(cond).
Find(&repoIDs)
}

// AccessibleRepositoryCondition takes a user a returns a condition for checking if a repository is accessible
func AccessibleRepositoryCondition(user *user_model.User, unitType unit.Type) builder.Cond {
cond := builder.NewCond()
Expand Down Expand Up @@ -680,16 +690,16 @@ func AccessibleRepoIDsQuery(user *user_model.User) *builder.Builder {
}

// FindUserCodeAccessibleRepoIDs finds all at Code level accessible repositories' ID by the user's id
func FindUserCodeAccessibleRepoIDs(user *user_model.User) ([]int64, error) {
repoIDs := make([]int64, 0, 10)
if err := db.GetEngine(db.DefaultContext).
Table("repository").
Cols("id").
Where(AccessibleRepositoryCondition(user, unit.TypeCode)).
Find(&repoIDs); err != nil {
return nil, fmt.Errorf("FindUserCodeAccesibleRepoIDs: %v", err)
}
return repoIDs, nil
func FindUserCodeAccessibleRepoIDs(ctx context.Context, user *user_model.User) ([]int64, error) {
return SearchRepositoryIDsByCondition(ctx, AccessibleRepositoryCondition(user, unit.TypeCode))
}

// FindUserCodeAccessibleOwnerRepoIDs finds all repository IDs for the given owner whose code the user can see.
func FindUserCodeAccessibleOwnerRepoIDs(ctx context.Context, ownerID int64, user *user_model.User) ([]int64, error) {
return SearchRepositoryIDsByCondition(ctx, builder.NewCond().And(
builder.Eq{"owner_id": ownerID},
AccessibleRepositoryCondition(user, unit.TypeCode),
))
}

// GetUserRepositories returns a list of repositories of given user.
Expand Down
1 change: 1 addition & 0 deletions modules/context/org.go
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,7 @@ func HandleOrgAssignment(ctx *Context, args ...bool) {
ctx.Data["IsOrganizationOwner"] = ctx.Org.IsOwner
ctx.Data["IsOrganizationMember"] = ctx.Org.IsMember
ctx.Data["IsPackageEnabled"] = setting.Packages.Enabled
ctx.Data["IsRepoIndexerEnabled"] = setting.Indexer.RepoIndexerEnabled
ctx.Data["IsPublicMember"] = func(uid int64) bool {
is, _ := organization.IsPublicMembership(ctx.Org.Organization.ID, uid)
return is
Expand Down
8 changes: 8 additions & 0 deletions options/locale/locale_en-US.ini
Original file line number Diff line number Diff line change
Expand Up @@ -268,8 +268,11 @@ users = Users
organizations = Organizations
search = Search
code = Code
search.type.tooltip = Search type
search.fuzzy = Fuzzy
search.fuzzy.tooltip = Include results that also matches the search term closely
search.match = Match
search.match.tooltip = Include only results that matches the exact search term
code_search_unavailable = Currently code search is not available. Please contact your site administrator.
repo_no_results = No matching repositories found.
user_no_results = No matching users found.
Expand Down Expand Up @@ -507,6 +510,7 @@ activity = Public Activity
followers = Followers
starred = Starred Repositories
watched = Watched Repositories
code = Code
projects = Projects
following = Following
follow = Follow
Expand Down Expand Up @@ -1763,8 +1767,11 @@ activity.git_stats_deletion_n = %d deletions

search = Search
search.search_repo = Search repository
search.type.tooltip = Search type
search.fuzzy = Fuzzy
search.fuzzy.tooltip = Include results that also matches the search term closely
search.match = Match
search.match.tooltip = Include only results that matches the exact search term
search.results = Search results for "%s" in <a href="%s">%s</a>
search.code_no_results = No source code matching your search term found.
search.code_search_unavailable = Currently code search is not available. Please contact your site administrator.
Expand Down Expand Up @@ -2310,6 +2317,7 @@ create_org = Create Organization
repo_updated = Updated
people = People
teams = Teams
code = Code
lower_members = members
lower_repositories = repositories
create_new_team = New Team
Expand Down
125 changes: 65 additions & 60 deletions routers/web/explore/code.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,86 +34,91 @@ func Code(ctx *context.Context) {

language := ctx.FormTrim("l")
keyword := ctx.FormTrim("q")

queryType := ctx.FormTrim("t")
isMatch := queryType == "match"

ctx.Data["Keyword"] = keyword
ctx.Data["Language"] = language
ctx.Data["queryType"] = queryType
ctx.Data["PageIsViewCode"] = true

if keyword == "" {
ctx.HTML(http.StatusOK, tplExploreCode)
return
}

page := ctx.FormInt("page")
if page <= 0 {
page = 1
}

queryType := ctx.FormTrim("t")
isMatch := queryType == "match"
var (
repoIDs []int64
err error
isAdmin bool
)
if ctx.Doer != nil {
isAdmin = ctx.Doer.IsAdmin
}

if keyword != "" {
var (
repoIDs []int64
err error
isAdmin bool
)
if ctx.Doer != nil {
isAdmin = ctx.Doer.IsAdmin
// guest user or non-admin user
if ctx.Doer == nil || !isAdmin {
repoIDs, err = repo_model.FindUserCodeAccessibleRepoIDs(ctx, ctx.Doer)
if err != nil {
ctx.ServerError("FindUserCodeAccessibleRepoIDs", err)
return
}
}

// guest user or non-admin user
if ctx.Doer == nil || !isAdmin {
repoIDs, err = repo_model.FindUserCodeAccessibleRepoIDs(ctx.Doer)
if err != nil {
var (
total int
searchResults []*code_indexer.Result
searchResultLanguages []*code_indexer.SearchResultLanguages
)

if (len(repoIDs) > 0) || isAdmin {
total, searchResults, searchResultLanguages, err = code_indexer.PerformSearch(ctx, repoIDs, language, keyword, page, setting.UI.RepoSearchPagingNum, isMatch)
if err != nil {
if code_indexer.IsAvailable() {
ctx.ServerError("SearchResults", err)
return
}
ctx.Data["CodeIndexerUnavailable"] = true
} else {
ctx.Data["CodeIndexerUnavailable"] = !code_indexer.IsAvailable()
}

var (
total int
searchResults []*code_indexer.Result
searchResultLanguages []*code_indexer.SearchResultLanguages
)

if (len(repoIDs) > 0) || isAdmin {
total, searchResults, searchResultLanguages, err = code_indexer.PerformSearch(ctx, repoIDs, language, keyword, page, setting.UI.RepoSearchPagingNum, isMatch)
if err != nil {
if code_indexer.IsAvailable() {
ctx.ServerError("SearchResults", err)
return
loadRepoIDs := make([]int64, 0, len(searchResults))
for _, result := range searchResults {
var find bool
for _, id := range loadRepoIDs {
if id == result.RepoID {
find = true
break
}
ctx.Data["CodeIndexerUnavailable"] = true
} else {
ctx.Data["CodeIndexerUnavailable"] = !code_indexer.IsAvailable()
}

loadRepoIDs := make([]int64, 0, len(searchResults))
for _, result := range searchResults {
var find bool
for _, id := range loadRepoIDs {
if id == result.RepoID {
find = true
break
}
}
if !find {
loadRepoIDs = append(loadRepoIDs, result.RepoID)
}
}

repoMaps, err := repo_model.GetRepositoriesMapByIDs(loadRepoIDs)
if err != nil {
ctx.ServerError("SearchResults", err)
return
if !find {
loadRepoIDs = append(loadRepoIDs, result.RepoID)
}
}

ctx.Data["RepoMaps"] = repoMaps
repoMaps, err := repo_model.GetRepositoriesMapByIDs(loadRepoIDs)
if err != nil {
ctx.ServerError("GetRepositoriesMapByIDs", err)
return
}

ctx.Data["Keyword"] = keyword
ctx.Data["Language"] = language
ctx.Data["queryType"] = queryType
ctx.Data["SearchResults"] = searchResults
ctx.Data["SearchResultLanguages"] = searchResultLanguages
ctx.Data["PageIsViewCode"] = true

pager := context.NewPagination(total, setting.UI.RepoSearchPagingNum, page, 5)
pager.SetDefaultParams(ctx)
pager.AddParam(ctx, "l", "Language")
ctx.Data["Page"] = pager
ctx.Data["RepoMaps"] = repoMaps
}

ctx.Data["SearchResults"] = searchResults
ctx.Data["SearchResultLanguages"] = searchResultLanguages

pager := context.NewPagination(total, setting.UI.RepoSearchPagingNum, page, 5)
pager.SetDefaultParams(ctx)
pager.AddParam(ctx, "l", "Language")
ctx.Data["Page"] = pager

ctx.HTML(http.StatusOK, tplExploreCode)
}
22 changes: 16 additions & 6 deletions routers/web/repo/search.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,14 +21,27 @@ func Search(ctx *context.Context) {
ctx.Redirect(ctx.Repo.RepoLink)
return
}

language := ctx.FormTrim("l")
keyword := ctx.FormTrim("q")

queryType := ctx.FormTrim("t")
isMatch := queryType == "match"

ctx.Data["Keyword"] = keyword
ctx.Data["Language"] = language
ctx.Data["queryType"] = queryType
ctx.Data["PageIsViewCode"] = true

if keyword == "" {
ctx.HTML(http.StatusOK, tplSearch)
return
}

page := ctx.FormInt("page")
if page <= 0 {
page = 1
}
queryType := ctx.FormTrim("t")
isMatch := queryType == "match"

total, searchResults, searchResultLanguages, err := code_indexer.PerformSearch(ctx, []int64{ctx.Repo.Repository.ID},
language, keyword, page, setting.UI.RepoSearchPagingNum, isMatch)
Expand All @@ -41,13 +54,10 @@ func Search(ctx *context.Context) {
} else {
ctx.Data["CodeIndexerUnavailable"] = !code_indexer.IsAvailable()
}
ctx.Data["Keyword"] = keyword
ctx.Data["Language"] = language
ctx.Data["queryType"] = queryType

ctx.Data["SourcePath"] = ctx.Repo.Repository.HTMLURL()
ctx.Data["SearchResults"] = searchResults
ctx.Data["SearchResultLanguages"] = searchResultLanguages
ctx.Data["PageIsViewCode"] = true

pager := context.NewPagination(total, setting.UI.RepoSearchPagingNum, page, 5)
pager.SetDefaultParams(ctx)
Expand Down
Loading

0 comments on commit b59b0ca

Please sign in to comment.