@@ -389,8 +389,7 @@ func CreatePullRequest(ctx *context.APIContext) {
389389
390390 form := * web .GetForm (ctx ).(* api.CreatePullRequestOption )
391391 if form .Head == form .Base {
392- ctx .Error (http .StatusUnprocessableEntity , "BaseHeadSame" ,
393- "Invalid PullRequest: There are no changes between the head and the base" )
392+ ctx .Error (http .StatusUnprocessableEntity , "BaseHeadSame" , "Invalid PullRequest: There are no changes between the head and the base" )
394393 return
395394 }
396395
@@ -401,14 +400,23 @@ func CreatePullRequest(ctx *context.APIContext) {
401400 )
402401
403402 // Get repo/branch information
404- headRepo , headGitRepo , compareInfo , baseBranch , headBranch := parseCompareInfo (ctx , form )
403+ //headRepo, headGitRepo, compareInfo, baseBranch, headBranch := parseCompareInfo(ctx, form)
404+ compareResult := parseCompareInfo (ctx , form )
405405 if ctx .Written () {
406406 return
407407 }
408- defer headGitRepo .Close ()
408+ defer compareResult .headGitRepo .Close ()
409+
410+ if ! compareResult .baseRef .IsBranch () || ! compareResult .headRef .IsBranch () {
411+ ctx .Error (http .StatusUnprocessableEntity , "BaseHeadInvalidRefType" , "Invalid PullRequest: base and head must be branches" )
412+ return
413+ }
409414
410415 // Check if another PR exists with the same targets
411- existingPr , err := issues_model .GetUnmergedPullRequest (ctx , headRepo .ID , ctx .Repo .Repository .ID , headBranch , baseBranch , issues_model .PullRequestFlowGithub )
416+ existingPr , err := issues_model .GetUnmergedPullRequest (ctx , compareResult .headRepo .ID , ctx .Repo .Repository .ID ,
417+ compareResult .headRef .ShortName (), compareResult .baseRef .ShortName (),
418+ issues_model .PullRequestFlowGithub ,
419+ )
412420 if err != nil {
413421 if ! issues_model .IsErrPullRequestNotExist (err ) {
414422 ctx .Error (http .StatusInternalServerError , "GetUnmergedPullRequest" , err )
@@ -484,13 +492,13 @@ func CreatePullRequest(ctx *context.APIContext) {
484492 DeadlineUnix : deadlineUnix ,
485493 }
486494 pr := & issues_model.PullRequest {
487- HeadRepoID : headRepo .ID ,
495+ HeadRepoID : compareResult . headRepo .ID ,
488496 BaseRepoID : repo .ID ,
489- HeadBranch : headBranch ,
490- BaseBranch : baseBranch ,
491- HeadRepo : headRepo ,
497+ HeadBranch : compareResult . headRef . ShortName () ,
498+ BaseBranch : compareResult . baseRef . ShortName () ,
499+ HeadRepo : compareResult . headRepo ,
492500 BaseRepo : repo ,
493- MergeBase : compareInfo .MergeBase ,
501+ MergeBase : compareResult . compareInfo .MergeBase ,
494502 Type : issues_model .PullRequestGitea ,
495503 }
496504
@@ -1080,71 +1088,64 @@ func MergePullRequest(ctx *context.APIContext) {
10801088 ctx .Status (http .StatusOK )
10811089}
10821090
1083- func parseCompareInfo (ctx * context.APIContext , form api.CreatePullRequestOption ) (* repo_model.Repository , * git.Repository , * git.CompareInfo , string , string ) {
1084- baseRepo := ctx .Repo .Repository
1091+ type parseCompareInfoResult struct {
1092+ headRepo * repo_model.Repository
1093+ headGitRepo * git.Repository
1094+ compareInfo * git.CompareInfo
1095+ baseRef git.RefName
1096+ headRef git.RefName
1097+ }
10851098
1099+ func parseCompareInfo (ctx * context.APIContext , form api.CreatePullRequestOption ) * parseCompareInfoResult {
1100+ var err error
10861101 // Get compared branches information
10871102 // format: <base branch>...[<head repo>:]<head branch>
10881103 // base<-head: master...head:feature
10891104 // same repo: master...feature
1105+ baseRepo := ctx .Repo .Repository
1106+ baseRefToGuess := form .Base
1107+ headRefToGuess := form .Head
10901108
1091- // TODO: Validate form first?
1092-
1093- baseBranch := form .Base
1109+ var headUser * user_model.User
10941110
1095- var (
1096- headUser * user_model.User
1097- headBranch string
1098- isSameRepo bool
1099- err error
1100- )
1101-
1102- // If there is no head repository, it means pull request between same repository.
11031111 headInfos := strings .Split (form .Head , ":" )
11041112 if len (headInfos ) == 1 {
1105- isSameRepo = true
1113+ // If there is no head repository, it means pull request between same repository.
11061114 headUser = ctx .Repo .Owner
1107- headBranch = headInfos [0 ]
1115+ headRefToGuess = headInfos [0 ]
11081116 } else if len (headInfos ) == 2 {
1117+ // There is a head repository (the head repository could also be the same base repo)
1118+ headRefToGuess = headInfos [1 ]
11091119 headUser , err = user_model .GetUserByName (ctx , headInfos [0 ])
11101120 if err != nil {
11111121 if user_model .IsErrUserNotExist (err ) {
11121122 ctx .NotFound ("GetUserByName" )
11131123 } else {
11141124 ctx .Error (http .StatusInternalServerError , "GetUserByName" , err )
11151125 }
1116- return nil , nil , nil , "" , ""
1126+ return nil
11171127 }
1118- headBranch = headInfos [1 ]
1119- // The head repository can also point to the same repo
1120- isSameRepo = ctx .Repo .Owner .ID == headUser .ID
11211128 } else {
11221129 ctx .NotFound ()
1123- return nil , nil , nil , "" , ""
1130+ return nil
11241131 }
11251132
1126- ctx .Repo .PullRequest .SameRepo = isSameRepo
1127- log .Trace ("Repo path: %q, base branch: %q, head branch: %q" , ctx .Repo .GitRepo .Path , baseBranch , headBranch )
1128- // Check if base branch is valid.
1129- if ! ctx .Repo .GitRepo .IsBranchExist (baseBranch ) && ! ctx .Repo .GitRepo .IsTagExist (baseBranch ) {
1130- ctx .NotFound ("BaseNotExist" )
1131- return nil , nil , nil , "" , ""
1132- }
1133+ isSameRepo := ctx .Repo .Owner .ID == headUser .ID
11331134
11341135 // Check if current user has fork of repository or in the same repository.
11351136 headRepo := repo_model .GetForkedRepo (ctx , headUser .ID , baseRepo .ID )
11361137 if headRepo == nil && ! isSameRepo {
1137- err : = baseRepo .GetBaseRepo (ctx )
1138+ err = baseRepo .GetBaseRepo (ctx )
11381139 if err != nil {
11391140 ctx .Error (http .StatusInternalServerError , "GetBaseRepo" , err )
1140- return nil , nil , nil , "" , ""
1141+ return nil
11411142 }
11421143
11431144 // Check if baseRepo's base repository is the same as headUser's repository.
11441145 if baseRepo .BaseRepo == nil || baseRepo .BaseRepo .OwnerID != headUser .ID {
11451146 log .Trace ("parseCompareInfo[%d]: does not have fork or in same repository" , baseRepo .ID )
11461147 ctx .NotFound ("GetBaseRepo" )
1147- return nil , nil , nil , "" , ""
1148+ return nil
11481149 }
11491150 // Assign headRepo so it can be used below.
11501151 headRepo = baseRepo .BaseRepo
@@ -1153,12 +1154,14 @@ func parseCompareInfo(ctx *context.APIContext, form api.CreatePullRequestOption)
11531154 var headGitRepo * git.Repository
11541155 if isSameRepo {
11551156 headRepo = ctx .Repo .Repository
1157+ // FIXME: it is not right, the caller will close this "ctx.Repo.GitRepo",
1158+ // but there could still be other operations on it later
11561159 headGitRepo = ctx .Repo .GitRepo
11571160 } else {
11581161 headGitRepo , err = gitrepo .OpenRepository (ctx , headRepo )
11591162 if err != nil {
11601163 ctx .Error (http .StatusInternalServerError , "OpenRepository" , err )
1161- return nil , nil , nil , "" , ""
1164+ return nil
11621165 }
11631166 }
11641167
@@ -1167,54 +1170,52 @@ func parseCompareInfo(ctx *context.APIContext, form api.CreatePullRequestOption)
11671170 if err != nil {
11681171 headGitRepo .Close ()
11691172 ctx .Error (http .StatusInternalServerError , "GetUserRepoPermission" , err )
1170- return nil , nil , nil , "" , ""
1173+ return nil
11711174 }
1175+
11721176 if ! permBase .CanReadIssuesOrPulls (true ) || ! permBase .CanRead (unit .TypeCode ) {
1173- if log .IsTrace () {
1174- log .Trace ("Permission Denied: User %-v cannot create/read pull requests or cannot read code in Repo %-v\n User in baseRepo has Permissions: %-+v" ,
1175- ctx .Doer ,
1176- baseRepo ,
1177- permBase )
1178- }
1177+ log .Trace ("Permission Denied: User %-v cannot create/read pull requests or cannot read code in Repo %-v\n User in baseRepo has Permissions: %-+v" , ctx .Doer , baseRepo , permBase )
11791178 headGitRepo .Close ()
11801179 ctx .NotFound ("Can't read pulls or can't read UnitTypeCode" )
1181- return nil , nil , nil , "" , ""
1180+ return nil
11821181 }
11831182
11841183 // user should have permission to read headrepo's codes
11851184 permHead , err := access_model .GetUserRepoPermission (ctx , headRepo , ctx .Doer )
11861185 if err != nil {
11871186 headGitRepo .Close ()
11881187 ctx .Error (http .StatusInternalServerError , "GetUserRepoPermission" , err )
1189- return nil , nil , nil , "" , ""
1188+ return nil
11901189 }
11911190 if ! permHead .CanRead (unit .TypeCode ) {
1192- if log .IsTrace () {
1193- log .Trace ("Permission Denied: User: %-v cannot read code in Repo: %-v\n User in headRepo has Permissions: %-+v" ,
1194- ctx .Doer ,
1195- headRepo ,
1196- permHead )
1197- }
1191+ log .Trace ("Permission Denied: User: %-v cannot read code in Repo: %-v\n User in headRepo has Permissions: %-+v" , ctx .Doer , headRepo , permHead )
11981192 headGitRepo .Close ()
11991193 ctx .NotFound ("Can't read headRepo UnitTypeCode" )
1200- return nil , nil , nil , "" , ""
1194+ return nil
12011195 }
12021196
1203- // Check if head branch is valid.
1204- if ! headGitRepo .IsBranchExist (headBranch ) && ! headGitRepo .IsTagExist (headBranch ) {
1197+ baseRef := ctx .Repo .GitRepo .UnstableGuessRefByShortName (baseRefToGuess )
1198+ headRef := headGitRepo .UnstableGuessRefByShortName (headRefToGuess )
1199+
1200+ log .Trace ("Repo path: %q, base ref: %q->%q, head ref: %q->%q" , ctx .Repo .GitRepo .Path , baseRefToGuess , baseRef , headRefToGuess , headRef )
1201+
1202+ baseRefValid := baseRef .IsBranch () || baseRef .IsTag () || git .IsStringLikelyCommitID (git .ObjectFormatFromName (ctx .Repo .Repository .ObjectFormatName ), baseRef .ShortName ())
1203+ headRefValid := headRef .IsBranch () || headRef .IsTag () || git .IsStringLikelyCommitID (git .ObjectFormatFromName (headRepo .ObjectFormatName ), headRef .ShortName ())
1204+ // Check if base&head ref are valid.
1205+ if ! baseRefValid || ! headRefValid {
12051206 headGitRepo .Close ()
12061207 ctx .NotFound ()
1207- return nil , nil , nil , "" , ""
1208+ return nil
12081209 }
12091210
1210- compareInfo , err := headGitRepo .GetCompareInfo (repo_model .RepoPath (baseRepo .Owner .Name , baseRepo .Name ), baseBranch , headBranch , false , false )
1211+ compareInfo , err := headGitRepo .GetCompareInfo (repo_model .RepoPath (baseRepo .Owner .Name , baseRepo .Name ), baseRef . ShortName (), headRef . ShortName () , false , false )
12111212 if err != nil {
12121213 headGitRepo .Close ()
12131214 ctx .Error (http .StatusInternalServerError , "GetCompareInfo" , err )
1214- return nil , nil , nil , "" , ""
1215+ return nil
12151216 }
12161217
1217- return headRepo , headGitRepo , compareInfo , baseBranch , headBranch
1218+ return & parseCompareInfoResult { headRepo : headRepo , headGitRepo : headGitRepo , compareInfo : compareInfo , baseRef : baseRef , headRef : headRef }
12181219}
12191220
12201221// UpdatePullRequest merge PR's baseBranch into headBranch
0 commit comments