2020-01-10 15:53:53 +08:00
// Copyright 2020 The Gitea Authors. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
package convert
import (
2022-01-19 23:26:57 +00:00
"context"
2020-01-31 22:13:51 +01:00
"fmt"
2020-01-10 15:53:53 +08:00
"code.gitea.io/gitea/models"
2021-11-28 19:58:28 +08:00
"code.gitea.io/gitea/models/perm"
2021-11-24 17:49:20 +08:00
user_model "code.gitea.io/gitea/models/user"
2020-01-10 15:53:53 +08:00
"code.gitea.io/gitea/modules/git"
"code.gitea.io/gitea/modules/log"
api "code.gitea.io/gitea/modules/structs"
)
// ToAPIPullRequest assumes following fields have been assigned with valid values:
// Required - Issue
// Optional - Merger
2022-01-19 23:26:57 +00:00
func ToAPIPullRequest ( ctx context . Context , pr * models . PullRequest , doer * user_model . User ) * api . PullRequest {
2020-01-10 15:53:53 +08:00
var (
baseBranch * git . Branch
headBranch * git . Branch
baseCommit * git . Commit
err error
)
2020-01-31 22:13:51 +01:00
2020-01-10 15:53:53 +08:00
if err = pr . Issue . LoadRepo ( ) ; err != nil {
2020-01-31 22:13:51 +01:00
log . Error ( "pr.Issue.LoadRepo[%d]: %v" , pr . ID , err )
2020-01-10 15:53:53 +08:00
return nil
}
2020-01-31 22:13:51 +01:00
2020-02-29 03:49:50 +01:00
apiIssue := ToAPIIssue ( pr . Issue )
2020-03-03 06:31:55 +08:00
if err := pr . LoadBaseRepo ( ) ; err != nil {
log . Error ( "GetRepositoryById[%d]: %v" , pr . ID , err )
return nil
2020-01-10 15:53:53 +08:00
}
2020-03-03 06:31:55 +08:00
if err := pr . LoadHeadRepo ( ) ; err != nil {
log . Error ( "GetRepositoryById[%d]: %v" , pr . ID , err )
return nil
2020-01-10 15:53:53 +08:00
}
2021-11-28 19:58:28 +08:00
p , err := models . GetUserRepoPermission ( pr . BaseRepo , doer )
2021-10-07 07:03:37 +07:00
if err != nil {
log . Error ( "GetUserRepoPermission[%d]: %v" , pr . BaseRepoID , err )
2021-11-28 19:58:28 +08:00
p . AccessMode = perm . AccessModeNone
2021-10-07 07:03:37 +07:00
}
2020-01-10 15:53:53 +08:00
apiPullRequest := & api . PullRequest {
ID : pr . ID ,
URL : pr . Issue . HTMLURL ( ) ,
Index : pr . Index ,
Poster : apiIssue . Poster ,
Title : apiIssue . Title ,
Body : apiIssue . Body ,
Labels : apiIssue . Labels ,
Milestone : apiIssue . Milestone ,
Assignee : apiIssue . Assignee ,
Assignees : apiIssue . Assignees ,
State : apiIssue . State ,
2020-06-01 23:01:55 +02:00
IsLocked : apiIssue . IsLocked ,
2020-01-10 15:53:53 +08:00
Comments : apiIssue . Comments ,
HTMLURL : pr . Issue . HTMLURL ( ) ,
DiffURL : pr . Issue . DiffURL ( ) ,
PatchURL : pr . Issue . PatchURL ( ) ,
HasMerged : pr . HasMerged ,
MergeBase : pr . MergeBase ,
Deadline : apiIssue . Deadline ,
Created : pr . Issue . CreatedUnix . AsTimePtr ( ) ,
Updated : pr . Issue . UpdatedUnix . AsTimePtr ( ) ,
2020-03-03 06:31:55 +08:00
Base : & api . PRBranchInfo {
2020-01-10 15:53:53 +08:00
Name : pr . BaseBranch ,
Ref : pr . BaseBranch ,
RepoID : pr . BaseRepoID ,
2021-11-28 19:58:28 +08:00
Repository : ToRepo ( pr . BaseRepo , p . AccessMode ) ,
2020-03-03 06:31:55 +08:00
} ,
Head : & api . PRBranchInfo {
Name : pr . HeadBranch ,
2021-12-02 20:36:50 +01:00
Ref : fmt . Sprintf ( "%s%d/head" , git . PullPrefix , pr . Index ) ,
2020-03-03 06:31:55 +08:00
RepoID : - 1 ,
} ,
}
2022-03-29 21:13:41 +02:00
gitRepo , err := git . OpenRepository ( ctx , pr . BaseRepo . RepoPath ( ) )
2021-11-24 15:56:24 +08:00
if err != nil {
log . Error ( "OpenRepository[%s]: %v" , pr . BaseRepo . RepoPath ( ) , err )
return nil
}
defer gitRepo . Close ( )
baseBranch , err = gitRepo . GetBranch ( pr . BaseBranch )
2020-03-03 06:31:55 +08:00
if err != nil && ! git . IsErrBranchNotExist ( err ) {
log . Error ( "GetBranch[%s]: %v" , pr . BaseBranch , err )
return nil
}
if err == nil {
2020-01-10 15:53:53 +08:00
baseCommit , err = baseBranch . GetCommit ( )
2020-03-03 06:31:55 +08:00
if err != nil && ! git . IsErrNotExist ( err ) {
log . Error ( "GetCommit[%s]: %v" , baseBranch . Name , err )
return nil
}
if err == nil {
apiPullRequest . Base . Sha = baseCommit . ID . String ( )
2020-01-10 15:53:53 +08:00
}
}
2021-07-28 17:42:56 +08:00
if pr . Flow == models . PullRequestFlowAGit {
2022-03-29 21:13:41 +02:00
gitRepo , err := git . OpenRepository ( ctx , pr . BaseRepo . RepoPath ( ) )
2021-07-28 17:42:56 +08:00
if err != nil {
log . Error ( "OpenRepository[%s]: %v" , pr . GetGitRefName ( ) , err )
return nil
}
defer gitRepo . Close ( )
apiPullRequest . Head . Sha , err = gitRepo . GetRefCommitID ( pr . GetGitRefName ( ) )
if err != nil {
log . Error ( "GetRefCommitID[%s]: %v" , pr . GetGitRefName ( ) , err )
return nil
}
apiPullRequest . Head . RepoID = pr . BaseRepoID
apiPullRequest . Head . Repository = apiPullRequest . Base . Repository
apiPullRequest . Head . Name = ""
}
if pr . HeadRepo != nil && pr . Flow == models . PullRequestFlowGithub {
2021-11-28 19:58:28 +08:00
p , err := models . GetUserRepoPermission ( pr . HeadRepo , doer )
2021-10-07 07:03:37 +07:00
if err != nil {
log . Error ( "GetUserRepoPermission[%d]: %v" , pr . HeadRepoID , err )
2021-11-28 19:58:28 +08:00
p . AccessMode = perm . AccessModeNone
2021-10-07 07:03:37 +07:00
}
2020-03-03 06:31:55 +08:00
apiPullRequest . Head . RepoID = pr . HeadRepo . ID
2021-11-28 19:58:28 +08:00
apiPullRequest . Head . Repository = ToRepo ( pr . HeadRepo , p . AccessMode )
2020-03-03 06:31:55 +08:00
2022-03-29 21:13:41 +02:00
headGitRepo , err := git . OpenRepository ( ctx , pr . HeadRepo . RepoPath ( ) )
2020-01-10 15:53:53 +08:00
if err != nil {
2020-03-03 06:31:55 +08:00
log . Error ( "OpenRepository[%s]: %v" , pr . HeadRepo . RepoPath ( ) , err )
return nil
}
defer headGitRepo . Close ( )
headBranch , err = headGitRepo . GetBranch ( pr . HeadBranch )
if err != nil && ! git . IsErrBranchNotExist ( err ) {
log . Error ( "GetBranch[%s]: %v" , pr . HeadBranch , err )
return nil
}
if git . IsErrBranchNotExist ( err ) {
headCommitID , err := headGitRepo . GetRefCommitID ( apiPullRequest . Head . Ref )
if err != nil && ! git . IsErrNotExist ( err ) {
2020-03-09 07:06:38 +00:00
log . Error ( "GetCommit[%s]: %v" , pr . HeadBranch , err )
2020-01-10 15:53:53 +08:00
return nil
}
2020-03-03 06:31:55 +08:00
if err == nil {
apiPullRequest . Head . Sha = headCommitID
}
2020-01-10 15:53:53 +08:00
} else {
2020-03-03 06:31:55 +08:00
commit , err := headBranch . GetCommit ( )
if err != nil && ! git . IsErrNotExist ( err ) {
log . Error ( "GetCommit[%s]: %v" , headBranch . Name , err )
return nil
2020-01-31 22:13:51 +01:00
}
2020-03-03 06:31:55 +08:00
if err == nil {
apiPullRequest . Head . Ref = pr . HeadBranch
apiPullRequest . Head . Sha = commit . ID . String ( )
2020-01-31 22:13:51 +01:00
}
2020-01-10 15:53:53 +08:00
}
}
2021-03-08 21:48:31 +01:00
if len ( apiPullRequest . Head . Sha ) == 0 && len ( apiPullRequest . Head . Ref ) != 0 {
2022-03-29 21:13:41 +02:00
baseGitRepo , err := git . OpenRepository ( ctx , pr . BaseRepo . RepoPath ( ) )
2021-03-08 21:48:31 +01:00
if err != nil {
log . Error ( "OpenRepository[%s]: %v" , pr . BaseRepo . RepoPath ( ) , err )
return nil
}
defer baseGitRepo . Close ( )
refs , err := baseGitRepo . GetRefsFiltered ( apiPullRequest . Head . Ref )
if err != nil {
log . Error ( "GetRefsFiltered[%s]: %v" , apiPullRequest . Head . Ref , err )
return nil
} else if len ( refs ) == 0 {
log . Error ( "unable to resolve PR head ref" )
} else {
apiPullRequest . Head . Sha = refs [ 0 ] . Object . String ( )
}
}
2020-01-10 15:53:53 +08:00
if pr . Status != models . PullRequestStatusChecking {
mergeable := ! ( pr . Status == models . PullRequestStatusConflict || pr . Status == models . PullRequestStatusError ) && ! pr . IsWorkInProgress ( )
apiPullRequest . Mergeable = mergeable
}
if pr . HasMerged {
apiPullRequest . Merged = pr . MergedUnix . AsTimePtr ( )
apiPullRequest . MergedCommitID = & pr . MergedCommitID
2021-03-27 17:45:26 +01:00
apiPullRequest . MergedBy = ToUser ( pr . Merger , nil )
2020-01-10 15:53:53 +08:00
}
return apiPullRequest
}