2020-01-10 10:53:53 +03: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-20 02:26:57 +03:00
"context"
2020-02-01 00:13:51 +03:00
"fmt"
2020-01-10 10:53:53 +03:00
"code.gitea.io/gitea/models"
2021-11-28 14:58:28 +03:00
"code.gitea.io/gitea/models/perm"
2021-11-24 12:49:20 +03:00
user_model "code.gitea.io/gitea/models/user"
2020-01-10 10:53:53 +03: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-20 02:26:57 +03:00
func ToAPIPullRequest ( ctx context . Context , pr * models . PullRequest , doer * user_model . User ) * api . PullRequest {
2020-01-10 10:53:53 +03:00
var (
baseBranch * git . Branch
headBranch * git . Branch
baseCommit * git . Commit
err error
)
2020-02-01 00:13:51 +03:00
2022-04-08 12:11:15 +03:00
if err = pr . Issue . LoadRepo ( ctx ) ; err != nil {
2020-02-01 00:13:51 +03:00
log . Error ( "pr.Issue.LoadRepo[%d]: %v" , pr . ID , err )
2020-01-10 10:53:53 +03:00
return nil
}
2020-02-01 00:13:51 +03:00
2020-02-29 05:49:50 +03:00
apiIssue := ToAPIIssue ( pr . Issue )
2020-03-03 01:31:55 +03:00
if err := pr . LoadBaseRepo ( ) ; err != nil {
log . Error ( "GetRepositoryById[%d]: %v" , pr . ID , err )
return nil
2020-01-10 10:53:53 +03:00
}
2020-03-03 01:31:55 +03:00
if err := pr . LoadHeadRepo ( ) ; err != nil {
log . Error ( "GetRepositoryById[%d]: %v" , pr . ID , err )
return nil
2020-01-10 10:53:53 +03:00
}
2021-11-28 14:58:28 +03:00
p , err := models . GetUserRepoPermission ( pr . BaseRepo , doer )
2021-10-07 03:03:37 +03:00
if err != nil {
log . Error ( "GetUserRepoPermission[%d]: %v" , pr . BaseRepoID , err )
2021-11-28 14:58:28 +03:00
p . AccessMode = perm . AccessModeNone
2021-10-07 03:03:37 +03:00
}
2020-01-10 10:53:53 +03: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-02 00:01:55 +03:00
IsLocked : apiIssue . IsLocked ,
2020-01-10 10:53:53 +03: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 01:31:55 +03:00
Base : & api . PRBranchInfo {
2020-01-10 10:53:53 +03:00
Name : pr . BaseBranch ,
Ref : pr . BaseBranch ,
RepoID : pr . BaseRepoID ,
2021-11-28 14:58:28 +03:00
Repository : ToRepo ( pr . BaseRepo , p . AccessMode ) ,
2020-03-03 01:31:55 +03:00
} ,
Head : & api . PRBranchInfo {
Name : pr . HeadBranch ,
2021-12-02 22:36:50 +03:00
Ref : fmt . Sprintf ( "%s%d/head" , git . PullPrefix , pr . Index ) ,
2020-03-03 01:31:55 +03:00
RepoID : - 1 ,
} ,
}
2022-03-29 22:13:41 +03:00
gitRepo , err := git . OpenRepository ( ctx , pr . BaseRepo . RepoPath ( ) )
2021-11-24 10:56:24 +03: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 01:31:55 +03:00
if err != nil && ! git . IsErrBranchNotExist ( err ) {
log . Error ( "GetBranch[%s]: %v" , pr . BaseBranch , err )
return nil
}
if err == nil {
2020-01-10 10:53:53 +03:00
baseCommit , err = baseBranch . GetCommit ( )
2020-03-03 01:31:55 +03: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 10:53:53 +03:00
}
}
2021-07-28 12:42:56 +03:00
if pr . Flow == models . PullRequestFlowAGit {
2022-03-29 22:13:41 +03:00
gitRepo , err := git . OpenRepository ( ctx , pr . BaseRepo . RepoPath ( ) )
2021-07-28 12:42:56 +03: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 14:58:28 +03:00
p , err := models . GetUserRepoPermission ( pr . HeadRepo , doer )
2021-10-07 03:03:37 +03:00
if err != nil {
log . Error ( "GetUserRepoPermission[%d]: %v" , pr . HeadRepoID , err )
2021-11-28 14:58:28 +03:00
p . AccessMode = perm . AccessModeNone
2021-10-07 03:03:37 +03:00
}
2020-03-03 01:31:55 +03:00
apiPullRequest . Head . RepoID = pr . HeadRepo . ID
2021-11-28 14:58:28 +03:00
apiPullRequest . Head . Repository = ToRepo ( pr . HeadRepo , p . AccessMode )
2020-03-03 01:31:55 +03:00
2022-03-29 22:13:41 +03:00
headGitRepo , err := git . OpenRepository ( ctx , pr . HeadRepo . RepoPath ( ) )
2020-01-10 10:53:53 +03:00
if err != nil {
2020-03-03 01:31:55 +03: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 10:06:38 +03:00
log . Error ( "GetCommit[%s]: %v" , pr . HeadBranch , err )
2020-01-10 10:53:53 +03:00
return nil
}
2020-03-03 01:31:55 +03:00
if err == nil {
apiPullRequest . Head . Sha = headCommitID
}
2020-01-10 10:53:53 +03:00
} else {
2020-03-03 01:31:55 +03:00
commit , err := headBranch . GetCommit ( )
if err != nil && ! git . IsErrNotExist ( err ) {
log . Error ( "GetCommit[%s]: %v" , headBranch . Name , err )
return nil
2020-02-01 00:13:51 +03:00
}
2020-03-03 01:31:55 +03:00
if err == nil {
apiPullRequest . Head . Ref = pr . HeadBranch
apiPullRequest . Head . Sha = commit . ID . String ( )
2020-02-01 00:13:51 +03:00
}
2020-01-10 10:53:53 +03:00
}
}
2021-03-08 23:48:31 +03:00
if len ( apiPullRequest . Head . Sha ) == 0 && len ( apiPullRequest . Head . Ref ) != 0 {
2022-03-29 22:13:41 +03:00
baseGitRepo , err := git . OpenRepository ( ctx , pr . BaseRepo . RepoPath ( ) )
2021-03-08 23:48:31 +03: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 10:53:53 +03: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 19:45:26 +03:00
apiPullRequest . MergedBy = ToUser ( pr . Merger , nil )
2020-01-10 10:53:53 +03:00
}
return apiPullRequest
}