gitee_cli/internal/api/pull_request/pull_request.go

299 lines
8.5 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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
}