1
0
mirror of https://github.com/jesseduffield/lazygit.git synced 2025-03-27 22:01:46 +02:00

Implement pull request options menu

This commit is contained in:
Denis Palashevskii 2021-04-21 15:23:36 +04:00 committed by Jesse Duffield
parent f2645da16a
commit 0e6598adbd
6 changed files with 110 additions and 24 deletions

View File

@ -37,24 +37,39 @@ func NewService(typeName string, repositoryDomain string, siteDomain string) *Se
service = &Service{ service = &Service{
Name: repositoryDomain, Name: repositoryDomain,
PullRequestURL: func(owner string, repository string, from string, to string) string { PullRequestURL: func(owner string, repository string, from string, to string) string {
urlFormat := fmt.Sprintf("https://%s%s", siteDomain, "/%s/%s/compare/%s?expand=1") if to == "" {
return fmt.Sprintf(urlFormat, owner, repository, from) urlFormat := fmt.Sprintf("https://%s%s", siteDomain, "/%s/%s/compare/%s?expand=1")
return fmt.Sprintf(urlFormat, owner, repository, from)
} else {
urlFormat := fmt.Sprintf("https://%s%s", siteDomain, "/%s/%s/compare/%s...%s?expand=1")
return fmt.Sprintf(urlFormat, owner, repository, to, from)
}
}, },
} }
case "bitbucket": case "bitbucket":
service = &Service{ service = &Service{
Name: repositoryDomain, Name: repositoryDomain,
PullRequestURL: func(owner string, repository string, from string, to string) string { PullRequestURL: func(owner string, repository string, from string, to string) string {
urlFormat := fmt.Sprintf("https://%s%s", siteDomain, "/%s/%s/pull-requests/new?source=%s&t=1") if to == "" {
return fmt.Sprintf(urlFormat, owner, repository, from) urlFormat := fmt.Sprintf("https://%s%s", siteDomain, "/%s/%s/pull-requests/new?source=%s&t=1")
return fmt.Sprintf(urlFormat, owner, repository, from)
} else {
urlFormat := fmt.Sprintf("https://%s%s", siteDomain, "/%s/%s/pull-requests/new?source=%s&dest=%s&t=1")
return fmt.Sprintf(urlFormat, owner, repository, from, to)
}
}, },
} }
case "gitlab": case "gitlab":
service = &Service{ service = &Service{
Name: repositoryDomain, Name: repositoryDomain,
PullRequestURL: func(owner string, repository string, from string, to string) string { PullRequestURL: func(owner string, repository string, from string, to string) string {
urlFormat := fmt.Sprintf("https://%s%s", siteDomain, "/%s/%s/merge_requests/new?merge_request[source_branch]=%s") if to == "" {
return fmt.Sprintf(urlFormat, owner, repository, from) urlFormat := fmt.Sprintf("https://%s%s", siteDomain, "/%s/%s/merge_requests/new?merge_request[source_branch]=%s")
return fmt.Sprintf(urlFormat, owner, repository, from)
} else {
urlFormat := fmt.Sprintf("https://%s%s", siteDomain, "/%s/%s/merge_requests/new?merge_request[source_branch]=%s&merge_request[target_branch]=%s")
return fmt.Sprintf(urlFormat, owner, repository, from, to)
}
}, },
} }
} }
@ -99,8 +114,8 @@ func NewPullRequest(gitCommand *GitCommand) *PullRequest {
} }
// Create opens link to new pull request in browser // Create opens link to new pull request in browser
func (pr *PullRequest) Create(branch *models.Branch) (string, error) { func (pr *PullRequest) Create(from *models.Branch, to *models.Branch) (string, error) {
pullRequestURL, err := pr.getPullRequestURL(branch) pullRequestURL, err := pr.getPullRequestURL(from, to)
if err != nil { if err != nil {
return "", err return "", err
} }
@ -109,8 +124,8 @@ func (pr *PullRequest) Create(branch *models.Branch) (string, error) {
} }
// CopyURL copies the pull request URL to the clipboard // CopyURL copies the pull request URL to the clipboard
func (pr *PullRequest) CopyURL(branch *models.Branch) (string, error) { func (pr *PullRequest) CopyURL(from *models.Branch, to *models.Branch) (string, error) {
pullRequestURL, err := pr.getPullRequestURL(branch) pullRequestURL, err := pr.getPullRequestURL(from, to)
if err != nil { if err != nil {
return "", err return "", err
} }
@ -118,8 +133,8 @@ func (pr *PullRequest) CopyURL(branch *models.Branch) (string, error) {
return pullRequestURL, pr.GitCommand.OSCommand.CopyToClipboard(pullRequestURL) return pullRequestURL, pr.GitCommand.OSCommand.CopyToClipboard(pullRequestURL)
} }
func (pr *PullRequest) getPullRequestURL(branch *models.Branch) (string, error) { func (pr *PullRequest) getPullRequestURL(from *models.Branch, to *models.Branch) (string, error) {
branchExistsOnRemote := pr.GitCommand.CheckRemoteBranchExists(branch) branchExistsOnRemote := pr.GitCommand.CheckRemoteBranchExists(from)
if !branchExistsOnRemote { if !branchExistsOnRemote {
return "", errors.New(pr.GitCommand.Tr.NoBranchOnRemote) return "", errors.New(pr.GitCommand.Tr.NoBranchOnRemote)
@ -140,7 +155,13 @@ func (pr *PullRequest) getPullRequestURL(branch *models.Branch) (string, error)
} }
repoInfo := getRepoInfoFromURL(repoURL) repoInfo := getRepoInfoFromURL(repoURL)
pullRequestURL := gitService.PullRequestURL(repoInfo.Owner, repoInfo.Repository, branch.Name, "") var toBranchName string
if to == nil {
toBranchName = ""
} else {
toBranchName = to.Name
}
pullRequestURL := gitService.PullRequestURL(repoInfo.Owner, repoInfo.Repository, from.Name, toBranchName)
return pullRequestURL, nil return pullRequestURL, nil
} }

View File

@ -193,6 +193,7 @@ type KeybindingFilesConfig struct {
type KeybindingBranchesConfig struct { type KeybindingBranchesConfig struct {
CreatePullRequest string `yaml:"createPullRequest"` CreatePullRequest string `yaml:"createPullRequest"`
ViewPullRequestOptions string `yaml:"viewPullRequestOptions"`
CopyPullRequestURL string `yaml:"copyPullRequestURL"` CopyPullRequestURL string `yaml:"copyPullRequestURL"`
CheckoutBranchByName string `yaml:"checkoutBranchByName"` CheckoutBranchByName string `yaml:"checkoutBranchByName"`
ForceCheckoutBranch string `yaml:"forceCheckoutBranch"` ForceCheckoutBranch string `yaml:"forceCheckoutBranch"`
@ -437,6 +438,7 @@ func GetDefaultConfig() *UserConfig {
Branches: KeybindingBranchesConfig{ Branches: KeybindingBranchesConfig{
CopyPullRequestURL: "<c-y>", CopyPullRequestURL: "<c-y>",
CreatePullRequest: "o", CreatePullRequest: "o",
ViewPullRequestOptions: "O",
CheckoutBranchByName: "c", CheckoutBranchByName: "c",
ForceCheckoutBranch: "F", ForceCheckoutBranch: "F",
RebaseBranch: "r", RebaseBranch: "r",

View File

@ -91,23 +91,25 @@ func (gui *Gui) handleBranchPress() error {
} }
func (gui *Gui) handleCreatePullRequestPress() error { func (gui *Gui) handleCreatePullRequestPress() error {
pullRequest := commands.NewPullRequest(gui.GitCommand)
branch := gui.getSelectedBranch() branch := gui.getSelectedBranch()
url, err := pullRequest.Create(branch) return createPullRequest(branch, nil, gui)
if err != nil { }
return gui.surfaceError(err)
}
gui.OnRunCommand(oscommands.NewCmdLogEntry(fmt.Sprintf("Creating pull request at URL: %s", url), "Create pull request", false))
return nil func (gui *Gui) handleCreatePullRequestMenu() error {
selectedBranch := gui.getSelectedBranch()
if selectedBranch == nil {
return nil
}
checkedOutBranch := gui.getCheckedOutBranch()
return gui.createPullRequestMenu(selectedBranch, checkedOutBranch)
} }
func (gui *Gui) handleCopyPullRequestURLPress() error { func (gui *Gui) handleCopyPullRequestURLPress() error {
pullRequest := commands.NewPullRequest(gui.GitCommand) pullRequest := commands.NewPullRequest(gui.GitCommand)
branch := gui.getSelectedBranch() branch := gui.getSelectedBranch()
url, err := pullRequest.CopyURL(branch) url, err := pullRequest.CopyURL(branch, nil)
if err != nil { if err != nil {
return gui.surfaceError(err) return gui.surfaceError(err)
} }

View File

@ -545,6 +545,13 @@ func (gui *Gui) GetInitialKeybindings() []*Binding {
Handler: gui.handleCreatePullRequestPress, Handler: gui.handleCreatePullRequestPress,
Description: gui.Tr.LcCreatePullRequest, Description: gui.Tr.LcCreatePullRequest,
}, },
{
ViewName: "branches",
Contexts: []string{string(LOCAL_BRANCHES_CONTEXT_KEY)},
Key: gui.getKey(config.Branches.ViewPullRequestOptions),
Handler: gui.handleCreatePullRequestMenu,
Description: gui.Tr.LcCreatePullRequest,
},
{ {
ViewName: "branches", ViewName: "branches",
Contexts: []string{string(LOCAL_BRANCHES_CONTEXT_KEY)}, Contexts: []string{string(LOCAL_BRANCHES_CONTEXT_KEY)},

View File

@ -0,0 +1,52 @@
package gui
import (
"fmt"
"github.com/jesseduffield/lazygit/pkg/commands"
"github.com/jesseduffield/lazygit/pkg/commands/models"
"github.com/jesseduffield/lazygit/pkg/commands/oscommands"
)
func (gui *Gui) createPullRequestMenu(selectedBranch *models.Branch, checkedOutBranch *models.Branch) error {
menuItems := make([]*menuItem, 0, 2)
if selectedBranch != checkedOutBranch {
menuItems = append(menuItems, &menuItem{
displayStrings: []string{
fmt.Sprintf("%s -> default branch", selectedBranch.Name),
},
onPress: func() error {
return createPullRequest(selectedBranch, nil, gui)
},
}, &menuItem{
displayStrings: []string{
fmt.Sprintf("%s -> %s", checkedOutBranch.Name, selectedBranch.Name),
},
onPress: func() error {
return createPullRequest(checkedOutBranch, selectedBranch, gui)
},
})
}
menuItems = append(menuItems, &menuItem{
displayStrings: []string{
fmt.Sprintf("%s -> default branch", checkedOutBranch.Name),
},
onPress: func() error {
return createPullRequest(checkedOutBranch, nil, gui)
},
})
return gui.createMenu(fmt.Sprintf(gui.Tr.CreatePullRequest), menuItems, createMenuOptions{showCancel: true})
}
func createPullRequest(checkedOutBranch *models.Branch, selectedBranch *models.Branch, gui *Gui) error {
pullRequest := commands.NewPullRequest(gui.GitCommand)
url, err := pullRequest.Create(checkedOutBranch, selectedBranch)
if err != nil {
return gui.surfaceError(err)
}
gui.OnRunCommand(oscommands.NewCmdLogEntry(fmt.Sprintf("Creating pull request at URL: %s", url), "Create pull request", false))
return nil
}

View File

@ -454,6 +454,7 @@ type TranslationSet struct {
ToggleWhitespaceInDiffView string ToggleWhitespaceInDiffView string
IgnoringWhitespaceInDiffView string IgnoringWhitespaceInDiffView string
ShowingWhitespaceInDiffView string ShowingWhitespaceInDiffView string
CreatePullRequest string
Spans Spans Spans Spans
} }
@ -1001,6 +1002,7 @@ func englishTranslationSet() TranslationSet {
ToggleWhitespaceInDiffView: "Toggle whether or not whitespace changes are shown in the diff view", ToggleWhitespaceInDiffView: "Toggle whether or not whitespace changes are shown in the diff view",
IgnoringWhitespaceInDiffView: "Whitespace will be ignored in the diff view", IgnoringWhitespaceInDiffView: "Whitespace will be ignored in the diff view",
ShowingWhitespaceInDiffView: "Whitespace will be shown in the diff view", ShowingWhitespaceInDiffView: "Whitespace will be shown in the diff view",
CreatePullRequest: "Create pull request",
Spans: Spans{ Spans: Spans{
// TODO: combine this with the original keybinding descriptions (those are all in lowercase atm) // TODO: combine this with the original keybinding descriptions (those are all in lowercase atm)
CheckoutCommit: "Checkout commit", CheckoutCommit: "Checkout commit",