@@ -192,6 +192,8 @@ type SearchRepoOptions struct { | |||
// False -> include just no courses | |||
Course util.OptionalBool | |||
OnlySearchPrivate bool | |||
RepoIds []int64 | |||
} | |||
//SearchOrderBy is used to sort the result | |||
@@ -206,6 +208,7 @@ type FindReposResponse struct { | |||
Page int | |||
PageSize int | |||
Total int64 | |||
RepoIds []int64 | |||
} | |||
// Strings for sorting result | |||
@@ -281,6 +284,33 @@ func SearchRepositoryCondition(opts *SearchRepoOptions) builder.Cond { | |||
if opts.StarredByID > 0 { | |||
cond = cond.And(builder.In("id", builder.Select("repo_id").From("star").Where(builder.Eq{"uid": opts.StarredByID}))) | |||
} | |||
if len(opts.RepoIds) > 0 { | |||
const MaxINItems = 1000 | |||
if len(opts.RepoIds) <= MaxINItems { | |||
cond = cond.And(builder.In("id", opts.RepoIds)) | |||
} else { | |||
repoIdsMap := make(map[int][]int64, 0) | |||
i := 0 | |||
for j := 0; j < len(opts.RepoIds); j++ { | |||
if _, ok := repoIdsMap[i]; !ok { | |||
repoIdsMap[i] = make([]int64, 0) | |||
} | |||
repoIdsMap[i] = append(repoIdsMap[i], opts.RepoIds[j]) | |||
if (j+1)%MaxINItems == 0 { | |||
i += 1 | |||
} | |||
} | |||
subCond := builder.NewCond() | |||
for _, repoSplit := range repoIdsMap { | |||
subCond = subCond.Or(builder.In("id", repoSplit)) | |||
} | |||
cond = cond.And(subCond) | |||
} | |||
} | |||
// Restrict repositories to those the OwnerID owns or contributes to as per opts.Collaborate | |||
if opts.OwnerID > 0 { | |||
@@ -10,10 +10,11 @@ import ( | |||
) | |||
const ( | |||
TechHide = 1 | |||
TechShow = 2 | |||
TechShow = 1 | |||
TechHide = 2 | |||
TechMigrating = 3 | |||
TechMigrateFailed = 4 | |||
TechNotExist = 5 | |||
) | |||
const DefaultTechApprovedStatus = TechShow | |||
@@ -161,6 +162,16 @@ func GetProjectNames() []string { | |||
x.Table("tech_converge_base_info").Distinct("project_name").Find(&names) | |||
return names | |||
} | |||
func GetIdByProjectName(name string) []string { | |||
var ids []int64 | |||
x.Table("tech_converge_base_info").Cols("id").Where("project_name=?", name).Find(&ids) | |||
idStrs := make([]string, 0, len(ids)) | |||
for _, id := range ids { | |||
idStrs = append(idStrs, strconv.FormatInt(id, 10)) | |||
} | |||
return idStrs | |||
} | |||
func GetSummitRepoIds() []int64 { | |||
var ids []int64 | |||
x.Table("repo_converge_info").Cols("repo_id").Find(&ids) | |||
@@ -326,10 +337,37 @@ type TechRepoInfo struct { | |||
Repos []*RepoWithInstitution | |||
} | |||
func SearchTechRepoInfo(opt SearchTechOpt) ([]*TechRepoInfo, int64, error) { | |||
func GetAvailableRepoConvergeInfo(opt *SearchRepoOpt) ([]*RepoConvergeInfo, error) { | |||
repos := make([]*RepoConvergeInfo, 0) | |||
err := x.Table("repo_converge_info").Where(buildRepoFilterCond(opt)).Find(&repos) | |||
return repos, err | |||
} | |||
func buildRepoFilterCond(opt *SearchRepoOpt) string { | |||
sql := "" | |||
if opt.Institution != "" { | |||
sql += getPrefixWithoutWhere(sql) + " (institution like '%" + opt.Institution + ",%'" + " or institution like '%," + opt.Institution + "%'" + " or institution = '" + opt.Institution + "')" | |||
} | |||
if opt.ProjectName != "" { | |||
baseInfoIds := GetIdByProjectName(opt.ProjectName) | |||
if len(baseInfoIds) > 0 { | |||
sql += getPrefixWithoutWhere(sql) + " id in (" + strings.Join(baseInfoIds, ",") + ")" | |||
} | |||
} | |||
return sql | |||
} | |||
func SearchTechRepoInfo(opt *SearchTechOpt) ([]*TechRepoInfo, int64, error) { | |||
sql := `select a.*,COALESCE(b.count,0) as repo_count, COALESCE(b.max,0) as max from tech_converge_base_info a left join | |||
(select base_info_id,count(id),max(updated_unix) from repo_converge_info where status=2 GROUP BY base_info_id ) b | |||
(select base_info_id,count(id),max(updated_unix) from repo_converge_info where status=` + strconv.Itoa(TechShow) + ` GROUP BY base_info_id ) b | |||
on a.id=b.base_info_id` | |||
totalSql := "select count(*) from (" + sql + ") c" + buildTechFilterCond(opt) | |||
total, err := x.SQL(totalSql).Count(new(TechConvergeBaseInfo)) | |||
@@ -363,7 +401,7 @@ func SearchTechRepoInfo(opt SearchTechOpt) ([]*TechRepoInfo, int64, error) { | |||
} | |||
func buildTechFilterCond(opt SearchTechOpt) string { | |||
func buildTechFilterCond(opt *SearchTechOpt) string { | |||
sql := "" | |||
@@ -394,6 +432,13 @@ func getWherePrefix(sql string) string { | |||
return " and " | |||
} | |||
func getPrefixWithoutWhere(sql string) string { | |||
if sql == "" { | |||
return "" | |||
} | |||
return " and " | |||
} | |||
func loadRepoInfoForTech(list []*TechRepoInfo) { | |||
for _, techRepo := range list { | |||
@@ -47,11 +47,38 @@ func GetFilterInfo(ctx *context.APIContext) { | |||
func SearchRepoInfo(ctx *context.APIContext) { | |||
opts := &models.SearchRepoOpt{} | |||
opts.Q = ctx.Query("name") | |||
opts.ProjectName = ctx.Query("tech_name") | |||
opts.Topic = ctx.Query("topic") | |||
opts.Institution = ctx.Query("institution_name") | |||
page := ctx.QueryInt("page") | |||
if page <= 0 { | |||
page = 1 | |||
} | |||
opts.Page = page | |||
pageSize := ctx.QueryInt("pageSize") | |||
if pageSize <= 0 { | |||
pageSize = 30 | |||
} | |||
opts.PageSize = pageSize | |||
orderBy := ctx.Query("sort") | |||
opts.OrderBy = orderBy | |||
infos, total, err := techService.SearchRepoInfoWithInstitution(opts) | |||
if err != nil { | |||
log.Error("search has error", err) | |||
ctx.JSON(http.StatusOK, map[string]interface { | |||
}{"total": 0, "data": []*models.RepoWithInstitution{}}) | |||
} else { | |||
ctx.JSON(http.StatusOK, map[string]interface { | |||
}{"total": total, "data": infos}) | |||
} | |||
} | |||
func SearchTechProjectInfo(ctx *context.APIContext) { | |||
opts := models.SearchTechOpt{} | |||
opts := &models.SearchTechOpt{} | |||
opts.Q = ctx.Query("name") | |||
opts.ApplyYear = ctx.QueryInt("apply_year") | |||
opts.ExecuteYear = ctx.QueryInt("execute_year") | |||
@@ -67,7 +94,7 @@ func SearchTechProjectInfo(ctx *context.APIContext) { | |||
pageSize = 15 | |||
} | |||
opts.PageSize = pageSize | |||
orderBy := ctx.Query("orderBy") | |||
orderBy := ctx.Query("sort") | |||
if orderBy == "" || orderBy == "count" { | |||
opts.OrderBy = "order by repo_count desc, max desc " | |||
} else { | |||
@@ -169,6 +169,7 @@ type FindReposOptions struct { | |||
Topic string | |||
Private bool | |||
OwnerID int64 | |||
RepoIds []int64 | |||
} | |||
func FindRepos(opts FindReposOptions) (*models.FindReposResponse, error) { | |||
@@ -224,6 +225,7 @@ func FindRepos(opts FindReposOptions) (*models.FindReposResponse, error) { | |||
AllLimited: true, | |||
TopicName: opts.Topic, | |||
IncludeDescription: setting.UI.SearchRepoDescription, | |||
RepoIds: opts.RepoIds, | |||
}) | |||
if err != nil { | |||
log.Error("FindRepos error when SearchRepository.%v", err) | |||
@@ -1,6 +1,9 @@ | |||
package tech | |||
import "code.gitea.io/gitea/models" | |||
import ( | |||
"code.gitea.io/gitea/models" | |||
"code.gitea.io/gitea/services/repository" | |||
) | |||
func FindTech(opt models.FindTechOpt) ([]*models.TechConvergeBrief, error) { | |||
techList, err := models.FindTech(opt) | |||
@@ -14,6 +17,55 @@ func FindTech(opt models.FindTechOpt) ([]*models.TechConvergeBrief, error) { | |||
return r, nil | |||
} | |||
func SearchRepoInfoWithInstitution(opt *models.SearchRepoOpt) ([]*models.RepoWithInstitution, int64, error) { | |||
infos, err := models.GetAvailableRepoConvergeInfo(opt) | |||
if err != nil { | |||
return nil, 0, err | |||
} | |||
repoIds, institutionMap := getRepoIdAndInstitutionMap(infos) | |||
result, err := repository.FindRepos(repository.FindReposOptions{ | |||
ListOptions: models.ListOptions{Page: opt.Page, PageSize: opt.PageSize}, | |||
Sort: opt.OrderBy, | |||
Keyword: opt.Q, | |||
Topic: opt.Topic, | |||
RepoIds: repoIds, | |||
}) | |||
if err != nil { | |||
return nil, 0, err | |||
} | |||
repoResult := make([]*models.RepoWithInstitution, 0, len(result.Repos)) | |||
for _, repo := range result.Repos { | |||
repoResult = append(repoResult, &models.RepoWithInstitution{ | |||
ID: repo.ID, | |||
OwnerID: repo.OwnerID, | |||
OwnerName: repo.OwnerName, | |||
Name: repo.Name, | |||
Topics: repo.Topics, | |||
Description: repo.Description, | |||
Institution: institutionMap[repo.ID], | |||
UpdatedUnix: repo.UpdatedUnix, | |||
}) | |||
} | |||
return repoResult, result.Total, nil | |||
} | |||
func getRepoIdAndInstitutionMap(infos []*models.RepoConvergeInfo) ([]int64, map[int64]string) { | |||
repoIds := make([]int64, 0, len(infos)) | |||
institutionMap := make(map[int64]string, 0) | |||
// We only need the keys | |||
for _, info := range infos { | |||
repoIds = append(repoIds, info.RepoID) | |||
institutionMap[info.RepoID] = info.Institution | |||
} | |||
return repoIds, institutionMap | |||
} | |||
func IsValidRepoConvergeExists(repoId, baseInfoId int64) (bool, error) { | |||
list, err := models.GetRepoConverge(models.GetRepoConvergeOpts{ | |||
Status: []int{models.TechHide, models.TechShow, models.TechMigrating}, | |||