gitee_cli/internal/api/pull_request/pull_request.go

299 lines
8.5 KiB
Go
Raw Normal View History

2024-04-07 17:49:39 +08:00
package pull_request
import (
"encoding/json"
"errors"
"fmt"
"gitee_cli/config"
"gitee_cli/utils/git_utils"
"gitee_cli/utils/http_utils"
"os/exec"
"strconv"
"strings"
"time"
)
type PullRequest struct {
Id int `json:"id"`
Title string `json:"title"`
HtmlUrl string `json:"html_url"`
Mergeable bool `json:"mergeable"`
CanMergeCheck bool `json:"can_merge_check"`
PatchUrl string `json:"patch_url"`
Draft bool `json:"draft"`
Creator creator `json:"user"`
Assignees []assignee `json:"assignees"`
User assignee `json:"-"`
Number int `json:"number"`
Body string `json:"body"`
}
type assignee struct {
Id int `json:"id"`
Name string `json:"name"`
Accept bool `json:"accept"`
}
type creator struct {
Id int `json:"id"`
Name string `json:"name"`
}
func Note(iid int, note string) error {
// https://gitee.com/api/v5/repos/{owner}/{repo}/pulls/{number}/comments
pathWithNamespace, err := git_utils.ParseCurrentRepo()
if err != nil {
pathWithNamespace = config.Conf.DefaultPathWithNamespace
}
url := fmt.Sprintf(config.Conf.ApiPrefix+"/repos/%s/pulls/%d/comments", pathWithNamespace, iid)
payload := map[string]string{"body": note}
giteeClient := http_utils.NewGiteeClient("POST", url, nil, payload)
giteeClient, _ = giteeClient.Do()
if giteeClient.IsFail() {
return errors.New(fmt.Sprintf("评论 pr %d 失败!", iid))
}
return nil
}
func List(scope string) []PullRequest {
pathWithNamespace, err := git_utils.ParseCurrentRepo()
if err != nil {
pathWithNamespace = config.Conf.DefaultPathWithNamespace
}
url := fmt.Sprintf(config.Conf.ApiPrefix+"/repos/%s/pulls?state=open&sort=created&direction=desc&page=1&per_page=100", pathWithNamespace)
giteeClient := http_utils.NewGiteeClient("GET", url, nil, nil)
pullRequests := make([]PullRequest, 50)
giteeClient.Do()
res, _ := giteeClient.GetRespBody()
err = json.Unmarshal(res, &pullRequests)
if err != nil {
fmt.Println("解析 Pull Request 异常!")
return nil
}
pullRequests = filterPullRequest(pullRequests, scope)
return pullRequests
}
func filterPullRequest(pullRequests []PullRequest, scope string) []PullRequest {
if len(pullRequests) == 0 {
return pullRequests
}
// 过滤指定 User 审查的 PR
filteredPullRequests := make([]PullRequest, 0)
userId := config.Conf.UserId
if scope == "owner" {
for _, pr := range pullRequests {
if pr.Creator.Id == userId {
filteredPullRequests = append(filteredPullRequests, pr)
}
}
} else {
for _, pr := range pullRequests {
assignees := pr.Assignees
for _, assignee := range assignees {
if assignee.Id == userId {
pr.User = assignee
filteredPullRequests = append(filteredPullRequests, pr)
break
}
}
}
}
return filteredPullRequests
}
func (pr PullRequest) TransferUrlToEnt() string {
url := pr.HtmlUrl
data := strings.Split(url, "/")
iid := data[len(data)-1]
pathWithName, err := git_utils.ParseCurrentRepo()
if err != nil {
pathWithName = config.Conf.DefaultPathWithNamespace
}
return fmt.Sprintf("https://e.gitee.com/oschina/repos/%s/pulls/%s", pathWithName, iid)
}
func FuzzySearch(pullRequests []PullRequest, keyword string) []PullRequest {
if len(pullRequests) == 0 {
return pullRequests
}
// 模糊搜索
fuzzyPullRequests := make([]PullRequest, 0)
for _, pr := range pullRequests {
if strings.Contains(pr.Title, keyword) {
fuzzyPullRequests = append(fuzzyPullRequests, pr)
}
}
return fuzzyPullRequests
}
func FindPullRequestByIid(commitSha, pathWithNamespace string) (PullRequest, error) {
currentBranch, err := git_utils.GetCurrentBranch()
if err != nil {
return PullRequest{}, err
}
iid, err := findPrIidBySha(commitSha, git_utils.CurrentDir(), currentBranch)
if err != nil {
return PullRequest{}, err
}
url := fmt.Sprintf("https://gitee.com/api/v5/repos/%s/pulls/%d", pathWithNamespace, iid)
giteeClient := http_utils.NewGiteeClient("GET", url, nil, nil)
giteeClient.Do()
if giteeClient.IsFail() {
return PullRequest{}, errors.New("查找 pr 异常!")
}
res, _ := giteeClient.GetRespBody()
pullRequest := PullRequest{}
err = json.Unmarshal(res, &pullRequest)
if err != nil {
fmt.Println("解析 Pull Request 异常!")
return PullRequest{}, errors.New("解析 Pull Request 异常!")
}
return pullRequest, nil
}
func findPrIidBySha(commitSha, dir, currentBranch string) (int, error) {
command := fmt.Sprintf("git log --merges --ancestry-path --oneline %s..%s | grep 'pull request' | tail -n1 | awk '{print $2\";\"$3}'", commitSha, currentBranch)
cmd := exec.Command("/bin/sh", "-c", command)
cmd.Dir = dir
res, err := cmd.CombinedOutput()
if err != nil {
fmt.Println(err.Error())
return 0, errors.New("获取 Pull Request ID 失败!")
}
result := strings.Split(string(res), ";")
if len(result) != 2 {
return 0, errors.New("未找到匹配的 Pull Request")
}
iid, _ := strconv.Atoi(strings.TrimPrefix(result[0], "!"))
title := result[1]
if title == "" {
return 0, errors.New("获取 Pull Request ID 失败!")
}
return iid, nil
}
func CreatePr(baseRepo, baseRef, headRef, title, body, assignees, testers string, draft bool, prune bool) (PullRequest, error) {
url := fmt.Sprintf("https://gitee.com/api/v5/repos/%s/pulls", baseRepo)
payload := map[string]interface{}{
"base": baseRef,
"head": headRef,
"title": title,
"body": body,
"assignees": assignees,
"testers": testers,
"draft": draft,
"prune_source_branch": prune,
}
giteeClient := http_utils.NewGiteeClient("POST", url, nil, payload)
giteeClient, err := giteeClient.Do()
if err != nil {
return PullRequest{}, errors.New("GiteeCilent 异常!")
}
res, _ := giteeClient.GetRespBody()
if giteeClient.IsFail() {
errResponse := http_utils.ErrMsgV5{}
err := json.Unmarshal(res, &errResponse)
if err != nil {
return PullRequest{}, errors.New("创建 pull request 失败!")
}
return PullRequest{}, errors.New(errResponse.Message)
}
pullRequest := PullRequest{}
if err := json.Unmarshal(res, &pullRequest); err != nil {
return pullRequest, errors.New("解析响应失败")
}
return pullRequest, nil
}
func CreateLightPr(baseRepo, baseRef, prTitle string) (PullRequest, error) {
content := "test"
message := "test"
unixTime := time.Now().Format("20060102150405")
path := "test_" + unixTime + ".txt"
branch := "test_" + unixTime
// 新建分支
url := fmt.Sprintf("https://gitee.com/api/v5/repos/%s/branches", baseRepo)
payload := map[string]string{"refs": baseRef, "branch_name": branch}
giteeClient := http_utils.NewGiteeClient("POST", url, nil, payload)
giteeClient.Do()
if giteeClient.IsFail() {
return PullRequest{}, errors.New("创建 PR 失败")
}
giteeClient.Payload = map[string]string{"message": message, "content": content, "branch": branch}
giteeClient.Url = fmt.Sprintf("https://gitee.com/api/v5/repos/%s/contents/%s", baseRepo, path)
giteeClient.Do()
if giteeClient.IsFail() {
return PullRequest{}, errors.New("创建 PR 失败")
}
// 创建 pr
giteeClient.Url = fmt.Sprintf("https://gitee.com/api/v5/repos/%s/pulls", baseRepo)
giteeClient.Payload = map[string]string{
"title": prTitle,
"head": branch,
"base": baseRef,
}
giteeClient.Do()
if giteeClient.IsFail() {
return PullRequest{}, errors.New("创建 PR 失败")
}
res, _ := giteeClient.GetRespBody()
pullRequest := PullRequest{}
err := json.Unmarshal(res, &pullRequest)
if err != nil {
fmt.Println("解析 Pull Request 异常!")
return PullRequest{}, errors.New("解析 Pull Request 异常!")
}
return pullRequest, nil
}
func Detail(iid, repoPath string) (PullRequest, error) {
url := fmt.Sprintf("https://gitee.com/api/v5/repos/%s/pulls/%s", repoPath, iid)
giteeClient := http_utils.NewGiteeClient("GET", url, nil, nil)
if _, err := giteeClient.Do(); err != nil || giteeClient.IsFail() {
return PullRequest{}, errors.New("获取 Pull Request 详情失败")
}
_pullRequest := PullRequest{}
data, _ := giteeClient.GetRespBody()
json.Unmarshal(data, &_pullRequest)
return _pullRequest, nil
}
func FetchPatchContent(iid, repoPath string) (string, error) {
url := fmt.Sprintf("https://gitee.com/%s/pulls/%s.diff", repoPath, iid)
giteeClient := http_utils.NewGiteeClient("GET", url, nil, nil)
giteeClient.SetCookieAuth()
if _, err := giteeClient.Do(); err != nil || giteeClient.IsFail() {
return "", errors.New("获取 Pull Request 补丁内容失败")
}
data, _ := giteeClient.GetRespBody()
return string(data), nil
}