@@ -166,6 +166,8 @@ type SearchRepoOptions struct { | |||||
Archived util.OptionalBool | Archived util.OptionalBool | ||||
// only search topic name | // only search topic name | ||||
TopicOnly bool | TopicOnly bool | ||||
//search by Specific TopicName | |||||
TopicName string | |||||
// include description in keyword search | // include description in keyword search | ||||
IncludeDescription bool | IncludeDescription bool | ||||
// None -> include has milestones AND has no milestone | // None -> include has milestones AND has no milestone | ||||
@@ -327,6 +329,18 @@ func SearchRepositoryCondition(opts *SearchRepoOptions) builder.Cond { | |||||
} | } | ||||
cond = cond.And(keywordCond) | cond = cond.And(keywordCond) | ||||
} | } | ||||
if opts.TopicName != "" { | |||||
var subQueryCond = builder.NewCond() | |||||
subQueryCond = subQueryCond.Or(builder.Eq{"topic.name": opts.TopicName}) | |||||
subQuery := builder.Select("repo_topic.repo_id").From("repo_topic"). | |||||
Join("INNER", "topic", "topic.id = repo_topic.topic_id"). | |||||
Where(subQueryCond). | |||||
GroupBy("repo_topic.repo_id") | |||||
var topicNameCond = builder.In("id", subQuery) | |||||
cond = cond.And(topicNameCond) | |||||
} | |||||
if opts.Fork != util.OptionalBoolNone { | if opts.Fork != util.OptionalBoolNone { | ||||
cond = cond.And(builder.Eq{"is_fork": opts.Fork == util.OptionalBoolTrue}) | cond = cond.And(builder.Eq{"is_fork": opts.Fork == util.OptionalBoolTrue}) | ||||
@@ -87,7 +87,7 @@ write = Write | |||||
preview = Preview | preview = Preview | ||||
loading = Loading… | loading = Loading… | ||||
error404_index = Request forbidden by administrative rules | |||||
error404_index = Request forbidden by administrative rules | |||||
error500_index = Internal Server Error | error500_index = Internal Server Error | ||||
error404 = The page you are trying to reach either <strong>does not exist</strong> or <strong>you are not authorized</strong> to view it. | error404 = The page you are trying to reach either <strong>does not exist</strong> or <strong>you are not authorized</strong> to view it. | ||||
error500= Sorry, the site has encountered some problems, we are trying to <strong>fix the page</strong>, please try again later. | error500= Sorry, the site has encountered some problems, we are trying to <strong>fix the page</strong>, please try again later. | ||||
@@ -1246,6 +1246,11 @@ pulls.reject_count_1 = "%d change request" | |||||
pulls.reject_count_n = "%d change requests" | pulls.reject_count_n = "%d change requests" | ||||
pulls.waiting_count_1 = "%d waiting review" | pulls.waiting_count_1 = "%d waiting review" | ||||
pulls.waiting_count_n = "%d waiting reviews" | pulls.waiting_count_n = "%d waiting reviews" | ||||
pulls.commits_count_1=This branch is %d commit behind the upstream. | |||||
pulls.commits_count_n=This branch is %d commit behind the upstream. | |||||
pulls.fetch_upstream=Fetch upstream | |||||
pulls.upstream_up_to_date=No new commits to fetch | |||||
pulls.upstream_error=Cannot get upstream info | |||||
pulls.no_merge_desc = This pull request cannot be merged because all repository merge options are disabled. | pulls.no_merge_desc = This pull request cannot be merged because all repository merge options are disabled. | ||||
pulls.no_merge_helper = Enable merge options in the repository settings or merge the pull request manually. | pulls.no_merge_helper = Enable merge options in the repository settings or merge the pull request manually. | ||||
@@ -1248,6 +1248,11 @@ pulls.reject_count_1=%d 变更请求 | |||||
pulls.reject_count_n=%d 变更请求 | pulls.reject_count_n=%d 变更请求 | ||||
pulls.waiting_count_1=%d 个正在等待审核 | pulls.waiting_count_1=%d 个正在等待审核 | ||||
pulls.waiting_count_n=%d 个正在等待审核 | pulls.waiting_count_n=%d 个正在等待审核 | ||||
pulls.commits_count_1=当前分支落后上游分支 %d 个提交 | |||||
pulls.commits_count_n=当前分支落后上游分支 %d 个提交 | |||||
pulls.fetch_upstream=拉取上游更新 | |||||
pulls.upstream_up_to_date=上游分支没有新的更新 | |||||
pulls.upstream_error=获取上游分支信息错误 | |||||
pulls.no_merge_desc=由于未启用合并选项,此合并请求无法被合并。 | pulls.no_merge_desc=由于未启用合并选项,此合并请求无法被合并。 | ||||
pulls.no_merge_helper=在项目设置中启用合并选项或者手工合并请求。 | pulls.no_merge_helper=在项目设置中启用合并选项或者手工合并请求。 | ||||
@@ -149,8 +149,7 @@ func RenderRepoSearch(ctx *context.Context, opts *RepoSearchOptions) { | |||||
//todo:support other topics | //todo:support other topics | ||||
keyword := strings.Trim(ctx.Query("q"), " ") | keyword := strings.Trim(ctx.Query("q"), " ") | ||||
topicOnly := ctx.QueryBool("topic") | |||||
ctx.Data["TopicOnly"] = topicOnly | |||||
topic := strings.Trim(ctx.Query("topic"), " ") | |||||
repos, count, err = models.SearchRepository(&models.SearchRepoOptions{ | repos, count, err = models.SearchRepository(&models.SearchRepoOptions{ | ||||
ListOptions: models.ListOptions{ | ListOptions: models.ListOptions{ | ||||
@@ -164,7 +163,7 @@ func RenderRepoSearch(ctx *context.Context, opts *RepoSearchOptions) { | |||||
OwnerID: opts.OwnerID, | OwnerID: opts.OwnerID, | ||||
AllPublic: true, | AllPublic: true, | ||||
AllLimited: true, | AllLimited: true, | ||||
TopicOnly: topicOnly, | |||||
TopicName: topic, | |||||
IncludeDescription: setting.UI.SearchRepoDescription, | IncludeDescription: setting.UI.SearchRepoDescription, | ||||
}) | }) | ||||
if err != nil { | if err != nil { | ||||
@@ -177,6 +176,8 @@ func RenderRepoSearch(ctx *context.Context, opts *RepoSearchOptions) { | |||||
repo.Active = int64(repo.NumIssues) + int64(repo.NumPulls) + int64(repo.NumCommit) | repo.Active = int64(repo.NumIssues) + int64(repo.NumPulls) + int64(repo.NumCommit) | ||||
} | } | ||||
ctx.Data["Keyword"] = keyword | ctx.Data["Keyword"] = keyword | ||||
ctx.Data["Topic"] = topic | |||||
ctx.Data["Total"] = count | ctx.Data["Total"] = count | ||||
ctx.Data["Repos"] = repos | ctx.Data["Repos"] = repos | ||||
ctx.Data["IsRepoIndexerEnabled"] = setting.Indexer.RepoIndexerEnabled | ctx.Data["IsRepoIndexerEnabled"] = setting.Indexer.RepoIndexerEnabled | ||||
@@ -790,6 +790,44 @@ func renderCode(ctx *context.Context) { | |||||
} | } | ||||
} | } | ||||
//如果是fork的仓库 | |||||
if ctx.Repo.Repository.IsFork { | |||||
//获得fetchUpstream对应的分支参数 | |||||
/* | |||||
// 1. /{:baseOwner}/{:baseRepoName}/compare/{:baseBranch}...{:headBranch} | |||||
// 2. /{:baseOwner}/{:baseRepoName}/compare/{:baseBranch}...{:headOwner}:{:headBranch} | |||||
// 3. /{:baseOwner}/{:baseRepoName}/compare/{:baseBranch}...{:headOwner}/{:headRepoName}:{:headBranch} | |||||
*/ | |||||
baseGitRepo, err := git.OpenRepository(ctx.Repo.Repository.BaseRepo.RepoPath()) | |||||
defer baseGitRepo.Close() | |||||
if err != nil { | |||||
log.Error("error open baseRepo:%s",ctx.Repo.Repository.BaseRepo.RepoPath()) | |||||
ctx.Data["FetchUpstreamCnt"] = -1 // minus value indicates error | |||||
}else{ | |||||
if _,error:= baseGitRepo.GetBranch(ctx.Repo.BranchName);error==nil{ | |||||
//base repo has the same branch, then compare between current repo branch and base repo's branch | |||||
compareUrl := ctx.Repo.BranchName + "..." + ctx.Repo.Repository.BaseRepo.OwnerName + "/" + ctx.Repo.Repository.BaseRepo.Name + ":" + ctx.Repo.BranchName | |||||
ctx.SetParams("*",compareUrl) | |||||
}else{ | |||||
//else, compare between current repo branch and base repo's default branch | |||||
compareUrl := ctx.Repo.BranchName + "..." + ctx.Repo.Repository.BaseRepo.OwnerName + "/" + ctx.Repo.Repository.BaseRepo.Name + ":" + ctx.Repo.Repository.BaseRepo.DefaultBranch | |||||
ctx.SetParams("*",compareUrl) | |||||
} | |||||
_, _, headGitRepo, compareInfo, _, _ := ParseCompareInfo(ctx) | |||||
defer headGitRepo.Close() | |||||
if compareInfo!= nil { | |||||
if compareInfo.Commits!=nil { | |||||
log.Info("compareInfoCommits数量:%d",compareInfo.Commits.Len()) | |||||
ctx.Data["FetchUpstreamCnt"] = compareInfo.Commits.Len() | |||||
}else{ | |||||
log.Info("compareInfo nothing different") | |||||
ctx.Data["FetchUpstreamCnt"] = 0 | |||||
} | |||||
}else{ | |||||
ctx.Data["FetchUpstreamCnt"] = -1 // minus value indicates error | |||||
} | |||||
} | |||||
} | |||||
ctx.Data["Paths"] = paths | ctx.Data["Paths"] = paths | ||||
ctx.Data["TreeLink"] = treeLink | ctx.Data["TreeLink"] = treeLink | ||||
ctx.Data["TreeNames"] = treeNames | ctx.Data["TreeNames"] = treeNames | ||||
@@ -154,6 +154,21 @@ | |||||
<a href="{{.BaseRepo.Link}}/compare/{{.BaseRepo.DefaultBranch | EscapePound}}...{{if ne .Repository.Owner.Name .BaseRepo.Owner.Name}}{{.Repository.Owner.Name}}:{{end}}{{.BranchName | EscapePound}}"> | <a href="{{.BaseRepo.Link}}/compare/{{.BaseRepo.DefaultBranch | EscapePound}}...{{if ne .Repository.Owner.Name .BaseRepo.Owner.Name}}{{.Repository.Owner.Name}}:{{end}}{{.BranchName | EscapePound}}"> | ||||
<button id="new-pull-request" class="ui compact basic button">{{if .PullRequestCtx.Allowed}}{{.i18n.Tr "repo.pulls.compare_changes"}}{{else}}{{.i18n.Tr "action.compare_branch"}}{{end}}</button> | <button id="new-pull-request" class="ui compact basic button">{{if .PullRequestCtx.Allowed}}{{.i18n.Tr "repo.pulls.compare_changes"}}{{else}}{{.i18n.Tr "action.compare_branch"}}{{end}}</button> | ||||
</a> | </a> | ||||
{{if and .Repository.IsFork .PullRequestCtx.Allowed}} | |||||
{{if gt .FetchUpstreamCnt 0 }} | |||||
<a href="{{.Repository.Link}}/compare/{{.BranchName | EscapePound}}...{{.BaseRepo.Owner.Name}}:{{.BaseRepo.DefaultBranch | EscapePound}}"> | |||||
<button id="new-pull-request" class="ui compact basic button" title="{{$.i18n.Tr (TrN $.i18n.Lang .FetchUpstreamCnt "repo.pulls.commits_count_1" "repo.pulls.commits_count_n") .FetchUpstreamCnt}}">{{.i18n.Tr "repo.pulls.fetch_upstream"}}</button> | |||||
</a> | |||||
{{else if lt .FetchUpstreamCnt 0}} | |||||
<a href="{{.Repository.Link}}/compare/{{.BranchName | EscapePound}}...{{.BaseRepo.Owner.Name}}:{{.BaseRepo.DefaultBranch | EscapePound}}"> | |||||
<button id="new-pull-request" class="ui compact basic button" title="{{.i18n.Tr "repo.pulls.upstream_error"}}">{{.i18n.Tr "repo.pulls.fetch_upstream"}}</button> | |||||
</a> | |||||
{{else}} | |||||
<a href="{{.Repository.Link}}/compare/{{.BranchName | EscapePound}}...{{.BaseRepo.Owner.Name}}:{{.BaseRepo.DefaultBranch | EscapePound}}"> | |||||
<button id="new-pull-request" class="ui compact basic button" title="{{.i18n.Tr "repo.pulls.upstream_up_to_date"}}">{{.i18n.Tr "repo.pulls.fetch_upstream"}}</button> | |||||
</a> | |||||
{{end}} | |||||
{{end}} | |||||
</div> | </div> | ||||
{{end}} | {{end}} | ||||
{{else}} | {{else}} | ||||
@@ -3,12 +3,7 @@ | |||||
{{template "repo/header" .}} | {{template "repo/header" .}} | ||||
<div class="ui container"> | <div class="ui container"> | ||||
<div class="ui three column stackable grid"> | <div class="ui three column stackable grid"> | ||||
<div class="column" style="display: flex;align-items: center;"> | |||||
<div class="ui large breadcrumb"> | |||||
<a href="{{.RepoLink}}/issues">{{.i18n.Tr "repo.issues"}}</a> | |||||
<div class="divider"> / </div> | |||||
</div> | |||||
<div class="column" style="display: flex;align-items: center;"> | |||||
</div> | </div> | ||||
<div class="column center aligned"> | <div class="column center aligned"> | ||||
{{template "repo/issue/search" .}} | {{template "repo/issue/search" .}} | ||||
@@ -197,13 +197,13 @@ export default { | |||||
}) | }) | ||||
}, | }, | ||||
postTopic(){ | postTopic(){ | ||||
const patter = /^[\u4e00-\u9fa5a-z0-9][\u4e00-\u9fa5a-zA-Z0-9-]{0,35}$/ | |||||
const patter = /^[\u4e00-\u9fa5a-zA-Z0-9][\u4e00-\u9fa5a-zA-Z0-9-]{0,34}$/ | |||||
let regexp = patter.test(this.input) | let regexp = patter.test(this.input) | ||||
console.log("regexp",regexp) | console.log("regexp",regexp) | ||||
if(!regexp){ | if(!regexp){ | ||||
this.$notify({ | this.$notify({ | ||||
message: '主题必须以中文、字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符', | |||||
message: '标签名必须以中文、字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符', | |||||
duration: 3000, | duration: 3000, | ||||
type:'error' | type:'error' | ||||
}); | }); | ||||