@ -10,8 +10,10 @@ import (
"crypto/subtle"
"crypto/subtle"
"errors"
"errors"
"fmt"
"fmt"
"html"
"net/http"
"net/http"
"path"
"net/url"
"strconv"
"strings"
"strings"
"time"
"time"
@ -34,7 +36,6 @@ import (
"code.gitea.io/gitea/services/gitdiff"
"code.gitea.io/gitea/services/gitdiff"
pull_service "code.gitea.io/gitea/services/pull"
pull_service "code.gitea.io/gitea/services/pull"
repo_service "code.gitea.io/gitea/services/repository"
repo_service "code.gitea.io/gitea/services/repository"
"github.com/unknwon/com"
)
)
const (
const (
@ -109,8 +110,7 @@ func getForkRepository(ctx *context.Context) *models.Repository {
ctx . Data [ "IsPrivate" ] = forkRepo . IsPrivate || forkRepo . Owner . Visibility == structs . VisibleTypePrivate
ctx . Data [ "IsPrivate" ] = forkRepo . IsPrivate || forkRepo . Owner . Visibility == structs . VisibleTypePrivate
canForkToUser := forkRepo . OwnerID != ctx . User . ID && ! ctx . User . HasForkedRepo ( forkRepo . ID )
canForkToUser := forkRepo . OwnerID != ctx . User . ID && ! ctx . User . HasForkedRepo ( forkRepo . ID )
ctx . Data [ "ForkFrom" ] = forkRepo . Owner . Name + "/" + forkRepo . Name
ctx . Data [ "ForkRepo" ] = forkRepo
ctx . Data [ "ForkFromOwnerID" ] = forkRepo . Owner . ID
if err := ctx . User . GetOwnedOrganizations ( ) ; err != nil {
if err := ctx . User . GetOwnedOrganizations ( ) ; err != nil {
ctx . ServerError ( "GetOwnedOrganizations" , err )
ctx . ServerError ( "GetOwnedOrganizations" , err )
@ -202,7 +202,7 @@ func ForkPost(ctx *context.Context) {
}
}
repo , has := models . HasForkedRepo ( ctxUser . ID , traverseParentRepo . ID )
repo , has := models . HasForkedRepo ( ctxUser . ID , traverseParentRepo . ID )
if has {
if has {
ctx . Redirect ( ctxUser . HomeLink ( ) + "/" + repo . Name )
ctx . Redirect ( ctxUser . HomeLink ( ) + "/" + url . PathEscape ( repo . Name ) )
return
return
}
}
if ! traverseParentRepo . IsFork {
if ! traverseParentRepo . IsFork {
@ -248,7 +248,7 @@ func ForkPost(ctx *context.Context) {
}
}
log . Trace ( "Repository forked[%d]: %s/%s" , forkRepo . ID , ctxUser . Name , repo . Name )
log . Trace ( "Repository forked[%d]: %s/%s" , forkRepo . ID , ctxUser . Name , repo . Name )
ctx . Redirect ( ctxUser . HomeLink ( ) + "/" + repo . Name )
ctx . Redirect ( ctxUser . HomeLink ( ) + "/" + url . PathEscape ( repo . Name ) )
}
}
func checkPullInfo ( ctx * context . Context ) * models . Issue {
func checkPullInfo ( ctx * context . Context ) * models . Issue {
@ -682,8 +682,7 @@ func ViewPullFiles(ctx *context.Context) {
}
}
}
}
headTarget := path . Join ( ctx . Repo . Owner . Name , ctx . Repo . Repository . Name )
setCompareContext ( ctx , baseCommit , commit , ctx . Repo . Owner . Name , ctx . Repo . Repository . Name )
setCompareContext ( ctx , baseCommit , commit , headTarget )
ctx . Data [ "RequireHighlightJS" ] = true
ctx . Data [ "RequireHighlightJS" ] = true
ctx . Data [ "RequireSimpleMDE" ] = true
ctx . Data [ "RequireSimpleMDE" ] = true
@ -746,7 +745,7 @@ func UpdatePullRequest(ctx *context.Context) {
// ToDo: add check if maintainers are allowed to change branch ... (need migration & co)
// ToDo: add check if maintainers are allowed to change branch ... (need migration & co)
if ( ! allowedUpdateByMerge && ! rebase ) || ( rebase && ! allowedUpdateByRebase ) {
if ( ! allowedUpdateByMerge && ! rebase ) || ( rebase && ! allowedUpdateByRebase ) {
ctx . Flash . Error ( ctx . Tr ( "repo.pulls.update_not_allowed" ) )
ctx . Flash . Error ( ctx . Tr ( "repo.pulls.update_not_allowed" ) )
ctx . Redirect ( ctx . Repo . RepoLink + "/pulls/" + fmt . Sprint ( issue . Index ) )
ctx . Redirect ( issue . Link ( ) )
return
return
}
}
@ -766,7 +765,7 @@ func UpdatePullRequest(ctx *context.Context) {
return
return
}
}
ctx . Flash . Error ( flashError )
ctx . Flash . Error ( flashError )
ctx . Redirect ( ctx . Repo . RepoLink + "/pulls/" + fmt . Sprint ( issue . Index ) )
ctx . Redirect ( issue . Link ( ) )
return
return
} else if models . IsErrRebaseConflicts ( err ) {
} else if models . IsErrRebaseConflicts ( err ) {
conflictError := err . ( models . ErrRebaseConflicts )
conflictError := err . ( models . ErrRebaseConflicts )
@ -780,19 +779,19 @@ func UpdatePullRequest(ctx *context.Context) {
return
return
}
}
ctx . Flash . Error ( flashError )
ctx . Flash . Error ( flashError )
ctx . Redirect ( ctx . Repo . RepoLink + "/pulls/" + fmt . Sprint ( issue . Index ) )
ctx . Redirect ( issue . Link ( ) )
return
return
}
}
ctx . Flash . Error ( err . Error ( ) )
ctx . Flash . Error ( err . Error ( ) )
ctx . Redirect ( ctx . Repo . RepoLink + "/pulls/" + fmt . Sprint ( issue . Index ) )
ctx . Redirect ( issue . Link ( ) )
return
return
}
}
time . Sleep ( 1 * time . Second )
time . Sleep ( 1 * time . Second )
ctx . Flash . Success ( ctx . Tr ( "repo.pulls.update_branch_success" ) )
ctx . Flash . Success ( ctx . Tr ( "repo.pulls.update_branch_success" ) )
ctx . Redirect ( ctx . Repo . RepoLink + "/pulls/" + fmt . Sprint ( issue . Index ) )
ctx . Redirect ( issue . Link ( ) )
}
}
// MergePullRequest response for merging pull request
// MergePullRequest response for merging pull request
@ -805,11 +804,11 @@ func MergePullRequest(ctx *context.Context) {
if issue . IsClosed {
if issue . IsClosed {
if issue . IsPull {
if issue . IsPull {
ctx . Flash . Error ( ctx . Tr ( "repo.pulls.is_closed" ) )
ctx . Flash . Error ( ctx . Tr ( "repo.pulls.is_closed" ) )
ctx . Redirect ( ctx . Repo . RepoLink + "/pulls/" + fmt . Sprint ( issue . Index ) )
ctx . Redirect ( issue . Link ( ) )
return
return
}
}
ctx . Flash . Error ( ctx . Tr ( "repo.issues.closed_title" ) )
ctx . Flash . Error ( ctx . Tr ( "repo.issues.closed_title" ) )
ctx . Redirect ( ctx . Repo . RepoLink + "/issues/" + fmt . Sprint ( issue . Index ) )
ctx . Redirect ( issue . Link ( ) )
return
return
}
}
@ -822,13 +821,13 @@ func MergePullRequest(ctx *context.Context) {
}
}
if ! allowedMerge {
if ! allowedMerge {
ctx . Flash . Error ( ctx . Tr ( "repo.pulls.update_not_allowed" ) )
ctx . Flash . Error ( ctx . Tr ( "repo.pulls.update_not_allowed" ) )
ctx . Redirect ( ctx . Repo . RepoLink + "/pulls/" + fmt . Sprint ( issue . Index ) )
ctx . Redirect ( issue . Link ( ) )
return
return
}
}
if pr . HasMerged {
if pr . HasMerged {
ctx . Flash . Error ( ctx . Tr ( "repo.pulls.has_merged" ) )
ctx . Flash . Error ( ctx . Tr ( "repo.pulls.has_merged" ) )
ctx . Redirect ( ctx . Repo . RepoLink + "/pulls/" + com . ToStr ( issue . Index ) )
ctx . Redirect ( issue . Link ( ) )
return
return
}
}
@ -837,11 +836,11 @@ func MergePullRequest(ctx *context.Context) {
if err = pull_service . MergedManually ( pr , ctx . User , ctx . Repo . GitRepo , form . MergeCommitID ) ; err != nil {
if err = pull_service . MergedManually ( pr , ctx . User , ctx . Repo . GitRepo , form . MergeCommitID ) ; err != nil {
if models . IsErrInvalidMergeStyle ( err ) {
if models . IsErrInvalidMergeStyle ( err ) {
ctx . Flash . Error ( ctx . Tr ( "repo.pulls.invalid_merge_option" ) )
ctx . Flash . Error ( ctx . Tr ( "repo.pulls.invalid_merge_option" ) )
ctx . Redirect ( ctx . Repo . RepoLink + "/pulls/" + com . ToStr ( issue . Index ) )
ctx . Redirect ( issue . Link ( ) )
return
return
} else if strings . Contains ( err . Error ( ) , "Wrong commit ID" ) {
} else if strings . Contains ( err . Error ( ) , "Wrong commit ID" ) {
ctx . Flash . Error ( ctx . Tr ( "repo.pulls.wrong_commit_id" ) )
ctx . Flash . Error ( ctx . Tr ( "repo.pulls.wrong_commit_id" ) )
ctx . Redirect ( ctx . Repo . RepoLink + "/pulls/" + com . ToStr ( issue . Index ) )
ctx . Redirect ( issue . Link ( ) )
return
return
}
}
@ -849,19 +848,19 @@ func MergePullRequest(ctx *context.Context) {
return
return
}
}
ctx . Redirect ( ctx . Repo . RepoLink + "/pulls/" + com . ToStr ( issue . Index ) )
ctx . Redirect ( issue . Link ( ) )
return
return
}
}
if ! pr . CanAutoMerge ( ) {
if ! pr . CanAutoMerge ( ) {
ctx . Flash . Error ( ctx . Tr ( "repo.pulls.no_merge_not_ready" ) )
ctx . Flash . Error ( ctx . Tr ( "repo.pulls.no_merge_not_ready" ) )
ctx . Redirect ( ctx . Repo . RepoLink + "/pulls/" + com . ToStr ( issue . Index ) )
ctx . Redirect ( issue . Link ( ) )
return
return
}
}
if pr . IsWorkInProgress ( ) {
if pr . IsWorkInProgress ( ) {
ctx . Flash . Error ( ctx . Tr ( "repo.pulls.no_merge_wip" ) )
ctx . Flash . Error ( ctx . Tr ( "repo.pulls.no_merge_wip" ) )
ctx . Redirect ( ctx . Repo . RepoLink + "/pulls/" + fmt . Sprint ( pr . Index ) )
ctx . Redirect ( issue . Link ( ) )
return
return
}
}
@ -875,14 +874,14 @@ func MergePullRequest(ctx *context.Context) {
return
return
} else if ! isRepoAdmin {
} else if ! isRepoAdmin {
ctx . Flash . Error ( ctx . Tr ( "repo.pulls.no_merge_not_ready" ) )
ctx . Flash . Error ( ctx . Tr ( "repo.pulls.no_merge_not_ready" ) )
ctx . Redirect ( ctx . Repo . RepoLink + "/pulls/" + fmt . Sprint ( pr . Index ) )
ctx . Redirect ( issue . Link ( ) )
return
return
}
}
}
}
if ctx . HasError ( ) {
if ctx . HasError ( ) {
ctx . Flash . Error ( ctx . Data [ "ErrorMsg" ] . ( string ) )
ctx . Flash . Error ( ctx . Data [ "ErrorMsg" ] . ( string ) )
ctx . Redirect ( ctx . Repo . RepoLink + "/pulls/" + fmt . Sprint ( pr . Index ) )
ctx . Redirect ( issue . Link ( ) )
return
return
}
}
@ -914,14 +913,14 @@ func MergePullRequest(ctx *context.Context) {
if ! noDeps {
if ! noDeps {
ctx . Flash . Error ( ctx . Tr ( "repo.issues.dependency.pr_close_blocked" ) )
ctx . Flash . Error ( ctx . Tr ( "repo.issues.dependency.pr_close_blocked" ) )
ctx . Redirect ( ctx . Repo . RepoLink + "/pulls/" + fmt . Sprint ( pr . Index ) )
ctx . Redirect ( issue . Link ( ) )
return
return
}
}
if err = pull_service . Merge ( pr , ctx . User , ctx . Repo . GitRepo , models . MergeStyle ( form . Do ) , message ) ; err != nil {
if err = pull_service . Merge ( pr , ctx . User , ctx . Repo . GitRepo , models . MergeStyle ( form . Do ) , message ) ; err != nil {
if models . IsErrInvalidMergeStyle ( err ) {
if models . IsErrInvalidMergeStyle ( err ) {
ctx . Flash . Error ( ctx . Tr ( "repo.pulls.invalid_merge_option" ) )
ctx . Flash . Error ( ctx . Tr ( "repo.pulls.invalid_merge_option" ) )
ctx . Redirect ( ctx . Repo . RepoLink + "/pulls/" + fmt . Sprint ( pr . Index ) )
ctx . Redirect ( issue . Link ( ) )
return
return
} else if models . IsErrMergeConflicts ( err ) {
} else if models . IsErrMergeConflicts ( err ) {
conflictError := err . ( models . ErrMergeConflicts )
conflictError := err . ( models . ErrMergeConflicts )
@ -935,7 +934,7 @@ func MergePullRequest(ctx *context.Context) {
return
return
}
}
ctx . Flash . Error ( flashError )
ctx . Flash . Error ( flashError )
ctx . Redirect ( ctx . Repo . RepoLink + "/pulls/" + fmt . Sprint ( pr . Index ) )
ctx . Redirect ( issue . Link ( ) )
return
return
} else if models . IsErrRebaseConflicts ( err ) {
} else if models . IsErrRebaseConflicts ( err ) {
conflictError := err . ( models . ErrRebaseConflicts )
conflictError := err . ( models . ErrRebaseConflicts )
@ -949,17 +948,17 @@ func MergePullRequest(ctx *context.Context) {
return
return
}
}
ctx . Flash . Error ( flashError )
ctx . Flash . Error ( flashError )
ctx . Redirect ( ctx . Repo . RepoLink + "/pulls/" + fmt . Sprint ( pr . Index ) )
ctx . Redirect ( issue . Link ( ) )
return
return
} else if models . IsErrMergeUnrelatedHistories ( err ) {
} else if models . IsErrMergeUnrelatedHistories ( err ) {
log . Debug ( "MergeUnrelatedHistories error: %v" , err )
log . Debug ( "MergeUnrelatedHistories error: %v" , err )
ctx . Flash . Error ( ctx . Tr ( "repo.pulls.unrelated_histories" ) )
ctx . Flash . Error ( ctx . Tr ( "repo.pulls.unrelated_histories" ) )
ctx . Redirect ( ctx . Repo . RepoLink + "/pulls/" + fmt . Sprint ( pr . Index ) )
ctx . Redirect ( issue . Link ( ) )
return
return
} else if git . IsErrPushOutOfDate ( err ) {
} else if git . IsErrPushOutOfDate ( err ) {
log . Debug ( "MergePushOutOfDate error: %v" , err )
log . Debug ( "MergePushOutOfDate error: %v" , err )
ctx . Flash . Error ( ctx . Tr ( "repo.pulls.merge_out_of_date" ) )
ctx . Flash . Error ( ctx . Tr ( "repo.pulls.merge_out_of_date" ) )
ctx . Redirect ( ctx . Repo . RepoLink + "/pulls/" + fmt . Sprint ( pr . Index ) )
ctx . Redirect ( issue . Link ( ) )
return
return
} else if git . IsErrPushRejected ( err ) {
} else if git . IsErrPushRejected ( err ) {
log . Debug ( "MergePushRejected error: %v" , err )
log . Debug ( "MergePushRejected error: %v" , err )
@ -979,7 +978,7 @@ func MergePullRequest(ctx *context.Context) {
}
}
ctx . Flash . Error ( flashError )
ctx . Flash . Error ( flashError )
}
}
ctx . Redirect ( ctx . Repo . RepoLink + "/pulls/" + fmt . Sprint ( pr . Index ) )
ctx . Redirect ( issue . Link ( ) )
return
return
}
}
ctx . ServerError ( "Merge" , err )
ctx . ServerError ( "Merge" , err )
@ -1008,7 +1007,7 @@ func MergePullRequest(ctx *context.Context) {
deleteBranch ( ctx , pr , headRepo )
deleteBranch ( ctx , pr , headRepo )
}
}
ctx . Redirect ( ctx . Repo . RepoLink + "/pulls/" + fmt . Sprint ( pr . Index ) )
ctx . Redirect ( issue . Link ( ) )
}
}
func stopTimerIfAvailable ( user * models . User , issue * models . Issue ) error {
func stopTimerIfAvailable ( user * models . User , issue * models . Issue ) error {
@ -1097,6 +1096,7 @@ func CompareAndPullRequestPost(ctx *context.Context) {
pullIssue := & models . Issue {
pullIssue := & models . Issue {
RepoID : repo . ID ,
RepoID : repo . ID ,
Repo : repo ,
Title : form . Title ,
Title : form . Title ,
PosterID : ctx . User . ID ,
PosterID : ctx . User . ID ,
Poster : ctx . User ,
Poster : ctx . User ,
@ -1138,7 +1138,7 @@ func CompareAndPullRequestPost(ctx *context.Context) {
}
}
ctx . Flash . Error ( flashError )
ctx . Flash . Error ( flashError )
}
}
ctx . Redirect ( ctx . Repo . RepoLink + "/pulls/" + fmt . Sprint ( pullIssue . Index ) )
ctx . Redirect ( pullIssue . Link ( ) )
return
return
}
}
ctx . ServerError ( "NewPullRequest" , err )
ctx . ServerError ( "NewPullRequest" , err )
@ -1146,7 +1146,7 @@ func CompareAndPullRequestPost(ctx *context.Context) {
}
}
log . Trace ( "Pull request created: %d/%d" , repo . ID , pullIssue . ID )
log . Trace ( "Pull request created: %d/%d" , repo . ID , pullIssue . ID )
ctx . Redirect ( ctx . Repo . RepoLink + "/pulls/" + fmt . Sprint ( pullIssue . Index ) )
ctx . Redirect ( pullIssue . Link ( ) )
}
}
// TriggerTask response for a trigger task request
// TriggerTask response for a trigger task request
@ -1261,7 +1261,7 @@ func CleanUpPullRequest(ctx *context.Context) {
defer func ( ) {
defer func ( ) {
ctx . JSON ( http . StatusOK , map [ string ] interface { } {
ctx . JSON ( http . StatusOK , map [ string ] interface { } {
"redirect" : pr . BaseRepo . Link ( ) + "/pulls/" + fmt . Sprint ( issue . Index ) ,
"redirect" : issue . Link ( ) ,
} )
} )
} ( )
} ( )
@ -1369,7 +1369,7 @@ func UpdatePullRequestTarget(ctx *context.Context) {
err := err . ( models . ErrPullRequestAlreadyExists )
err := err . ( models . ErrPullRequestAlreadyExists )
RepoRelPath := ctx . Repo . Owner . Name + "/" + ctx . Repo . Repository . Name
RepoRelPath := ctx . Repo . Owner . Name + "/" + ctx . Repo . Repository . Name
errorMessage := ctx . Tr ( "repo.pulls.has_pull_request" , ctx . Repo . RepoLink , RepoRelPath , err . IssueID )
errorMessage := ctx . Tr ( "repo.pulls.has_pull_request" , html . EscapeString ( ctx . Repo . RepoLink + "/pulls/" + strconv . FormatInt ( err . IssueID , 10 ) ) , html . EscapeString ( RepoRelPath ) , err . IssueID ) // FIXME: Creates url insidde locale string
ctx . Flash . Error ( errorMessage )
ctx . Flash . Error ( errorMessage )
ctx . JSON ( http . StatusConflict , map [ string ] interface { } {
ctx . JSON ( http . StatusConflict , map [ string ] interface { } {