mirror of
https://github.com/jesseduffield/lazygit.git
synced 2025-07-30 03:23:08 +03:00
Add option to (un)set upstream for a local branch
This commit is contained in:
@ -97,9 +97,50 @@ func (self *BranchesController) GetKeybindings(opts types.KeybindingsOpts) []*ty
|
||||
Handler: self.checkSelectedAndReal(self.rename),
|
||||
Description: self.c.Tr.LcRenameBranch,
|
||||
},
|
||||
{
|
||||
Key: opts.GetKey(opts.Config.Branches.SetUpstream),
|
||||
Handler: self.checkSelected(self.setUpstream),
|
||||
Description: self.c.Tr.LcSetUnsetUpstream,
|
||||
OpensMenu: true,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func (self *BranchesController) setUpstream(selectedBranch *models.Branch) error {
|
||||
return self.c.Menu(types.CreateMenuOptions{
|
||||
Title: self.c.Tr.Actions.SetUnsetUpstream,
|
||||
Items: []*types.MenuItem{
|
||||
{
|
||||
DisplayStrings: []string{self.c.Tr.LcUnsetUpstream},
|
||||
OnPress: func() error {
|
||||
if err := self.git.Branch.UnsetUpstream(selectedBranch.Name); err != nil {
|
||||
return self.c.Error(err)
|
||||
}
|
||||
return nil
|
||||
},
|
||||
Key: 'u',
|
||||
},
|
||||
{
|
||||
DisplayStrings: []string{self.c.Tr.LcSetUpstream},
|
||||
OnPress: func() error {
|
||||
return self.helpers.Upstream.PromptForUpstream(selectedBranch, func(upstream string) error {
|
||||
upstreamRemote, upstreamBranch, err := self.helpers.Upstream.ParseUpstream(upstream)
|
||||
if err != nil {
|
||||
return self.c.Error(err)
|
||||
}
|
||||
|
||||
if err := self.git.Branch.SetUpstream(upstreamRemote, upstreamBranch, selectedBranch.Name); err != nil {
|
||||
return self.c.Error(err)
|
||||
}
|
||||
return nil
|
||||
})
|
||||
},
|
||||
Key: 's',
|
||||
},
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
func (self *BranchesController) Context() types.Context {
|
||||
return self.context()
|
||||
}
|
||||
|
@ -12,6 +12,7 @@ type Helpers struct {
|
||||
Host *HostHelper
|
||||
PatchBuilding *PatchBuildingHelper
|
||||
GPG *GpgHelper
|
||||
Upstream *UpstreamHelper
|
||||
}
|
||||
|
||||
func NewStubHelpers() *Helpers {
|
||||
@ -27,5 +28,6 @@ func NewStubHelpers() *Helpers {
|
||||
Host: &HostHelper{},
|
||||
PatchBuilding: &PatchBuildingHelper{},
|
||||
GPG: &GpgHelper{},
|
||||
Upstream: &UpstreamHelper{},
|
||||
}
|
||||
}
|
||||
|
78
pkg/gui/controllers/helpers/upstream_helper.go
Normal file
78
pkg/gui/controllers/helpers/upstream_helper.go
Normal file
@ -0,0 +1,78 @@
|
||||
package helpers
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"strings"
|
||||
|
||||
"github.com/jesseduffield/lazygit/pkg/commands/models"
|
||||
"github.com/jesseduffield/lazygit/pkg/gui/types"
|
||||
)
|
||||
|
||||
type UpstreamHelper struct {
|
||||
c *types.HelperCommon
|
||||
model *types.Model
|
||||
|
||||
getRemoteBranchesSuggestionsFunc func(string) func(string) []*types.Suggestion
|
||||
}
|
||||
|
||||
type IUpstreamHelper interface {
|
||||
ParseUpstream(string) (string, string, error)
|
||||
PromptForUpstream(*models.Branch, func(string) error) error
|
||||
GetSuggestedRemote() string
|
||||
}
|
||||
|
||||
var _ IUpstreamHelper = &UpstreamHelper{}
|
||||
|
||||
func NewUpstreamHelper(
|
||||
c *types.HelperCommon,
|
||||
model *types.Model,
|
||||
getRemoteBranchesSuggestionsFunc func(string) func(string) []*types.Suggestion,
|
||||
) *UpstreamHelper {
|
||||
return &UpstreamHelper{
|
||||
c: c,
|
||||
model: model,
|
||||
getRemoteBranchesSuggestionsFunc: getRemoteBranchesSuggestionsFunc,
|
||||
}
|
||||
}
|
||||
|
||||
func (self *UpstreamHelper) ParseUpstream(upstream string) (string, string, error) {
|
||||
var upstreamBranch, upstreamRemote string
|
||||
split := strings.Split(upstream, " ")
|
||||
if len(split) != 2 {
|
||||
return "", "", errors.New(self.c.Tr.InvalidUpstream)
|
||||
}
|
||||
|
||||
upstreamRemote = split[0]
|
||||
upstreamBranch = split[1]
|
||||
|
||||
return upstreamRemote, upstreamBranch, nil
|
||||
}
|
||||
|
||||
func (self *UpstreamHelper) PromptForUpstream(currentBranch *models.Branch, onConfirm func(string) error) error {
|
||||
suggestedRemote := self.GetSuggestedRemote()
|
||||
|
||||
return self.c.Prompt(types.PromptOpts{
|
||||
Title: self.c.Tr.EnterUpstream,
|
||||
InitialContent: suggestedRemote + " " + currentBranch.Name,
|
||||
FindSuggestionsFunc: self.getRemoteBranchesSuggestionsFunc(" "),
|
||||
HandleConfirm: onConfirm,
|
||||
})
|
||||
}
|
||||
|
||||
func (self *UpstreamHelper) GetSuggestedRemote() string {
|
||||
return getSuggestedRemote(self.model.Remotes)
|
||||
}
|
||||
|
||||
func getSuggestedRemote(remotes []*models.Remote) string {
|
||||
if len(remotes) == 0 {
|
||||
return "origin"
|
||||
}
|
||||
|
||||
for _, remote := range remotes {
|
||||
if remote.Name == "origin" {
|
||||
return remote.Name
|
||||
}
|
||||
}
|
||||
|
||||
return remotes[0].Name
|
||||
}
|
31
pkg/gui/controllers/helpers/upstream_helper_test.go
Normal file
31
pkg/gui/controllers/helpers/upstream_helper_test.go
Normal file
@ -0,0 +1,31 @@
|
||||
package helpers
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/jesseduffield/generics/slices"
|
||||
"github.com/jesseduffield/lazygit/pkg/commands/models"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestGetSuggestedRemote(t *testing.T) {
|
||||
cases := []struct {
|
||||
remotes []*models.Remote
|
||||
expected string
|
||||
}{
|
||||
{mkRemoteList(), "origin"},
|
||||
{mkRemoteList("upstream", "origin", "foo"), "origin"},
|
||||
{mkRemoteList("upstream", "foo", "bar"), "upstream"},
|
||||
}
|
||||
|
||||
for _, c := range cases {
|
||||
result := getSuggestedRemote(c.remotes)
|
||||
assert.EqualValues(t, c.expected, result)
|
||||
}
|
||||
}
|
||||
|
||||
func mkRemoteList(names ...string) []*models.Remote {
|
||||
return slices.Map(names, func(name string) *models.Remote {
|
||||
return &models.Remote{Name: name}
|
||||
})
|
||||
}
|
@ -57,7 +57,7 @@ func (self *RemoteBranchesController) GetKeybindings(opts types.KeybindingsOpts)
|
||||
{
|
||||
Key: opts.GetKey(opts.Config.Branches.SetUpstream),
|
||||
Handler: self.checkSelected(self.setAsUpstream),
|
||||
Description: self.c.Tr.LcSetUpstream,
|
||||
Description: self.c.Tr.LcSetAsUpstream,
|
||||
},
|
||||
{
|
||||
Key: opts.GetKey(opts.Config.Universal.Return),
|
||||
|
@ -1,7 +1,6 @@
|
||||
package controllers
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
@ -13,21 +12,16 @@ import (
|
||||
type SyncController struct {
|
||||
baseController
|
||||
*controllerCommon
|
||||
|
||||
getSuggestedRemote func() string
|
||||
}
|
||||
|
||||
var _ types.IController = &SyncController{}
|
||||
|
||||
func NewSyncController(
|
||||
common *controllerCommon,
|
||||
getSuggestedRemote func() string,
|
||||
) *SyncController {
|
||||
return &SyncController{
|
||||
baseController: baseController{},
|
||||
controllerCommon: common,
|
||||
|
||||
getSuggestedRemote: getSuggestedRemote,
|
||||
}
|
||||
}
|
||||
|
||||
@ -85,8 +79,8 @@ func (self *SyncController) push(currentBranch *models.Branch) error {
|
||||
if self.git.Config.GetPushToCurrent() {
|
||||
return self.pushAux(pushOpts{setUpstream: true})
|
||||
} else {
|
||||
return self.promptForUpstream(currentBranch, func(upstream string) error {
|
||||
upstreamRemote, upstreamBranch, err := self.parseUpstream(upstream)
|
||||
return self.helpers.Upstream.PromptForUpstream(currentBranch, func(upstream string) error {
|
||||
upstreamRemote, upstreamBranch, err := self.helpers.Upstream.ParseUpstream(upstream)
|
||||
if err != nil {
|
||||
return self.c.Error(err)
|
||||
}
|
||||
@ -106,7 +100,7 @@ func (self *SyncController) pull(currentBranch *models.Branch) error {
|
||||
|
||||
// if we have no upstream branch we need to set that first
|
||||
if !currentBranch.IsTrackingRemote() {
|
||||
return self.promptForUpstream(currentBranch, func(upstream string) error {
|
||||
return self.helpers.Upstream.PromptForUpstream(currentBranch, func(upstream string) error {
|
||||
if err := self.setCurrentBranchUpstream(upstream); err != nil {
|
||||
return self.c.Error(err)
|
||||
}
|
||||
@ -119,7 +113,7 @@ func (self *SyncController) pull(currentBranch *models.Branch) error {
|
||||
}
|
||||
|
||||
func (self *SyncController) setCurrentBranchUpstream(upstream string) error {
|
||||
upstreamRemote, upstreamBranch, err := self.parseUpstream(upstream)
|
||||
upstreamRemote, upstreamBranch, err := self.helpers.Upstream.ParseUpstream(upstream)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -136,30 +130,6 @@ func (self *SyncController) setCurrentBranchUpstream(upstream string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *SyncController) parseUpstream(upstream string) (string, string, error) {
|
||||
var upstreamBranch, upstreamRemote string
|
||||
split := strings.Split(upstream, " ")
|
||||
if len(split) != 2 {
|
||||
return "", "", errors.New(self.c.Tr.InvalidUpstream)
|
||||
}
|
||||
|
||||
upstreamRemote = split[0]
|
||||
upstreamBranch = split[1]
|
||||
|
||||
return upstreamRemote, upstreamBranch, nil
|
||||
}
|
||||
|
||||
func (self *SyncController) promptForUpstream(currentBranch *models.Branch, onConfirm func(string) error) error {
|
||||
suggestedRemote := self.getSuggestedRemote()
|
||||
|
||||
return self.c.Prompt(types.PromptOpts{
|
||||
Title: self.c.Tr.EnterUpstream,
|
||||
InitialContent: suggestedRemote + " " + currentBranch.Name,
|
||||
FindSuggestionsFunc: self.helpers.Suggestions.GetRemoteBranchesSuggestionsFunc(" "),
|
||||
HandleConfirm: onConfirm,
|
||||
})
|
||||
}
|
||||
|
||||
type PullFilesOptions struct {
|
||||
UpstreamRemote string
|
||||
UpstreamBranch string
|
||||
|
Reference in New Issue
Block a user