1
0
mirror of https://github.com/jesseduffield/lazygit.git synced 2024-11-28 09:08:41 +02:00

Add inline status for pushing/pulling/fast-forwarding branches

When pulling/pushing/fast-forwarding a branch, show this state in the branches
list for that branch for as long as the operation takes, to make it easier to
see when it's done (without having to stare at the status bar in the lower
left).

This will hopefully help with making these operations feel more predictable, now
that we no longer show a loader panel for them.
This commit is contained in:
Stefan Haller 2023-10-08 18:09:29 +02:00
parent 7075b66bc6
commit 707fa37160
15 changed files with 71 additions and 38 deletions

View File

@ -65,6 +65,10 @@ func (b *Branch) ID() string {
return b.RefName()
}
func (b *Branch) URN() string {
return "branch-" + b.ID()
}
func (b *Branch) Description() string {
return b.RefName()
}

View File

@ -27,6 +27,7 @@ func NewBranchesContext(c *ContextCommon) *BranchesContext {
getDisplayStrings := func(_ int, _ int) [][]string {
return presentation.GetBranchListDisplayStrings(
viewModel.GetItems(),
c.State().GetItemOperation,
c.State().GetRepoState().GetScreenMode() != types.SCREEN_NORMAL,
c.Modes().Diffing.Ref,
c.Tr,

View File

@ -563,14 +563,7 @@ func (self *BranchesController) fastForward(branch *models.Branch) error {
action := self.c.Tr.Actions.FastForwardBranch
message := utils.ResolvePlaceholderString(
self.c.Tr.FastForwarding,
map[string]string{
"branch": branch.Name,
},
)
return self.c.WithWaitingStatus(message, func(task gocui.Task) error {
return self.c.WithInlineStatus(branch, types.ItemOperationFastForwarding, context.LOCAL_BRANCHES_CONTEXT_KEY, func(task gocui.Task) error {
worktree, ok := self.worktreeForBranch(branch)
if ok {
self.c.LogAction(action)

View File

@ -678,7 +678,7 @@ func (self *RefreshHelper) refreshStatus() {
repoName := self.c.Git().RepoPaths.RepoName()
status := presentation.FormatStatus(repoName, currentBranch, linkedWorktreeName, workingTreeState, self.c.Tr)
status := presentation.FormatStatus(repoName, currentBranch, types.ItemOperationNone, linkedWorktreeName, workingTreeState, self.c.Tr)
self.c.SetViewContent(self.c.Views().Status, status)
}

View File

@ -106,7 +106,7 @@ func (self *StatusController) onClick() error {
}
cx, _ := self.c.Views().Status.Cursor()
upstreamStatus := presentation.BranchStatus(currentBranch, self.c.Tr)
upstreamStatus := presentation.BranchStatus(currentBranch, types.ItemOperationNone, self.c.Tr)
repoName := self.c.Git().RepoPaths.RepoName()
workingTreeState := self.c.Git().Status.WorkingTreeState()
switch workingTreeState {

View File

@ -7,6 +7,7 @@ import (
"github.com/jesseduffield/gocui"
"github.com/jesseduffield/lazygit/pkg/commands/git_commands"
"github.com/jesseduffield/lazygit/pkg/commands/models"
"github.com/jesseduffield/lazygit/pkg/gui/context"
"github.com/jesseduffield/lazygit/pkg/gui/types"
"github.com/jesseduffield/lazygit/pkg/utils"
)
@ -73,13 +74,13 @@ func (self *SyncController) push(currentBranch *models.Branch) error {
if currentBranch.IsTrackingRemote() {
opts := pushOpts{}
if currentBranch.HasCommitsToPull() {
return self.requestToForcePush(opts)
return self.requestToForcePush(currentBranch, opts)
} else {
return self.pushAux(opts)
return self.pushAux(currentBranch, opts)
}
} else {
if self.c.Git().Config.GetPushToCurrent() {
return self.pushAux(pushOpts{setUpstream: true})
return self.pushAux(currentBranch, pushOpts{setUpstream: true})
} else {
return self.c.Helpers().Upstream.PromptForUpstreamWithInitialContent(currentBranch, func(upstream string) error {
upstreamRemote, upstreamBranch, err := self.c.Helpers().Upstream.ParseUpstream(upstream)
@ -87,7 +88,7 @@ func (self *SyncController) push(currentBranch *models.Branch) error {
return self.c.Error(err)
}
return self.pushAux(pushOpts{
return self.pushAux(currentBranch, pushOpts{
setUpstream: true,
upstreamRemote: upstreamRemote,
upstreamBranch: upstreamBranch,
@ -107,11 +108,11 @@ func (self *SyncController) pull(currentBranch *models.Branch) error {
return self.c.Error(err)
}
return self.PullAux(PullFilesOptions{Action: action})
return self.PullAux(currentBranch, PullFilesOptions{Action: action})
})
}
return self.PullAux(PullFilesOptions{Action: action})
return self.PullAux(currentBranch, PullFilesOptions{Action: action})
}
func (self *SyncController) setCurrentBranchUpstream(upstream string) error {
@ -139,8 +140,8 @@ type PullFilesOptions struct {
Action string
}
func (self *SyncController) PullAux(opts PullFilesOptions) error {
return self.c.WithWaitingStatus(self.c.Tr.PullingStatus, func(task gocui.Task) error {
func (self *SyncController) PullAux(currentBranch *models.Branch, opts PullFilesOptions) error {
return self.c.WithInlineStatus(currentBranch, types.ItemOperationPulling, context.LOCAL_BRANCHES_CONTEXT_KEY, func(task gocui.Task) error {
return self.pullWithLock(task, opts)
})
}
@ -167,8 +168,8 @@ type pushOpts struct {
setUpstream bool
}
func (self *SyncController) pushAux(opts pushOpts) error {
return self.c.WithWaitingStatus(self.c.Tr.PushingStatus, func(task gocui.Task) error {
func (self *SyncController) pushAux(currentBranch *models.Branch, opts pushOpts) error {
return self.c.WithInlineStatus(currentBranch, types.ItemOperationPushing, context.LOCAL_BRANCHES_CONTEXT_KEY, func(task gocui.Task) error {
self.c.LogAction(self.c.Tr.Actions.Push)
err := self.c.Git().Sync.Push(
task,
@ -192,18 +193,18 @@ func (self *SyncController) pushAux(opts pushOpts) error {
newOpts := opts
newOpts.force = true
return self.pushAux(newOpts)
return self.pushAux(currentBranch, newOpts)
},
})
return nil
}
_ = self.c.Error(err)
return err
}
return self.c.Refresh(types.RefreshOptions{Mode: types.ASYNC})
})
}
func (self *SyncController) requestToForcePush(opts pushOpts) error {
func (self *SyncController) requestToForcePush(currentBranch *models.Branch, opts pushOpts) error {
forcePushDisabled := self.c.UserConfig.Git.DisableForcePushing
if forcePushDisabled {
return self.c.ErrorMsg(self.c.Tr.ForcePushDisabled)
@ -214,7 +215,7 @@ func (self *SyncController) requestToForcePush(opts pushOpts) error {
Prompt: self.forcePushPrompt(),
HandleConfirm: func() error {
opts.force = true
return self.pushAux(opts)
return self.pushAux(currentBranch, opts)
},
})
}

View File

@ -9,6 +9,7 @@ import (
"github.com/jesseduffield/lazygit/pkg/config"
"github.com/jesseduffield/lazygit/pkg/gui/presentation/icons"
"github.com/jesseduffield/lazygit/pkg/gui/style"
"github.com/jesseduffield/lazygit/pkg/gui/types"
"github.com/jesseduffield/lazygit/pkg/i18n"
"github.com/jesseduffield/lazygit/pkg/theme"
"github.com/jesseduffield/lazygit/pkg/utils"
@ -19,6 +20,7 @@ var branchPrefixColorCache = make(map[string]style.TextStyle)
func GetBranchListDisplayStrings(
branches []*models.Branch,
getItemOperation func(item types.HasUrn) types.ItemOperation,
fullDescription bool,
diffName string,
tr *i18n.TranslationSet,
@ -27,13 +29,14 @@ func GetBranchListDisplayStrings(
) [][]string {
return lo.Map(branches, func(branch *models.Branch, _ int) []string {
diffed := branch.Name == diffName
return getBranchDisplayStrings(branch, fullDescription, diffed, tr, userConfig, worktrees)
return getBranchDisplayStrings(branch, getItemOperation(branch), fullDescription, diffed, tr, userConfig, worktrees)
})
}
// getBranchDisplayStrings returns the display string of branch
func getBranchDisplayStrings(
b *models.Branch,
itemOperation types.ItemOperation,
fullDescription bool,
diffed bool,
tr *i18n.TranslationSet,
@ -51,7 +54,7 @@ func getBranchDisplayStrings(
}
coloredName := nameTextStyle.Sprint(displayName)
branchStatus := utils.WithPadding(ColoredBranchStatus(b, tr), 2, utils.AlignLeft)
branchStatus := utils.WithPadding(ColoredBranchStatus(b, itemOperation, tr), 2, utils.AlignLeft)
if git_commands.CheckedOutByOtherWorktree(b, worktrees) {
worktreeIcon := lo.Ternary(icons.IsIconEnabled(), icons.LINKED_WORKTREE_ICON, fmt.Sprintf("(%s)", tr.LcWorktree))
coloredName = fmt.Sprintf("%s %s", coloredName, style.FgDefault.Sprint(worktreeIcon))
@ -109,9 +112,11 @@ func GetBranchTextStyle(name string) style.TextStyle {
}
}
func ColoredBranchStatus(branch *models.Branch, tr *i18n.TranslationSet) string {
func ColoredBranchStatus(branch *models.Branch, itemOperation types.ItemOperation, tr *i18n.TranslationSet) string {
colour := style.FgYellow
if branch.UpstreamGone {
if itemOperation != types.ItemOperationNone {
colour = style.FgCyan
} else if branch.UpstreamGone {
colour = style.FgRed
} else if branch.MatchesUpstream() {
colour = style.FgGreen
@ -119,10 +124,15 @@ func ColoredBranchStatus(branch *models.Branch, tr *i18n.TranslationSet) string
colour = style.FgMagenta
}
return colour.Sprint(BranchStatus(branch, tr))
return colour.Sprint(BranchStatus(branch, itemOperation, tr))
}
func BranchStatus(branch *models.Branch, tr *i18n.TranslationSet) string {
func BranchStatus(branch *models.Branch, itemOperation types.ItemOperation, tr *i18n.TranslationSet) string {
itemOperationStr := itemOperationToString(itemOperation, tr)
if itemOperationStr != "" {
return itemOperationStr + " " + utils.Loader()
}
if !branch.IsTrackingRemote() {
return ""
}

View File

@ -0,0 +1,23 @@
package presentation
import (
"github.com/jesseduffield/lazygit/pkg/gui/types"
"github.com/jesseduffield/lazygit/pkg/i18n"
)
func itemOperationToString(itemOperation types.ItemOperation, tr *i18n.TranslationSet) string {
switch itemOperation {
case types.ItemOperationNone:
return ""
case types.ItemOperationPushing:
return tr.PushingStatus
case types.ItemOperationPulling:
return tr.PullingStatus
case types.ItemOperationFastForwarding:
return tr.FastForwarding
case types.ItemOperationDeleting:
return tr.DeletingStatus
}
return ""
}

View File

@ -7,14 +7,15 @@ import (
"github.com/jesseduffield/lazygit/pkg/commands/types/enums"
"github.com/jesseduffield/lazygit/pkg/gui/presentation/icons"
"github.com/jesseduffield/lazygit/pkg/gui/style"
"github.com/jesseduffield/lazygit/pkg/gui/types"
"github.com/jesseduffield/lazygit/pkg/i18n"
)
func FormatStatus(repoName string, currentBranch *models.Branch, linkedWorktreeName string, workingTreeState enums.RebaseMode, tr *i18n.TranslationSet) string {
func FormatStatus(repoName string, currentBranch *models.Branch, itemOperation types.ItemOperation, linkedWorktreeName string, workingTreeState enums.RebaseMode, tr *i18n.TranslationSet) string {
status := ""
if currentBranch.IsRealBranch() {
status += ColoredBranchStatus(currentBranch, tr) + " "
status += ColoredBranchStatus(currentBranch, itemOperation, tr) + " "
}
if workingTreeState != enums.REBASE_MODE_NONE {

View File

@ -169,7 +169,7 @@ func chineseTranslationSet() TranslationSet {
ToggleStagingPanel: `切换到其他面板`,
ReturnToFilesPanel: `返回文件面板`,
FastForward: `从上游快进此分支`,
FastForwarding: "抓取并快进 {{.branch}} ...",
FastForwarding: "抓取并快进",
FoundConflictsTitle: "自动合并失败",
ViewMergeRebaseOptions: "查看 合并/变基 选项",
NotMergingOrRebasing: "您目前既不进行变基也不进行合并",

View File

@ -134,7 +134,7 @@ func dutchTranslationSet() TranslationSet {
ToggleStagingPanel: `Ga naar een ander paneel`,
ReturnToFilesPanel: `Ga terug naar het bestanden paneel`,
FastForward: `Fast-forward deze branch vanaf zijn upstream`,
FastForwarding: "Fast-forwarding {{.branch}} ...",
FastForwarding: "Fast-forwarding",
FoundConflictsTitle: "Conflicten!",
ViewMergeRebaseOptions: "Bekijk merge/rebase opties",
NotMergingOrRebasing: "Je bent momenteel niet aan het rebasen of mergen",

View File

@ -980,7 +980,7 @@ func EnglishTranslationSet() TranslationSet {
ToggleStagingPanel: `Switch to other panel (staged/unstaged changes)`,
ReturnToFilesPanel: `Return to files panel`,
FastForward: `Fast-forward this branch from its upstream`,
FastForwarding: "Fast-forwarding {{.branch}}",
FastForwarding: "Fast-forwarding",
FoundConflictsTitle: "Conflicts!",
ViewConflictsMenuItem: "View conflicts",
AbortMenuItem: "Abort the %s",

View File

@ -170,7 +170,7 @@ func koreanTranslationSet() TranslationSet {
ToggleStagingPanel: `패널 전환`,
ReturnToFilesPanel: `파일 목록으로 돌아가기`,
FastForward: `Fast-forward this branch from its upstream`,
FastForwarding: "Fast-forwarding {{.branch}} ...",
FastForwarding: "Fast-forwarding",
FoundConflictsTitle: "Auto-merge failed",
ViewMergeRebaseOptions: "View merge/rebase options",
NotMergingOrRebasing: "You are currently neither rebasing nor merging",

View File

@ -201,7 +201,7 @@ func RussianTranslationSet() TranslationSet {
ToggleStagingPanel: `Переключиться на другую панель (проиндексированные/непроиндексированные изменения)`,
ReturnToFilesPanel: `Вернуться к панели файлов`,
FastForward: `Перемотать эту ветку вперёд из её upstream-ветки`,
FastForwarding: "Получить изменения и перемотать вперёд {{.branch}} ...",
FastForwarding: "Получить изменения и перемотать вперёд",
FoundConflictsTitle: "Конфликты!",
ViewConflictsMenuItem: "Просмотр конфликтов",
AbortMenuItem: "Прервать %s",

View File

@ -234,7 +234,7 @@ func traditionalChineseTranslationSet() TranslationSet {
ToggleStagingPanel: `切換至另一個面板 (已預存/未預存更改)`,
ReturnToFilesPanel: `返回檔案面板`,
FastForward: `從上游快進此分支`,
FastForwarding: "{{.branch}} 的擷取和快進中...",
FastForwarding: "的擷取和快進中",
FoundConflictsTitle: "自動合併失敗",
ViewMergeRebaseOptions: "查看合併/變基選項",
NotMergingOrRebasing: "你當前既不在變基也不在合併中",