diff --git a/docs/keybindings/Keybindings_en.md b/docs/keybindings/Keybindings_en.md index 1cc81936d..3845d860e 100644 --- a/docs/keybindings/Keybindings_en.md +++ b/docs/keybindings/Keybindings_en.md @@ -39,8 +39,8 @@
space: checkout
- o: create pull request
- O: create pull request options
+ o: create / show pull request
+ O: create / show pull request options
ctrl+y: copy pull request URL to clipboard
c: checkout by name
F: force checkout
diff --git a/docs/keybindings/Keybindings_nl.md b/docs/keybindings/Keybindings_nl.md
index 56158c6fb..0f547524f 100644
--- a/docs/keybindings/Keybindings_nl.md
+++ b/docs/keybindings/Keybindings_nl.md
@@ -39,7 +39,7 @@
space: uitchecken
- o: maak een pull-request
+ o: maak of laat een pull-request zien
O: bekijk opties voor pull-aanvraag
ctrl+y: kopieer de URL van het pull-verzoek naar het klembord
c: uitchecken bij naam
diff --git a/pkg/commands/git.go b/pkg/commands/git.go
index 3a9e434cb..b24bd5d0e 100644
--- a/pkg/commands/git.go
+++ b/pkg/commands/git.go
@@ -10,6 +10,7 @@ import (
"github.com/go-errors/errors"
gogit "github.com/jesseduffield/go-git/v5"
+ "github.com/jesseduffield/lazygit/pkg/commands/models"
"github.com/jesseduffield/lazygit/pkg/commands/oscommands"
"github.com/jesseduffield/lazygit/pkg/commands/patch"
"github.com/jesseduffield/lazygit/pkg/config"
@@ -39,6 +40,8 @@ type GitCommand struct {
// Push to current determines whether the user has configured to push to the remote branch of the same name as the current or not
PushToCurrent bool
+
+ GithubRecentPRs map[string]models.GithubPullRequest
}
// NewGitCommand it runs git commands
diff --git a/pkg/commands/github.go b/pkg/commands/github.go
new file mode 100644
index 000000000..c78108e73
--- /dev/null
+++ b/pkg/commands/github.go
@@ -0,0 +1,65 @@
+package commands
+
+import (
+ "encoding/json"
+ "fmt"
+ "strings"
+
+ "github.com/jesseduffield/lazygit/pkg/commands/models"
+)
+
+func (c *GitCommand) GithubMostRecentPRs() map[string]models.GithubPullRequest {
+ commandOutput, err := c.OSCommand.RunCommandWithOutput("gh pr list --limit 50 --state all --json state,url,number,headRefName,headRepositoryOwner")
+ if err != nil {
+ fmt.Println(1, err)
+ return nil
+ }
+
+ prs := []models.GithubPullRequest{}
+ err = json.Unmarshal([]byte(commandOutput), &prs)
+ if err != nil {
+ fmt.Println(2, err)
+ return nil
+ }
+
+ res := map[string]models.GithubPullRequest{}
+ for _, pr := range prs {
+ res[pr.HeadRepositoryOwner.Login+":"+pr.HeadRefName] = pr
+ }
+ return res
+}
+
+func (c *GitCommand) InjectGithubPullRequests(prs map[string]models.GithubPullRequest, branches []*models.Branch) bool {
+ if len(prs) == 0 {
+ return false
+ }
+
+ remotesToOwnersMap, _ := c.GetRemotesToOwnersMap()
+ if len(remotesToOwnersMap) == 0 {
+ return false
+ }
+
+ foundBranchWithGithubPullRequest := false
+
+ for _, branch := range branches {
+ if branch.UpstreamName == "" {
+ continue
+ }
+
+ remoteAndName := strings.SplitN(branch.UpstreamName, "/", 2)
+ owner, foundRemoteOwner := remotesToOwnersMap[remoteAndName[0]]
+ if len(remoteAndName) != 2 || !foundRemoteOwner {
+ continue
+ }
+
+ pr, hasPr := prs[owner+":"+remoteAndName[1]]
+ if !hasPr {
+ continue
+ }
+
+ foundBranchWithGithubPullRequest = true
+ branch.PR = &pr
+ }
+
+ return foundBranchWithGithubPullRequest
+}
diff --git a/pkg/commands/github_test.go b/pkg/commands/github_test.go
new file mode 100644
index 000000000..befd4ec30
--- /dev/null
+++ b/pkg/commands/github_test.go
@@ -0,0 +1,75 @@
+package commands
+
+import (
+ "os/exec"
+ "testing"
+
+ "github.com/jesseduffield/lazygit/pkg/commands/models"
+ "github.com/jesseduffield/lazygit/pkg/secureexec"
+ "github.com/stretchr/testify/assert"
+)
+
+func TestGithubMostRecentPRs(t *testing.T) {
+ scenarios := []struct {
+ testName string
+ response string
+ expect map[string]models.GithubPullRequest
+ }{
+ {
+ "no response",
+ "",
+ nil,
+ },
+ {
+ "error response",
+ "none of the git remotes configured for this repository point to a known GitHub host. To tell gh about a new GitHub host, please use `gh auth login`",
+ nil,
+ },
+ {
+ "empty response",
+ "[]",
+ map[string]models.GithubPullRequest{},
+ },
+ {
+ "response with data",
+ `[{
+ "headRefName": "command-log-2",
+ "number": 1249,
+ "state": "MERGED",
+ "url": "https://github.com/jesseduffield/lazygit/pull/1249",
+ "headRepositoryOwner": {
+ "id": "MDQ6VXNlcjg0NTY2MzM=",
+ "name": "Jesse Duffield",
+ "login": "jesseduffield"
+ }
+ }]`,
+ map[string]models.GithubPullRequest{
+ "jesseduffield:command-log-2": {
+ HeadRefName: "command-log-2",
+ Number: 1249,
+ State: "MERGED",
+ Url: "https://github.com/jesseduffield/lazygit/pull/1249",
+ HeadRepositoryOwner: models.GithubRepositoryOwner{
+ ID: "MDQ6VXNlcjg0NTY2MzM=",
+ Name: "Jesse Duffield",
+ Login: "jesseduffield",
+ },
+ },
+ },
+ },
+ }
+
+ for _, s := range scenarios {
+ t.Run(s.testName, func(t *testing.T) {
+ gitCmd := NewDummyGitCommand()
+ gitCmd.OSCommand.Command = func(cmd string, args ...string) *exec.Cmd {
+ assert.EqualValues(t, "gh", cmd)
+ assert.EqualValues(t, []string{"pr", "list", "--limit", "50", "--state", "all", "--json", "state,url,number,headRefName,headRepositoryOwner"}, args)
+ return secureexec.Command("echo", s.response)
+ }
+
+ res := gitCmd.GithubMostRecentPRs()
+ assert.Equal(t, s.expect, res)
+ })
+ }
+}
diff --git a/pkg/commands/loading_branches.go b/pkg/commands/loading_branches.go
index 7565a9aee..eaee8e5fb 100644
--- a/pkg/commands/loading_branches.go
+++ b/pkg/commands/loading_branches.go
@@ -99,8 +99,8 @@ func (b *BranchListBuilder) obtainBranches() []*models.Branch {
}
// Build the list of branches for the current repo
-func (b *BranchListBuilder) Build() []*models.Branch {
- branches := b.obtainBranches()
+func (b *BranchListBuilder) Build() (branches []*models.Branch, branchesWithGithubPullRequests bool) {
+ branches = b.obtainBranches()
reflogBranches := b.obtainReflogBranches()
@@ -138,9 +138,17 @@ outer:
if err != nil {
panic(err)
}
- branches = append([]*models.Branch{{Name: currentBranchName, DisplayName: currentBranchDisplayName, Head: true, Recency: " *"}}, branches...)
+ branches = append([]*models.Branch{{
+ Name: currentBranchName,
+ DisplayName: currentBranchDisplayName,
+ Head: true,
+ Recency: " *",
+ }}, branches...)
}
- return branches
+
+ branchesWithGithubPullRequests = b.GitCommand.InjectGithubPullRequests(b.GitCommand.GithubRecentPRs, branches)
+
+ return
}
// TODO: only look at the new reflog commits, and otherwise store the recencies in
diff --git a/pkg/commands/models/branch.go b/pkg/commands/models/branch.go
index 3b8268bff..9199a3611 100644
--- a/pkg/commands/models/branch.go
+++ b/pkg/commands/models/branch.go
@@ -11,6 +11,7 @@ type Branch struct {
Pullables string
UpstreamName string
Head bool
+ PR *GithubPullRequest
}
func (b *Branch) RefName() string {
diff --git a/pkg/commands/models/github.go b/pkg/commands/models/github.go
new file mode 100644
index 000000000..088a066c4
--- /dev/null
+++ b/pkg/commands/models/github.go
@@ -0,0 +1,15 @@
+package models
+
+type GithubPullRequest struct {
+ HeadRefName string `json:"headRefName"`
+ Number int `json:"number"`
+ State string `json:"state"` // "MERGED", "OPEN", "CLOSED"
+ Url string `json:"url"`
+ HeadRepositoryOwner GithubRepositoryOwner `json:"headRepositoryOwner"`
+}
+
+type GithubRepositoryOwner struct {
+ ID string `json:"id"`
+ Name string `json:"name"`
+ Login string `json:"login"`
+}
diff --git a/pkg/commands/pull_request.go b/pkg/commands/pull_request.go
index 46dcbfd68..0d2715c0b 100644
--- a/pkg/commands/pull_request.go
+++ b/pkg/commands/pull_request.go
@@ -153,34 +153,9 @@ func (pr *PullRequest) getPullRequestURL(from string, to string) (string, error)
return "", errors.New(pr.GitCommand.Tr.UnsupportedGitService)
}
- repoInfo := getRepoInfoFromURL(repoURL)
+ repoInfo := GetRepoInfoFromURL(repoURL)
pullRequestURL := gitService.PullRequestURL(repoInfo.Owner, repoInfo.Repository, from, to)
return pullRequestURL, nil
}
-
-func getRepoInfoFromURL(url string) *RepoInformation {
- isHTTP := strings.HasPrefix(url, "http")
-
- if isHTTP {
- splits := strings.Split(url, "/")
- owner := strings.Join(splits[3:len(splits)-1], "/")
- repo := strings.TrimSuffix(splits[len(splits)-1], ".git")
-
- return &RepoInformation{
- Owner: owner,
- Repository: repo,
- }
- }
-
- tmpSplit := strings.Split(url, ":")
- splits := strings.Split(tmpSplit[1], "/")
- owner := strings.Join(splits[0:len(splits)-1], "/")
- repo := strings.TrimSuffix(splits[len(splits)-1], ".git")
-
- return &RepoInformation{
- Owner: owner,
- Repository: repo,
- }
-}
diff --git a/pkg/commands/pull_request_test.go b/pkg/commands/pull_request_test.go
index 2db5b8ade..2af57529f 100644
--- a/pkg/commands/pull_request_test.go
+++ b/pkg/commands/pull_request_test.go
@@ -38,7 +38,7 @@ func TestGetRepoInfoFromURL(t *testing.T) {
for _, s := range scenarios {
t.Run(s.testName, func(t *testing.T) {
- s.test(getRepoInfoFromURL(s.repoURL))
+ s.test(GetRepoInfoFromURL(s.repoURL))
})
}
}
diff --git a/pkg/commands/remotes.go b/pkg/commands/remotes.go
index 75dee0b46..1eb24d761 100644
--- a/pkg/commands/remotes.go
+++ b/pkg/commands/remotes.go
@@ -2,6 +2,7 @@ package commands
import (
"fmt"
+ "strings"
)
func (c *GitCommand) AddRemote(name string, url string) error {
@@ -39,3 +40,66 @@ func (c *GitCommand) CheckRemoteBranchExists(branchName string) bool {
func (c *GitCommand) GetRemoteURL() string {
return c.GetConfigValue("remote.origin.url")
}
+
+func (c *GitCommand) GetRemoteURLs() (map[string]string, error) {
+ res := map[string]string{}
+ out, err := c.OSCommand.RunCommandWithOutput("git remote -v")
+ if err != nil {
+ return nil, err
+ }
+ lines := strings.Split(strings.TrimSpace(out), "\n")
+ for _, line := range lines {
+ lineParts := strings.Split(line, "\t")
+ if len(lineParts) < 2 {
+ continue
+ }
+
+ name := lineParts[0] // "origin"
+ for _, mightBeUrl := range lineParts[1:] {
+ if len(mightBeUrl) > 0 {
+ // mightBeUrl = "git@github.com:jesseduffield/lazygit.git (fetch)"
+ res[name] = strings.SplitN(mightBeUrl, " ", 2)[0]
+ break
+ }
+ }
+ }
+ return res, nil
+}
+
+func GetRepoInfoFromURL(url string) *RepoInformation {
+ isHTTP := strings.HasPrefix(url, "http")
+
+ if isHTTP {
+ splits := strings.Split(url, "/")
+ owner := strings.Join(splits[3:len(splits)-1], "/")
+ repo := strings.TrimSuffix(splits[len(splits)-1], ".git")
+
+ return &RepoInformation{
+ Owner: owner,
+ Repository: repo,
+ }
+ }
+
+ tmpSplit := strings.Split(url, ":")
+ splits := strings.Split(tmpSplit[1], "/")
+ owner := strings.Join(splits[0:len(splits)-1], "/")
+ repo := strings.TrimSuffix(splits[len(splits)-1], ".git")
+
+ return &RepoInformation{
+ Owner: owner,
+ Repository: repo,
+ }
+}
+
+func (c *GitCommand) GetRemotesToOwnersMap() (map[string]string, error) {
+ remotes, err := c.GetRemoteURLs()
+ if err != nil {
+ return nil, err
+ }
+
+ res := map[string]string{}
+ for remoteName, remoteUrl := range remotes {
+ res[remoteName] = GetRepoInfoFromURL(remoteUrl).Owner
+ }
+ return res, nil
+}
diff --git a/pkg/config/user_config.go b/pkg/config/user_config.go
index 38259f6f2..9ad7578a7 100644
--- a/pkg/config/user_config.go
+++ b/pkg/config/user_config.go
@@ -192,19 +192,19 @@ type KeybindingFilesConfig struct {
}
type KeybindingBranchesConfig struct {
- CreatePullRequest string `yaml:"createPullRequest"`
- ViewPullRequestOptions string `yaml:"viewPullRequestOptions"`
- CopyPullRequestURL string `yaml:"copyPullRequestURL"`
- CheckoutBranchByName string `yaml:"checkoutBranchByName"`
- ForceCheckoutBranch string `yaml:"forceCheckoutBranch"`
- RebaseBranch string `yaml:"rebaseBranch"`
- RenameBranch string `yaml:"renameBranch"`
- MergeIntoCurrentBranch string `yaml:"mergeIntoCurrentBranch"`
- ViewGitFlowOptions string `yaml:"viewGitFlowOptions"`
- FastForward string `yaml:"fastForward"`
- PushTag string `yaml:"pushTag"`
- SetUpstream string `yaml:"setUpstream"`
- FetchRemote string `yaml:"fetchRemote"`
+ CreateOrShowPullRequest string `yaml:"createPullRequest"`
+ ViewPullRequestOptions string `yaml:"viewPullRequestOptions"`
+ CopyPullRequestURL string `yaml:"copyPullRequestURL"`
+ CheckoutBranchByName string `yaml:"checkoutBranchByName"`
+ ForceCheckoutBranch string `yaml:"forceCheckoutBranch"`
+ RebaseBranch string `yaml:"rebaseBranch"`
+ RenameBranch string `yaml:"renameBranch"`
+ MergeIntoCurrentBranch string `yaml:"mergeIntoCurrentBranch"`
+ ViewGitFlowOptions string `yaml:"viewGitFlowOptions"`
+ FastForward string `yaml:"fastForward"`
+ PushTag string `yaml:"pushTag"`
+ SetUpstream string `yaml:"setUpstream"`
+ FetchRemote string `yaml:"fetchRemote"`
}
type KeybindingCommitsConfig struct {
@@ -436,19 +436,19 @@ func GetDefaultConfig() *UserConfig {
OpenMergeTool: "M",
},
Branches: KeybindingBranchesConfig{
- CopyPullRequestURL: "",
- CreatePullRequest: "o",
- ViewPullRequestOptions: "O",
- CheckoutBranchByName: "c",
- ForceCheckoutBranch: "F",
- RebaseBranch: "r",
- RenameBranch: "R",
- MergeIntoCurrentBranch: "M",
- ViewGitFlowOptions: "i",
- FastForward: "f",
- PushTag: "P",
- SetUpstream: "u",
- FetchRemote: "f",
+ CopyPullRequestURL: "",
+ CreateOrShowPullRequest: "o",
+ ViewPullRequestOptions: "O",
+ CheckoutBranchByName: "c",
+ ForceCheckoutBranch: "F",
+ RebaseBranch: "r",
+ RenameBranch: "R",
+ MergeIntoCurrentBranch: "M",
+ ViewGitFlowOptions: "i",
+ FastForward: "f",
+ PushTag: "P",
+ SetUpstream: "u",
+ FetchRemote: "f",
},
Commits: KeybindingCommitsConfig{
SquashDown: "s",
diff --git a/pkg/gui/branches_panel.go b/pkg/gui/branches_panel.go
index 9e44a8a8c..18227992a 100644
--- a/pkg/gui/branches_panel.go
+++ b/pkg/gui/branches_panel.go
@@ -68,7 +68,7 @@ func (gui *Gui) refreshBranches() {
if err != nil {
_ = gui.surfaceError(err)
}
- gui.State.Branches = builder.Build()
+ gui.State.Branches, gui.State.BranchesWithGithubPullRequests = builder.Build()
if err := gui.postRefreshUpdate(gui.State.Contexts.Branches); err != nil {
gui.Log.Error(err)
@@ -77,6 +77,13 @@ func (gui *Gui) refreshBranches() {
gui.refreshStatus()
}
+func (gui *Gui) refreshGithubPullRequests() {
+ prs := gui.GitCommand.GithubMostRecentPRs()
+ if len(prs) > 0 {
+ gui.GitCommand.GithubRecentPRs = prs
+ }
+}
+
// specific functions
func (gui *Gui) handleBranchPress() error {
@@ -90,19 +97,22 @@ func (gui *Gui) handleBranchPress() error {
return gui.handleCheckoutRef(branch.Name, handleCheckoutRefOptions{span: gui.Tr.Spans.CheckoutBranch})
}
-func (gui *Gui) handleCreatePullRequestPress() error {
+func (gui *Gui) handleCreateOrShowPullRequestPress() error {
branch := gui.getSelectedBranch()
+ if branch.PR != nil {
+ return gui.OSCommand.OpenLink(branch.PR.Url)
+ }
return gui.createPullRequest(branch.Name, "")
}
-func (gui *Gui) handleCreatePullRequestMenu() error {
+func (gui *Gui) handleCreateOrOpenPullRequestMenu() error {
selectedBranch := gui.getSelectedBranch()
if selectedBranch == nil {
return nil
}
checkedOutBranch := gui.getCheckedOutBranch()
- return gui.createPullRequestMenu(selectedBranch, checkedOutBranch)
+ return gui.createOrOpenPullRequestMenu(selectedBranch, checkedOutBranch)
}
func (gui *Gui) handleCopyPullRequestURLPress() error {
diff --git a/pkg/gui/commits_panel.go b/pkg/gui/commits_panel.go
index 422d8ec29..04b0c8a61 100644
--- a/pkg/gui/commits_panel.go
+++ b/pkg/gui/commits_panel.go
@@ -61,12 +61,23 @@ func (gui *Gui) handleCommitSelect() error {
func (gui *Gui) refreshReflogCommitsConsideringStartup() {
switch gui.State.StartupStage {
case INITIAL:
+ var wg sync.WaitGroup
+ wg.Add(1)
+
go utils.Safe(func() {
_ = gui.refreshReflogCommits()
gui.refreshBranches()
gui.State.StartupStage = COMPLETE
+ wg.Done()
+ })
+ go utils.Safe(func() {
+ // The github cli can be quite slow so we load the github PRs sparately
+ gui.refreshGithubPullRequests()
+ wg.Wait()
+ gui.State.BranchesWithGithubPullRequests = gui.GitCommand.InjectGithubPullRequests(gui.GitCommand.GithubRecentPRs, gui.State.Branches)
+ _ = gui.postRefreshUpdate(gui.State.Contexts.Branches)
+ gui.refreshStatus()
})
-
case COMPLETE:
_ = gui.refreshReflogCommits()
}
diff --git a/pkg/gui/gui.go b/pkg/gui/gui.go
index 71b9702f2..89dc71374 100644
--- a/pkg/gui/gui.go
+++ b/pkg/gui/gui.go
@@ -289,12 +289,13 @@ type guiMutexes struct {
type guiState struct {
// the file panels (files and commit files) can render as a tree, so we have
// managers for them which handle rendering a flat list of files in tree form
- FileManager *filetree.FileManager
- CommitFileManager *filetree.CommitFileManager
- Submodules []*models.SubmoduleConfig
- Branches []*models.Branch
- Commits []*models.Commit
- StashEntries []*models.StashEntry
+ FileManager *filetree.FileManager
+ CommitFileManager *filetree.CommitFileManager
+ Submodules []*models.SubmoduleConfig
+ Branches []*models.Branch
+ BranchesWithGithubPullRequests bool
+ Commits []*models.Commit
+ StashEntries []*models.StashEntry
// Suggestions will sometimes appear when typing into a prompt
Suggestions []*types.Suggestion
// FilteredReflogCommits are the ones that appear in the reflog panel.
diff --git a/pkg/gui/keybindings.go b/pkg/gui/keybindings.go
index f9537e755..695f0b052 100644
--- a/pkg/gui/keybindings.go
+++ b/pkg/gui/keybindings.go
@@ -541,16 +541,16 @@ func (gui *Gui) GetInitialKeybindings() []*Binding {
{
ViewName: "branches",
Contexts: []string{string(LOCAL_BRANCHES_CONTEXT_KEY)},
- Key: gui.getKey(config.Branches.CreatePullRequest),
- Handler: gui.handleCreatePullRequestPress,
- Description: gui.Tr.LcCreatePullRequest,
+ Key: gui.getKey(config.Branches.CreateOrShowPullRequest),
+ Handler: gui.handleCreateOrShowPullRequestPress,
+ Description: gui.Tr.LcCreateOrShowPullRequest,
},
{
ViewName: "branches",
Contexts: []string{string(LOCAL_BRANCHES_CONTEXT_KEY)},
Key: gui.getKey(config.Branches.ViewPullRequestOptions),
- Handler: gui.handleCreatePullRequestMenu,
- Description: gui.Tr.LcCreatePullRequestOptions,
+ Handler: gui.handleCreateOrOpenPullRequestMenu,
+ Description: gui.Tr.LcCreateOrOpenPullRequestOptions,
OpensMenu: true,
},
{
diff --git a/pkg/gui/list_context_config.go b/pkg/gui/list_context_config.go
index 6e9563069..01fd1d117 100644
--- a/pkg/gui/list_context_config.go
+++ b/pkg/gui/list_context_config.go
@@ -70,7 +70,12 @@ func (gui *Gui) branchesListContext() *ListContext {
Gui: gui,
ResetMainViewOriginOnFocus: true,
GetDisplayStrings: func() [][]string {
- return presentation.GetBranchListDisplayStrings(gui.State.Branches, gui.State.ScreenMode != SCREEN_NORMAL, gui.State.Modes.Diffing.Ref)
+ return presentation.GetBranchListDisplayStrings(
+ gui.State.Branches,
+ gui.State.ScreenMode != SCREEN_NORMAL,
+ gui.State.Modes.Diffing.Ref,
+ gui.State.BranchesWithGithubPullRequests,
+ )
},
SelectedItem: func() (ListItem, bool) {
item := gui.getSelectedBranch()
diff --git a/pkg/gui/presentation/branches.go b/pkg/gui/presentation/branches.go
index 3e51e3d66..083f26e43 100644
--- a/pkg/gui/presentation/branches.go
+++ b/pkg/gui/presentation/branches.go
@@ -2,6 +2,7 @@ package presentation
import (
"fmt"
+ "strconv"
"strings"
"github.com/fatih/color"
@@ -10,19 +11,19 @@ import (
"github.com/jesseduffield/lazygit/pkg/utils"
)
-func GetBranchListDisplayStrings(branches []*models.Branch, fullDescription bool, diffName string) [][]string {
+func GetBranchListDisplayStrings(branches []*models.Branch, fullDescription bool, diffName string, showGithub bool) [][]string {
lines := make([][]string, len(branches))
for i := range branches {
diffed := branches[i].Name == diffName
- lines[i] = getBranchDisplayStrings(branches[i], fullDescription, diffed)
+ lines[i] = getBranchDisplayStrings(branches[i], fullDescription, diffed, showGithub)
}
return lines
}
// getBranchDisplayStrings returns the display string of branch
-func getBranchDisplayStrings(b *models.Branch, fullDescription bool, diffed bool) []string {
+func getBranchDisplayStrings(b *models.Branch, fullDescription bool, diffed, showGithub bool) []string {
displayName := b.Name
if b.DisplayName != "" {
displayName = b.DisplayName
@@ -42,11 +43,26 @@ func getBranchDisplayStrings(b *models.Branch, fullDescription bool, diffed bool
recencyColor = color.FgGreen
}
- if fullDescription {
- return []string{utils.ColoredString(b.Recency, recencyColor), coloredName, utils.ColoredString(b.UpstreamName, color.FgYellow)}
+ res := []string{utils.ColoredString(b.Recency, recencyColor)}
+ if showGithub {
+ if b.PR != nil {
+ colour := color.FgMagenta // = state MERGED
+ switch b.PR.State {
+ case "OPEN":
+ colour = color.FgGreen
+ case "CLOSED":
+ colour = color.FgRed
+ }
+ res = append(res, utils.ColoredString("#"+strconv.Itoa(b.PR.Number), colour))
+ } else {
+ res = append(res, "")
+ }
}
- return []string{utils.ColoredString(b.Recency, recencyColor), coloredName}
+ if fullDescription {
+ return append(res, coloredName, utils.ColoredString(b.UpstreamName, color.FgYellow))
+ }
+ return append(res, coloredName)
}
// GetBranchColor branch color
diff --git a/pkg/gui/pull_request_menu_panel.go b/pkg/gui/pull_request_menu_panel.go
index aa7bc481a..83665e197 100644
--- a/pkg/gui/pull_request_menu_panel.go
+++ b/pkg/gui/pull_request_menu_panel.go
@@ -2,13 +2,14 @@ package gui
import (
"fmt"
+ "strconv"
"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 {
+func (gui *Gui) createOrOpenPullRequestMenu(selectedBranch *models.Branch, checkedOutBranch *models.Branch) error {
menuItems := make([]*menuItem, 0, 4)
fromToDisplayStrings := func(from string, to string) []string {
@@ -38,6 +39,15 @@ func (gui *Gui) createPullRequestMenu(selectedBranch *models.Branch, checkedOutB
}
}
+ if selectedBranch.PR != nil {
+ menuItems = append(menuItems, &menuItem{
+ displayString: "open #" + strconv.Itoa(selectedBranch.PR.Number),
+ onPress: func() error {
+ return gui.OSCommand.OpenLink(selectedBranch.PR.Url)
+ },
+ })
+ }
+
if selectedBranch != checkedOutBranch {
menuItems = append(menuItems,
&menuItem{
@@ -52,7 +62,7 @@ func (gui *Gui) createPullRequestMenu(selectedBranch *models.Branch, checkedOutB
menuItems = append(menuItems, menuItemsForBranch(selectedBranch)...)
- return gui.createMenu(fmt.Sprintf(gui.Tr.CreatePullRequestOptions), menuItems, createMenuOptions{showCancel: true})
+ return gui.createMenu(fmt.Sprintf(gui.Tr.CreateOrOpenPullRequestOptions), menuItems, createMenuOptions{showCancel: true})
}
func (gui *Gui) createPullRequest(from string, to string) error {
@@ -61,7 +71,7 @@ func (gui *Gui) createPullRequest(from string, to string) error {
if err != nil {
return gui.surfaceError(err)
}
- gui.OnRunCommand(oscommands.NewCmdLogEntry(fmt.Sprintf(gui.Tr.CreatingPullRequestAtUrl, url), gui.Tr.CreatePullRequest, false))
+ gui.OnRunCommand(oscommands.NewCmdLogEntry(fmt.Sprintf(gui.Tr.CreatingPullRequestAtUrl, url), gui.Tr.CreateOrShowPullRequest, false))
return nil
}
diff --git a/pkg/i18n/chinese.go b/pkg/i18n/chinese.go
index 94fcda8c4..30d322c42 100644
--- a/pkg/i18n/chinese.go
+++ b/pkg/i18n/chinese.go
@@ -176,7 +176,7 @@ func chineseTranslationSet() TranslationSet {
SwitchRepo: `切换到最近的仓库`,
LcAllBranchesLogGraph: `显示所有分支日志`,
UnsupportedGitService: `不支持的git服务`,
- LcCreatePullRequest: `创建pull请求`,
+ LcCreateOrShowPullRequest: `创建pull请求`,
LcCopyPullRequestURL: `将拉取请求URL复制到剪贴板`,
NoBranchOnRemote: `该分支在远程上不存在。您需要先将其推送到远程.`,
LcFetch: `fetch`,
diff --git a/pkg/i18n/dutch.go b/pkg/i18n/dutch.go
index cd8e2160c..0b56ffe78 100644
--- a/pkg/i18n/dutch.go
+++ b/pkg/i18n/dutch.go
@@ -154,7 +154,7 @@ func dutchTranslationSet() TranslationSet {
SwitchRepo: "wissel naar een recente repo",
LcAllBranchesLogGraph: `alle logs van de branch laten zien`,
UnsupportedGitService: `Niet-ondersteunde git-service`,
- LcCreatePullRequest: `maak een pull-request`,
+ LcCreateOrShowPullRequest: `maak of laat een pull-request zien`,
LcCopyPullRequestURL: `kopieer de URL van het pull-verzoek naar het klembord`,
NoBranchOnRemote: `Deze branch bestaat niet op de remote. U moet het eerst naar de remote pushen.`,
LcFetch: `fetch`,
@@ -396,7 +396,7 @@ func dutchTranslationSet() TranslationSet {
LcInitSubmodule: "initialiseer submodule",
LcViewBulkSubmoduleOptions: "bekijk bulk submodule opties",
LcViewStashFiles: "bekijk bestanden van stash entry",
- CreatePullRequestOptions: "Bekijk opties voor pull-aanvraag",
- LcCreatePullRequestOptions: "bekijk opties voor pull-aanvraag",
+ CreateOrOpenPullRequestOptions: "Bekijk opties voor pull-aanvraag",
+ LcCreateOrOpenPullRequestOptions: "bekijk opties voor pull-aanvraag",
}
}
diff --git a/pkg/i18n/english.go b/pkg/i18n/english.go
index e2a9f38de..bfb0b7d54 100644
--- a/pkg/i18n/english.go
+++ b/pkg/i18n/english.go
@@ -169,7 +169,7 @@ type TranslationSet struct {
SwitchRepo string
LcAllBranchesLogGraph string
UnsupportedGitService string
- LcCreatePullRequest string
+ LcCreateOrShowPullRequest string
LcCopyPullRequestURL string
NoBranchOnRemote string
LcFetch string
@@ -454,11 +454,11 @@ type TranslationSet struct {
ToggleWhitespaceInDiffView string
IgnoringWhitespaceInDiffView string
ShowingWhitespaceInDiffView string
- CreatePullRequestOptions string
- LcCreatePullRequestOptions string
+ CreateOrOpenPullRequestOptions string
+ LcCreateOrOpenPullRequestOptions string
LcDefaultBranch string
LcSelectBranch string
- CreatePullRequest string
+ CreateOrShowPullRequest string
CreatingPullRequestAtUrl string
Spans Spans
}
@@ -720,7 +720,7 @@ func englishTranslationSet() TranslationSet {
SwitchRepo: `switch to a recent repo`,
LcAllBranchesLogGraph: `show all branch logs`,
UnsupportedGitService: `Unsupported git service`,
- LcCreatePullRequest: `create pull request`,
+ LcCreateOrShowPullRequest: `create / show pull request`,
LcCopyPullRequestURL: `copy pull request URL to clipboard`,
NoBranchOnRemote: `This branch doesn't exist on remote. You need to push it to remote first.`,
LcFetch: `fetch`,
@@ -1007,9 +1007,9 @@ func englishTranslationSet() TranslationSet {
ToggleWhitespaceInDiffView: "Toggle whether or not whitespace changes are shown in the diff view",
IgnoringWhitespaceInDiffView: "Whitespace will be ignored in the diff view",
ShowingWhitespaceInDiffView: "Whitespace will be shown in the diff view",
- CreatePullRequest: "Create pull request",
- CreatePullRequestOptions: "Create pull request options",
- LcCreatePullRequestOptions: "create pull request options",
+ CreateOrShowPullRequest: "Create / show pull request",
+ CreateOrOpenPullRequestOptions: "Create / show pull request options",
+ LcCreateOrOpenPullRequestOptions: "create / show pull request options",
LcDefaultBranch: "default branch",
LcSelectBranch: "select branch",
CreatingPullRequestAtUrl: "Creating pull request at URL: %s",
diff --git a/pkg/i18n/polish.go b/pkg/i18n/polish.go
index 1420d2ef9..aed1ceb10 100644
--- a/pkg/i18n/polish.go
+++ b/pkg/i18n/polish.go
@@ -127,7 +127,7 @@ func polishTranslationSet() TranslationSet {
ConfirmQuit: `Na pewno chcesz wyjść z programu?`,
LcAllBranchesLogGraph: `pokazywać wszystkie logi branżowe`,
UnsupportedGitService: `Nieobsługiwana usługa git`,
- LcCreatePullRequest: `utwórz żądanie wyciągnięcia`,
+ LcCreateOrShowPullRequest: `utwórz żądanie wyciągnięcia`,
LcCopyPullRequestURL: `skopiuj adres URL żądania ściągnięcia do schowka`,
NoBranchOnRemote: `Ta gałąź nie istnieje na zdalnym. Najpierw musisz go odepchnąć na odległość.`,
LcFetch: `fetch`,
@@ -255,7 +255,7 @@ func polishTranslationSet() TranslationSet {
PullRequestURLCopiedToClipboard: "URL żądania ściągnięcia skopiowany do schowka",
CommitMessageCopiedToClipboard: "Commit message skopiowany do schowka",
LcCopiedToClipboard: "skopiowany do schowka",
- CreatePullRequestOptions: "Utwórz opcje żądania ściągnięcia",
- LcCreatePullRequestOptions: "utwórz opcje żądania ściągnięcia",
+ CreateOrOpenPullRequestOptions: "Utwórz opcje żądania ściągnięcia",
+ LcCreateOrOpenPullRequestOptions: "utwórz opcje żądania ściągnięcia",
}
}