File: pull_create.go

package info (click to toggle)
tea-cli 0.9.2-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 1,364 kB
  • sloc: makefile: 120; sh: 17
file content (133 lines) | stat: -rw-r--r-- 3,681 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
// 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 task

import (
	"fmt"
	"strings"

	"code.gitea.io/sdk/gitea"
	"code.gitea.io/tea/modules/config"
	"code.gitea.io/tea/modules/context"
	local_git "code.gitea.io/tea/modules/git"
	"code.gitea.io/tea/modules/print"
	"code.gitea.io/tea/modules/utils"
)

// CreatePull creates a PR in the given repo and prints the result
func CreatePull(ctx *context.TeaContext, base, head string, opts *gitea.CreateIssueOption) (err error) {
	// default is default branch
	if len(base) == 0 {
		base, err = GetDefaultPRBase(ctx.Login, ctx.Owner, ctx.Repo)
		if err != nil {
			return err
		}
	}

	// default is current one
	if len(head) == 0 {
		if ctx.LocalRepo == nil {
			return fmt.Errorf("no local git repo detected, please specify head branch")
		}
		headOwner, headBranch, err := GetDefaultPRHead(ctx.LocalRepo)
		if err != nil {
			return err
		}

		head = GetHeadSpec(headOwner, headBranch, ctx.Owner)
	}

	// head & base may not be the same
	if head == base {
		return fmt.Errorf("can't create PR from %s to %s", head, base)
	}

	// default is head branch name
	if len(opts.Title) == 0 {
		opts.Title = GetDefaultPRTitle(head)
	}
	// title is required
	if len(opts.Title) == 0 {
		return fmt.Errorf("title is required")
	}

	pr, _, err := ctx.Login.Client().CreatePullRequest(ctx.Owner, ctx.Repo, gitea.CreatePullRequestOption{
		Head:      head,
		Base:      base,
		Title:     opts.Title,
		Body:      opts.Body,
		Assignees: opts.Assignees,
		Labels:    opts.Labels,
		Milestone: opts.Milestone,
		Deadline:  opts.Deadline,
	})

	if err != nil {
		return fmt.Errorf("could not create PR from %s to %s:%s: %s", head, ctx.Owner, base, err)
	}

	print.PullDetails(pr, nil, nil)

	fmt.Println(pr.HTMLURL)

	return err
}

// GetDefaultPRBase retrieves the default base branch for the given repo
func GetDefaultPRBase(login *config.Login, owner, repo string) (string, error) {
	meta, _, err := login.Client().GetRepo(owner, repo)
	if err != nil {
		return "", fmt.Errorf("could not fetch repo meta: %s", err)
	}
	return meta.DefaultBranch, nil
}

// GetDefaultPRHead uses the currently checked out branch, tries to find a remote
// that has a branch with the same name, and extracts the owner from its URL.
// If no remote matches, owner is empty, meaning same as head repo owner.
func GetDefaultPRHead(localRepo *local_git.TeaRepo) (owner, branch string, err error) {
	if branch, err = localRepo.TeaGetCurrentBranchName(); err != nil {
		return
	}

	remote, err := localRepo.TeaFindBranchRemote(branch, "")
	if err != nil {
		err = fmt.Errorf("could not determine remote for current branch: %s", err)
		return
	}

	if remote == nil {
		// if no remote branch is found for the local branch,
		// we leave owner empty, meaning "use same repo as head" to gitea.
		return
	}

	url, err := local_git.ParseURL(remote.Config().URLs[0])
	if err != nil {
		return
	}
	owner, _ = utils.GetOwnerAndRepo(url.Path, "")
	return
}

// GetHeadSpec creates a head string as expected by gitea API
func GetHeadSpec(owner, branch, baseOwner string) string {
	if len(owner) != 0 && owner != baseOwner {
		return fmt.Sprintf("%s:%s", owner, branch)
	}
	return branch
}

// GetDefaultPRTitle transforms a string like a branchname to a readable text
func GetDefaultPRTitle(head string) string {
	title := head
	if strings.Contains(title, ":") {
		title = strings.SplitN(title, ":", 2)[1]
	}
	title = strings.Replace(title, "-", " ", -1)
	title = strings.Replace(title, "_", " ", -1)
	title = strings.Title(strings.ToLower(title))
	return title
}