Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add option to (un)set upstream for a local branch #1869

Merged
merged 4 commits into from
May 6, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 1 addition & 0 deletions docs/keybindings/Keybindings_en.md
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ _This file is auto-generated. To update, make the changes in the pkg/i18n direct
<kbd>f</kbd>: fast-forward this branch from its upstream
<kbd>g</kbd>: view reset options
<kbd>R</kbd>: rename branch
<kbd>u</kbd>: set/unset upstream
<kbd>enter</kbd>: view commits
</pre>

Expand Down
1 change: 1 addition & 0 deletions docs/keybindings/Keybindings_nl.md
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@ _This file is auto-generated. To update, make the changes in the pkg/i18n direct
<kbd>f</kbd>: fast-forward deze branch vanaf zijn upstream
<kbd>g</kbd>: bekijk reset opties
<kbd>R</kbd>: hernoem branch
<kbd>u</kbd>: set/unset upstream
<kbd>enter</kbd>: bekijk commits
</pre>

Expand Down
1 change: 1 addition & 0 deletions docs/keybindings/Keybindings_pl.md
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ _This file is auto-generated. To update, make the changes in the pkg/i18n direct
<kbd>f</kbd>: fast-forward this branch from its upstream
<kbd>g</kbd>: wyświetl opcje resetu
<kbd>R</kbd>: rename branch
<kbd>u</kbd>: set/unset upstream
<kbd>enter</kbd>: view commits
</pre>

Expand Down
1 change: 1 addition & 0 deletions docs/keybindings/Keybindings_zh.md
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ _This file is auto-generated. To update, make the changes in the pkg/i18n direct
<kbd>f</kbd>: 从上游快进此分支
<kbd>g</kbd>: 查看重置选项
<kbd>R</kbd>: 重命名分支
<kbd>u</kbd>: set/unset upstream
<kbd>enter</kbd>: 查看提交
</pre>

Expand Down
4 changes: 4 additions & 0 deletions pkg/commands/git_commands/branch.go
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,10 @@ func (self *BranchCommands) SetUpstream(remoteName string, remoteBranchName stri
return self.cmd.New(fmt.Sprintf("git branch --set-upstream-to=%s/%s %s", self.cmd.Quote(remoteName), self.cmd.Quote(remoteBranchName), self.cmd.Quote(branchName))).Run()
}

func (self *BranchCommands) UnsetUpstream(branchName string) error {
return self.cmd.New(fmt.Sprintf("git branch --unset-upstream %s", self.cmd.Quote(branchName))).Run()
}

func (self *BranchCommands) GetCurrentBranchUpstreamDifferenceCount() (string, string) {
return self.GetCommitDifferences("HEAD", "HEAD@{u}")
}
Expand Down
5 changes: 3 additions & 2 deletions pkg/gui/controllers.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,13 @@ func (gui *Gui) resetControllers() {
)

rebaseHelper := helpers.NewMergeAndRebaseHelper(helperCommon, gui.State.Contexts, gui.git, gui.takeOverMergeConflictScrolling, refsHelper)
suggestionsHelper := helpers.NewSuggestionsHelper(helperCommon, model, gui.refreshSuggestions)
gui.helpers = &helpers.Helpers{
Refs: refsHelper,
Host: helpers.NewHostHelper(helperCommon, gui.git),
PatchBuilding: helpers.NewPatchBuildingHelper(helperCommon, gui.git),
Bisect: helpers.NewBisectHelper(helperCommon, gui.git),
Suggestions: helpers.NewSuggestionsHelper(helperCommon, model, gui.refreshSuggestions),
Suggestions: suggestionsHelper,
Files: helpers.NewFilesHelper(helperCommon, gui.git, osCommand),
WorkingTree: helpers.NewWorkingTreeHelper(helperCommon, gui.git, model),
Tags: helpers.NewTagsHelper(helperCommon, gui.git),
Expand All @@ -41,6 +42,7 @@ func (gui *Gui) resetControllers() {
func() *cherrypicking.CherryPicking { return gui.State.Modes.CherryPicking },
rebaseHelper,
),
Upstream: helpers.NewUpstreamHelper(helperCommon, model, suggestionsHelper.GetRemoteBranchesSuggestionsFunc),
}

gui.CustomCommandsClient = custom_commands.NewClient(
Expand All @@ -64,7 +66,6 @@ func (gui *Gui) resetControllers() {

syncController := controllers.NewSyncController(
common,
gui.getSuggestedRemote,
)

submodulesController := controllers.NewSubmodulesController(
Expand Down
59 changes: 59 additions & 0 deletions pkg/gui/controllers/branches_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -97,9 +97,68 @@ 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)
}
if err := self.c.Refresh(types.RefreshOptions{
Mode: types.SYNC,
Scope: []types.RefreshableView{
types.BRANCHES,
types.COMMITS,
},
}); err != nil {
return self.c.Error(err)
}
return nil
},
Key: 'u',
},
{
DisplayStrings: []string{self.c.Tr.LcSetUpstream},
OnPress: func() error {
return self.helpers.Upstream.PromptForUpstreamWithoutInitialContent(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)
}
if err := self.c.Refresh(types.RefreshOptions{
Mode: types.SYNC,
Scope: []types.RefreshableView{
types.BRANCHES,
types.COMMITS,
},
}); err != nil {
return self.c.Error(err)
}
return nil
})
},
Key: 's',
},
},
})
}

func (self *BranchesController) Context() types.Context {
return self.context()
}
Expand Down
2 changes: 2 additions & 0 deletions pkg/gui/controllers/helpers/helpers.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ type Helpers struct {
Host *HostHelper
PatchBuilding *PatchBuildingHelper
GPG *GpgHelper
Upstream *UpstreamHelper
}

func NewStubHelpers() *Helpers {
Expand All @@ -27,5 +28,6 @@ func NewStubHelpers() *Helpers {
Host: &HostHelper{},
PatchBuilding: &PatchBuildingHelper{},
GPG: &GpgHelper{},
Upstream: &UpstreamHelper{},
}
}
88 changes: 88 additions & 0 deletions pkg/gui/controllers/helpers/upstream_helper.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
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)
PromptForUpstreamWithInitialContent(*models.Branch, func(string) error) error
PromptForUpstreamWithoutInitialContent(*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, initialContent string, onConfirm func(string) error) error {
return self.c.Prompt(types.PromptOpts{
Title: self.c.Tr.EnterUpstream,
InitialContent: initialContent,
FindSuggestionsFunc: self.getRemoteBranchesSuggestionsFunc(" "),
HandleConfirm: onConfirm,
})
}

func (self *UpstreamHelper) PromptForUpstreamWithInitialContent(currentBranch *models.Branch, onConfirm func(string) error) error {
suggestedRemote := self.GetSuggestedRemote()
initialContent := suggestedRemote + " " + currentBranch.Name

return self.promptForUpstream(currentBranch, initialContent, onConfirm)
}

func (self *UpstreamHelper) PromptForUpstreamWithoutInitialContent(currentBranch *models.Branch, onConfirm func(string) error) error {
return self.promptForUpstream(currentBranch, "", 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
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package gui
package helpers

import (
"testing"
Expand Down
2 changes: 1 addition & 1 deletion pkg/gui/controllers/remote_branches_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -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),
Expand Down
38 changes: 4 additions & 34 deletions pkg/gui/controllers/sync_controller.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package controllers

import (
"errors"
"fmt"
"strings"

Expand All @@ -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,
}
}

Expand Down Expand Up @@ -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.PromptForUpstreamWithInitialContent(currentBranch, func(upstream string) error {
upstreamRemote, upstreamBranch, err := self.helpers.Upstream.ParseUpstream(upstream)
if err != nil {
return self.c.Error(err)
}
Expand All @@ -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.PromptForUpstreamWithInitialContent(currentBranch, func(upstream string) error {
if err := self.setCurrentBranchUpstream(upstream); err != nil {
return self.c.Error(err)
}
Expand All @@ -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
}
Expand All @@ -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
Expand Down
25 changes: 0 additions & 25 deletions pkg/gui/misc.go

This file was deleted.

1 change: 1 addition & 0 deletions pkg/i18n/chinese.go
Original file line number Diff line number Diff line change
Expand Up @@ -312,6 +312,7 @@ func chineseTranslationSet() TranslationSet {
DeleteRemoteBranch: "删除远程分支",
DeleteRemoteBranchMessage: "您确定要删除远程分支吗?",
LcSetUpstream: "设置为检出分支的上游",
LcSetAsUpstream: "设置为检出分支的上游",
SetUpstreamTitle: "设置上游分支",
SetUpstreamMessage: "您确定要将 {{.checkedOut}} 的上游分支设置为 {{.selected}} 吗?",
LcEditRemote: "编辑远程仓库",
Expand Down
1 change: 1 addition & 0 deletions pkg/i18n/dutch.go
Original file line number Diff line number Diff line change
Expand Up @@ -271,6 +271,7 @@ func dutchTranslationSet() TranslationSet {
DeleteRemoteBranch: "Verwijder Remote Branch",
DeleteRemoteBranchMessage: "Weet je zeker dat je deze remote branch wilt verwijderen",
LcSetUpstream: "stel in als upstream van uitgecheckte branch",
LcSetAsUpstream: "stel in als upstream van uitgecheckte branch",
SetUpstreamTitle: "Stel in als upstream branch",
SetUpstreamMessage: "Weet je zeker dat je de upstream branch van '{{.checkedOut}}' naar '{{.selected}}' wilt zetten",
LcEditRemote: "wijzig remote",
Expand Down