mirror of
https://github.com/jesseduffield/lazygit.git
synced 2025-05-10 20:05:50 +02:00
Show divergence from base branch in branches list
This commit is contained in:
parent
5b613f5bc7
commit
373b1970ca
11 changed files with 281 additions and 51 deletions
|
@ -187,6 +187,10 @@ gui:
|
|||
# If true, show commit hashes alongside branch names in the branches view.
|
||||
showBranchCommitHash: false
|
||||
|
||||
# Whether to show the divergence from the base branch in the branches view.
|
||||
# One of: 'none' | 'onlyArrow' | 'arrowAndNumber'
|
||||
showDivergenceFromBaseBranch: none
|
||||
|
||||
# Height of the command log view
|
||||
commandLogSize: 8
|
||||
|
||||
|
|
|
@ -5,6 +5,7 @@ import (
|
|||
"regexp"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/jesseduffield/generics/set"
|
||||
"github.com/jesseduffield/go-git/v5/config"
|
||||
|
@ -14,6 +15,7 @@ import (
|
|||
"github.com/jesseduffield/lazygit/pkg/utils"
|
||||
"github.com/samber/lo"
|
||||
"golang.org/x/exp/slices"
|
||||
"golang.org/x/sync/errgroup"
|
||||
)
|
||||
|
||||
// context:
|
||||
|
@ -63,7 +65,13 @@ func NewBranchLoader(
|
|||
}
|
||||
|
||||
// Load the list of branches for the current repo
|
||||
func (self *BranchLoader) Load(reflogCommits []*models.Commit) ([]*models.Branch, error) {
|
||||
func (self *BranchLoader) Load(reflogCommits []*models.Commit,
|
||||
mainBranches *MainBranches,
|
||||
oldBranches []*models.Branch,
|
||||
loadBehindCounts bool,
|
||||
onWorker func(func() error),
|
||||
renderFunc func(),
|
||||
) ([]*models.Branch, error) {
|
||||
branches := self.obtainBranches(self.version.IsAtLeast(2, 22, 0))
|
||||
|
||||
if self.AppState.LocalBranchSortOrder == "recency" {
|
||||
|
@ -122,11 +130,75 @@ func (self *BranchLoader) Load(reflogCommits []*models.Commit) ([]*models.Branch
|
|||
branch.UpstreamRemote = match.Remote
|
||||
branch.UpstreamBranch = match.Merge.Short()
|
||||
}
|
||||
|
||||
// If the branch already existed, take over its BehindBaseBranch value
|
||||
// to reduce flicker
|
||||
if oldBranch, found := lo.Find(oldBranches, func(b *models.Branch) bool {
|
||||
return b.Name == branch.Name
|
||||
}); found {
|
||||
branch.BehindBaseBranch.Store(oldBranch.BehindBaseBranch.Load())
|
||||
}
|
||||
}
|
||||
|
||||
if loadBehindCounts && self.UserConfig.Gui.ShowDivergenceFromBaseBranch != "none" {
|
||||
onWorker(func() error {
|
||||
return self.GetBehindBaseBranchValuesForAllBranches(branches, mainBranches, renderFunc)
|
||||
})
|
||||
}
|
||||
|
||||
return branches, nil
|
||||
}
|
||||
|
||||
func (self *BranchLoader) GetBehindBaseBranchValuesForAllBranches(
|
||||
branches []*models.Branch,
|
||||
mainBranches *MainBranches,
|
||||
renderFunc func(),
|
||||
) error {
|
||||
mainBranchRefs := mainBranches.Get()
|
||||
if len(mainBranchRefs) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
t := time.Now()
|
||||
errg := errgroup.Group{}
|
||||
|
||||
for _, branch := range branches {
|
||||
errg.Go(func() error {
|
||||
baseBranch, err := self.GetBaseBranch(branch, mainBranches)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
behind := 0 // prime it in case something below fails
|
||||
if baseBranch != "" {
|
||||
output, err := self.cmd.New(
|
||||
NewGitCmd("rev-list").
|
||||
Arg("--left-right").
|
||||
Arg("--count").
|
||||
Arg(fmt.Sprintf("%s...%s", branch.FullRefName(), baseBranch)).
|
||||
ToArgv(),
|
||||
).DontLog().RunWithOutput()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// The format of the output is "<ahead>\t<behind>"
|
||||
aheadBehindStr := strings.Split(strings.TrimSpace(output), "\t")
|
||||
if len(aheadBehindStr) == 2 {
|
||||
if value, err := strconv.Atoi(aheadBehindStr[1]); err == nil {
|
||||
behind = value
|
||||
}
|
||||
}
|
||||
}
|
||||
branch.BehindBaseBranch.Store(int32(behind))
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
err := errg.Wait()
|
||||
self.Log.Debugf("time to get behind base branch values for all branches: %s", time.Since(t))
|
||||
renderFunc()
|
||||
return err
|
||||
}
|
||||
|
||||
// Find the base branch for the given branch (i.e. the main branch that the
|
||||
// given branch was forked off of)
|
||||
//
|
||||
|
|
|
@ -1,6 +1,9 @@
|
|||
package models
|
||||
|
||||
import "fmt"
|
||||
import (
|
||||
"fmt"
|
||||
"sync/atomic"
|
||||
)
|
||||
|
||||
// Branch : A git branch
|
||||
// duplicating this for now
|
||||
|
@ -32,6 +35,11 @@ type Branch struct {
|
|||
Subject string
|
||||
// commit hash
|
||||
CommitHash string
|
||||
|
||||
// How far we have fallen behind our base branch. 0 means either not
|
||||
// determined yet, or up to date with base branch. (We don't need to
|
||||
// distinguish the two, as we don't draw anything in both cases.)
|
||||
BehindBaseBranch atomic.Int32
|
||||
}
|
||||
|
||||
func (b *Branch) FullRefName() string {
|
||||
|
|
|
@ -129,6 +129,9 @@ type GuiConfig struct {
|
|||
CommitHashLength int `yaml:"commitHashLength" jsonschema:"minimum=0"`
|
||||
// If true, show commit hashes alongside branch names in the branches view.
|
||||
ShowBranchCommitHash bool `yaml:"showBranchCommitHash"`
|
||||
// Whether to show the divergence from the base branch in the branches view.
|
||||
// One of: 'none' | 'onlyArrow' | 'arrowAndNumber'
|
||||
ShowDivergenceFromBaseBranch string `yaml:"showDivergenceFromBaseBranch" jsonschema:"enum=none,enum=onlyArrow,enum=arrowAndNumber"`
|
||||
// Height of the command log view
|
||||
CommandLogSize int `yaml:"commandLogSize" jsonschema:"minimum=0"`
|
||||
// Whether to split the main window when viewing file changes.
|
||||
|
@ -673,27 +676,28 @@ func GetDefaultConfig() *UserConfig {
|
|||
UnstagedChangesColor: []string{"red"},
|
||||
DefaultFgColor: []string{"default"},
|
||||
},
|
||||
CommitLength: CommitLengthConfig{Show: true},
|
||||
SkipNoStagedFilesWarning: false,
|
||||
ShowListFooter: true,
|
||||
ShowCommandLog: true,
|
||||
ShowBottomLine: true,
|
||||
ShowPanelJumps: true,
|
||||
ShowFileTree: true,
|
||||
ShowRandomTip: true,
|
||||
ShowIcons: false,
|
||||
NerdFontsVersion: "",
|
||||
ShowFileIcons: true,
|
||||
CommitHashLength: 8,
|
||||
ShowBranchCommitHash: false,
|
||||
CommandLogSize: 8,
|
||||
SplitDiff: "auto",
|
||||
SkipRewordInEditorWarning: false,
|
||||
WindowSize: "normal",
|
||||
Border: "rounded",
|
||||
AnimateExplosion: true,
|
||||
PortraitMode: "auto",
|
||||
FilterMode: "substring",
|
||||
CommitLength: CommitLengthConfig{Show: true},
|
||||
SkipNoStagedFilesWarning: false,
|
||||
ShowListFooter: true,
|
||||
ShowCommandLog: true,
|
||||
ShowBottomLine: true,
|
||||
ShowPanelJumps: true,
|
||||
ShowFileTree: true,
|
||||
ShowRandomTip: true,
|
||||
ShowIcons: false,
|
||||
NerdFontsVersion: "",
|
||||
ShowFileIcons: true,
|
||||
CommitHashLength: 8,
|
||||
ShowBranchCommitHash: false,
|
||||
ShowDivergenceFromBaseBranch: "none",
|
||||
CommandLogSize: 8,
|
||||
SplitDiff: "auto",
|
||||
SkipRewordInEditorWarning: false,
|
||||
WindowSize: "normal",
|
||||
Border: "rounded",
|
||||
AnimateExplosion: true,
|
||||
PortraitMode: "auto",
|
||||
FilterMode: "substring",
|
||||
Spinner: SpinnerConfig{
|
||||
Frames: []string{"|", "/", "-", "\\"},
|
||||
Rate: 50,
|
||||
|
|
|
@ -7,7 +7,12 @@ import (
|
|||
)
|
||||
|
||||
func (config *UserConfig) Validate() error {
|
||||
if err := validateEnum("gui.statusPanelView", config.Gui.StatusPanelView, []string{"dashboard", "allBranchesLog"}); err != nil {
|
||||
if err := validateEnum("gui.statusPanelView", config.Gui.StatusPanelView,
|
||||
[]string{"dashboard", "allBranchesLog"}); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := validateEnum("gui.showDivergenceFromBaseBranch", config.Gui.ShowDivergenceFromBaseBranch,
|
||||
[]string{"none", "onlyArrow", "arrowAndNumber"}); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
|
|
|
@ -130,7 +130,7 @@ func (self *RefreshHelper) Refresh(options types.RefreshOptions) error {
|
|||
if self.c.AppState.LocalBranchSortOrder == "recency" {
|
||||
refresh("reflog and branches", func() { self.refreshReflogAndBranches(includeWorktreesWithBranches, options.KeepBranchSelectionIndex) })
|
||||
} else {
|
||||
refresh("branches", func() { self.refreshBranches(includeWorktreesWithBranches, options.KeepBranchSelectionIndex) })
|
||||
refresh("branches", func() { self.refreshBranches(includeWorktreesWithBranches, options.KeepBranchSelectionIndex, true) })
|
||||
refresh("reflog", func() { _ = self.refreshReflogCommits() })
|
||||
}
|
||||
} else if scopeSet.Includes(types.REBASE_COMMITS) {
|
||||
|
@ -256,7 +256,7 @@ func (self *RefreshHelper) refreshReflogCommitsConsideringStartup() {
|
|||
case types.INITIAL:
|
||||
self.c.OnWorker(func(_ gocui.Task) error {
|
||||
_ = self.refreshReflogCommits()
|
||||
self.refreshBranches(false, true)
|
||||
self.refreshBranches(false, true, true)
|
||||
self.c.State().GetRepoState().SetStartupStage(types.COMPLETE)
|
||||
return nil
|
||||
})
|
||||
|
@ -267,9 +267,11 @@ func (self *RefreshHelper) refreshReflogCommitsConsideringStartup() {
|
|||
}
|
||||
|
||||
func (self *RefreshHelper) refreshReflogAndBranches(refreshWorktrees bool, keepBranchSelectionIndex bool) {
|
||||
loadBehindCounts := self.c.State().GetRepoState().GetStartupStage() == types.COMPLETE
|
||||
|
||||
self.refreshReflogCommitsConsideringStartup()
|
||||
|
||||
self.refreshBranches(refreshWorktrees, keepBranchSelectionIndex)
|
||||
self.refreshBranches(refreshWorktrees, keepBranchSelectionIndex, loadBehindCounts)
|
||||
}
|
||||
|
||||
func (self *RefreshHelper) refreshCommitsAndCommitFiles() {
|
||||
|
@ -438,7 +440,7 @@ func (self *RefreshHelper) refreshStateSubmoduleConfigs() error {
|
|||
|
||||
// self.refreshStatus is called at the end of this because that's when we can
|
||||
// be sure there is a State.Model.Branches array to pick the current branch from
|
||||
func (self *RefreshHelper) refreshBranches(refreshWorktrees bool, keepBranchSelectionIndex bool) {
|
||||
func (self *RefreshHelper) refreshBranches(refreshWorktrees bool, keepBranchSelectionIndex bool, loadBehindCounts bool) {
|
||||
self.c.Mutexes().RefreshingBranchesMutex.Lock()
|
||||
defer self.c.Mutexes().RefreshingBranchesMutex.Unlock()
|
||||
|
||||
|
@ -457,7 +459,25 @@ func (self *RefreshHelper) refreshBranches(refreshWorktrees bool, keepBranchSele
|
|||
}
|
||||
}
|
||||
|
||||
branches, err := self.c.Git().Loaders.BranchLoader.Load(reflogCommits)
|
||||
branches, err := self.c.Git().Loaders.BranchLoader.Load(
|
||||
reflogCommits,
|
||||
self.c.Model().MainBranches,
|
||||
self.c.Model().Branches,
|
||||
loadBehindCounts,
|
||||
func(f func() error) {
|
||||
self.c.OnWorker(func(_ gocui.Task) error {
|
||||
return f()
|
||||
})
|
||||
},
|
||||
func() {
|
||||
self.c.OnUIThread(func() error {
|
||||
if err := self.c.Contexts().Branches.HandleRender(); err != nil {
|
||||
self.c.Log.Error(err)
|
||||
}
|
||||
self.refreshStatus()
|
||||
return nil
|
||||
})
|
||||
})
|
||||
if err != nil {
|
||||
self.c.Log.Error(err)
|
||||
}
|
||||
|
|
|
@ -155,32 +155,38 @@ func BranchStatus(
|
|||
return style.FgCyan.Sprintf("%s %s", itemOperationStr, utils.Loader(now, userConfig.Gui.Spinner))
|
||||
}
|
||||
|
||||
if !branch.IsTrackingRemote() {
|
||||
return ""
|
||||
result := ""
|
||||
if branch.IsTrackingRemote() {
|
||||
if branch.UpstreamGone {
|
||||
result = style.FgRed.Sprint(tr.UpstreamGone)
|
||||
} else if branch.MatchesUpstream() {
|
||||
result = style.FgGreen.Sprint("✓")
|
||||
} else if branch.RemoteBranchNotStoredLocally() {
|
||||
result = style.FgMagenta.Sprint("?")
|
||||
} else if branch.IsBehindForPull() && branch.IsAheadForPull() {
|
||||
result = style.FgYellow.Sprintf("↓%s↑%s", branch.BehindForPull, branch.AheadForPull)
|
||||
} else if branch.IsBehindForPull() {
|
||||
result = style.FgYellow.Sprintf("↓%s", branch.BehindForPull)
|
||||
} else if branch.IsAheadForPull() {
|
||||
result = style.FgYellow.Sprintf("↑%s", branch.AheadForPull)
|
||||
}
|
||||
}
|
||||
|
||||
if branch.UpstreamGone {
|
||||
return style.FgRed.Sprint(tr.UpstreamGone)
|
||||
if userConfig.Gui.ShowDivergenceFromBaseBranch != "none" {
|
||||
behind := branch.BehindBaseBranch.Load()
|
||||
if behind != 0 {
|
||||
if result != "" {
|
||||
result += " "
|
||||
}
|
||||
if userConfig.Gui.ShowDivergenceFromBaseBranch == "arrowAndNumber" {
|
||||
result += style.FgCyan.Sprintf("↓%d", behind)
|
||||
} else {
|
||||
result += style.FgCyan.Sprintf("↓")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if branch.MatchesUpstream() {
|
||||
return style.FgGreen.Sprint("✓")
|
||||
}
|
||||
if branch.RemoteBranchNotStoredLocally() {
|
||||
return style.FgMagenta.Sprint("?")
|
||||
}
|
||||
|
||||
if branch.IsBehindForPull() && branch.IsAheadForPull() {
|
||||
return style.FgYellow.Sprintf("↓%s↑%s", branch.BehindForPull, branch.AheadForPull)
|
||||
}
|
||||
if branch.IsBehindForPull() {
|
||||
return style.FgYellow.Sprintf("↓%s", branch.BehindForPull)
|
||||
}
|
||||
if branch.IsAheadForPull() {
|
||||
return style.FgYellow.Sprintf("↑%s", branch.AheadForPull)
|
||||
}
|
||||
|
||||
return ""
|
||||
return result
|
||||
}
|
||||
|
||||
func SetCustomBranches(customBranchColors map[string]string) {
|
||||
|
|
|
@ -2,6 +2,7 @@ package presentation
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"sync/atomic"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
|
@ -15,6 +16,11 @@ import (
|
|||
"github.com/xo/terminfo"
|
||||
)
|
||||
|
||||
func makeAtomic(v int32) (result atomic.Int32) {
|
||||
result.Store(v)
|
||||
return //nolint: nakedret
|
||||
}
|
||||
|
||||
func Test_getBranchDisplayStrings(t *testing.T) {
|
||||
scenarios := []struct {
|
||||
branch *models.Branch
|
||||
|
@ -23,6 +29,7 @@ func Test_getBranchDisplayStrings(t *testing.T) {
|
|||
viewWidth int
|
||||
useIcons bool
|
||||
checkedOutByWorktree bool
|
||||
showDivergenceCfg string
|
||||
expected []string
|
||||
}{
|
||||
// First some tests for when the view is wide enough so that everything fits:
|
||||
|
@ -33,6 +40,7 @@ func Test_getBranchDisplayStrings(t *testing.T) {
|
|||
viewWidth: 100,
|
||||
useIcons: false,
|
||||
checkedOutByWorktree: false,
|
||||
showDivergenceCfg: "none",
|
||||
expected: []string{"1m", "branch_name"},
|
||||
},
|
||||
{
|
||||
|
@ -42,6 +50,7 @@ func Test_getBranchDisplayStrings(t *testing.T) {
|
|||
viewWidth: 100,
|
||||
useIcons: false,
|
||||
checkedOutByWorktree: true,
|
||||
showDivergenceCfg: "none",
|
||||
expected: []string{"1m", "branch_name (worktree)"},
|
||||
},
|
||||
{
|
||||
|
@ -51,6 +60,7 @@ func Test_getBranchDisplayStrings(t *testing.T) {
|
|||
viewWidth: 100,
|
||||
useIcons: true,
|
||||
checkedOutByWorktree: true,
|
||||
showDivergenceCfg: "none",
|
||||
expected: []string{"1m", "", "branch_name "},
|
||||
},
|
||||
{
|
||||
|
@ -66,6 +76,7 @@ func Test_getBranchDisplayStrings(t *testing.T) {
|
|||
viewWidth: 100,
|
||||
useIcons: false,
|
||||
checkedOutByWorktree: false,
|
||||
showDivergenceCfg: "none",
|
||||
expected: []string{"1m", "branch_name ✓"},
|
||||
},
|
||||
{
|
||||
|
@ -81,8 +92,57 @@ func Test_getBranchDisplayStrings(t *testing.T) {
|
|||
viewWidth: 100,
|
||||
useIcons: false,
|
||||
checkedOutByWorktree: true,
|
||||
showDivergenceCfg: "none",
|
||||
expected: []string{"1m", "branch_name (worktree) ↓5↑3"},
|
||||
},
|
||||
{
|
||||
branch: &models.Branch{
|
||||
Name: "branch_name",
|
||||
Recency: "1m",
|
||||
BehindBaseBranch: makeAtomic(2),
|
||||
},
|
||||
itemOperation: types.ItemOperationNone,
|
||||
fullDescription: false,
|
||||
viewWidth: 100,
|
||||
useIcons: false,
|
||||
checkedOutByWorktree: false,
|
||||
showDivergenceCfg: "onlyArrow",
|
||||
expected: []string{"1m", "branch_name ↓"},
|
||||
},
|
||||
{
|
||||
branch: &models.Branch{
|
||||
Name: "branch_name",
|
||||
Recency: "1m",
|
||||
UpstreamRemote: "origin",
|
||||
AheadForPull: "0",
|
||||
BehindForPull: "0",
|
||||
BehindBaseBranch: makeAtomic(2),
|
||||
},
|
||||
itemOperation: types.ItemOperationNone,
|
||||
fullDescription: false,
|
||||
viewWidth: 100,
|
||||
useIcons: false,
|
||||
checkedOutByWorktree: false,
|
||||
showDivergenceCfg: "arrowAndNumber",
|
||||
expected: []string{"1m", "branch_name ✓ ↓2"},
|
||||
},
|
||||
{
|
||||
branch: &models.Branch{
|
||||
Name: "branch_name",
|
||||
Recency: "1m",
|
||||
UpstreamRemote: "origin",
|
||||
AheadForPull: "3",
|
||||
BehindForPull: "5",
|
||||
BehindBaseBranch: makeAtomic(2),
|
||||
},
|
||||
itemOperation: types.ItemOperationNone,
|
||||
fullDescription: false,
|
||||
viewWidth: 100,
|
||||
useIcons: false,
|
||||
checkedOutByWorktree: false,
|
||||
showDivergenceCfg: "arrowAndNumber",
|
||||
expected: []string{"1m", "branch_name ↓5↑3 ↓2"},
|
||||
},
|
||||
{
|
||||
branch: &models.Branch{Name: "branch_name", Recency: "1m"},
|
||||
itemOperation: types.ItemOperationPushing,
|
||||
|
@ -90,6 +150,7 @@ func Test_getBranchDisplayStrings(t *testing.T) {
|
|||
viewWidth: 100,
|
||||
useIcons: false,
|
||||
checkedOutByWorktree: false,
|
||||
showDivergenceCfg: "none",
|
||||
expected: []string{"1m", "branch_name Pushing |"},
|
||||
},
|
||||
{
|
||||
|
@ -108,6 +169,7 @@ func Test_getBranchDisplayStrings(t *testing.T) {
|
|||
viewWidth: 100,
|
||||
useIcons: false,
|
||||
checkedOutByWorktree: false,
|
||||
showDivergenceCfg: "none",
|
||||
expected: []string{"1m", "12345678", "branch_name ✓", "origin branch_name", "commit title"},
|
||||
},
|
||||
|
||||
|
@ -119,6 +181,7 @@ func Test_getBranchDisplayStrings(t *testing.T) {
|
|||
viewWidth: 14,
|
||||
useIcons: false,
|
||||
checkedOutByWorktree: false,
|
||||
showDivergenceCfg: "none",
|
||||
expected: []string{"1m", "branch_na…"},
|
||||
},
|
||||
{
|
||||
|
@ -128,6 +191,7 @@ func Test_getBranchDisplayStrings(t *testing.T) {
|
|||
viewWidth: 14,
|
||||
useIcons: false,
|
||||
checkedOutByWorktree: true,
|
||||
showDivergenceCfg: "none",
|
||||
expected: []string{"1m", "bra… (worktree)"},
|
||||
},
|
||||
{
|
||||
|
@ -137,6 +201,7 @@ func Test_getBranchDisplayStrings(t *testing.T) {
|
|||
viewWidth: 14,
|
||||
useIcons: true,
|
||||
checkedOutByWorktree: true,
|
||||
showDivergenceCfg: "none",
|
||||
expected: []string{"1m", "", "branc… "},
|
||||
},
|
||||
{
|
||||
|
@ -152,6 +217,7 @@ func Test_getBranchDisplayStrings(t *testing.T) {
|
|||
viewWidth: 14,
|
||||
useIcons: false,
|
||||
checkedOutByWorktree: false,
|
||||
showDivergenceCfg: "none",
|
||||
expected: []string{"1m", "branch_… ✓"},
|
||||
},
|
||||
{
|
||||
|
@ -167,6 +233,7 @@ func Test_getBranchDisplayStrings(t *testing.T) {
|
|||
viewWidth: 30,
|
||||
useIcons: false,
|
||||
checkedOutByWorktree: true,
|
||||
showDivergenceCfg: "none",
|
||||
expected: []string{"1m", "branch_na… (worktree) ↓5↑3"},
|
||||
},
|
||||
{
|
||||
|
@ -176,6 +243,7 @@ func Test_getBranchDisplayStrings(t *testing.T) {
|
|||
viewWidth: 20,
|
||||
useIcons: false,
|
||||
checkedOutByWorktree: false,
|
||||
showDivergenceCfg: "none",
|
||||
expected: []string{"1m", "branc… Pushing |"},
|
||||
},
|
||||
{
|
||||
|
@ -185,6 +253,7 @@ func Test_getBranchDisplayStrings(t *testing.T) {
|
|||
viewWidth: -1,
|
||||
useIcons: false,
|
||||
checkedOutByWorktree: false,
|
||||
showDivergenceCfg: "none",
|
||||
expected: []string{"1m", "abc Pushing |"},
|
||||
},
|
||||
{
|
||||
|
@ -194,6 +263,7 @@ func Test_getBranchDisplayStrings(t *testing.T) {
|
|||
viewWidth: -1,
|
||||
useIcons: false,
|
||||
checkedOutByWorktree: false,
|
||||
showDivergenceCfg: "none",
|
||||
expected: []string{"1m", "ab Pushing |"},
|
||||
},
|
||||
{
|
||||
|
@ -203,6 +273,7 @@ func Test_getBranchDisplayStrings(t *testing.T) {
|
|||
viewWidth: -1,
|
||||
useIcons: false,
|
||||
checkedOutByWorktree: false,
|
||||
showDivergenceCfg: "none",
|
||||
expected: []string{"1m", "a Pushing |"},
|
||||
},
|
||||
{
|
||||
|
@ -221,6 +292,7 @@ func Test_getBranchDisplayStrings(t *testing.T) {
|
|||
viewWidth: 20,
|
||||
useIcons: false,
|
||||
checkedOutByWorktree: false,
|
||||
showDivergenceCfg: "none",
|
||||
expected: []string{"1m", "12345678", "bran… ✓", "origin branch_name", "commit title"},
|
||||
},
|
||||
}
|
||||
|
@ -232,6 +304,7 @@ func Test_getBranchDisplayStrings(t *testing.T) {
|
|||
|
||||
for i, s := range scenarios {
|
||||
icons.SetNerdFontsVersion(lo.Ternary(s.useIcons, "3", ""))
|
||||
c.UserConfig.Gui.ShowDivergenceFromBaseBranch = s.showDivergenceCfg
|
||||
|
||||
worktrees := []*models.Worktree{}
|
||||
if s.checkedOutByWorktree {
|
||||
|
|
|
@ -0,0 +1,27 @@
|
|||
package status
|
||||
|
||||
import (
|
||||
"github.com/jesseduffield/lazygit/pkg/config"
|
||||
. "github.com/jesseduffield/lazygit/pkg/integration/components"
|
||||
)
|
||||
|
||||
var ShowDivergenceFromBaseBranch = NewIntegrationTest(NewIntegrationTestArgs{
|
||||
Description: "Show divergence from base branch in the status panel",
|
||||
ExtraCmdArgs: []string{},
|
||||
Skip: false,
|
||||
SetupConfig: func(config *config.AppConfig) {
|
||||
config.UserConfig.Gui.ShowDivergenceFromBaseBranch = "arrowAndNumber"
|
||||
},
|
||||
SetupRepo: func(shell *Shell) {
|
||||
shell.CreateNCommits(2)
|
||||
shell.CloneIntoRemote("origin")
|
||||
shell.NewBranch("feature")
|
||||
shell.HardReset("HEAD^")
|
||||
},
|
||||
Run: func(t *TestDriver, keys config.KeybindingConfig) {
|
||||
t.GlobalPress(keys.Universal.NextBlock)
|
||||
|
||||
t.Views().Status().
|
||||
Content(Equals("↓1 repo → feature"))
|
||||
},
|
||||
})
|
|
@ -266,6 +266,7 @@ var tests = []*components.IntegrationTest{
|
|||
status.ClickRepoNameToOpenReposMenu,
|
||||
status.ClickToFocus,
|
||||
status.ClickWorkingTreeStateToOpenRebaseOptionsMenu,
|
||||
status.ShowDivergenceFromBaseBranch,
|
||||
submodule.Add,
|
||||
submodule.Enter,
|
||||
submodule.EnterNested,
|
||||
|
|
|
@ -331,6 +331,16 @@
|
|||
"description": "If true, show commit hashes alongside branch names in the branches view.",
|
||||
"default": false
|
||||
},
|
||||
"showDivergenceFromBaseBranch": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"none",
|
||||
"onlyArrow",
|
||||
"arrowAndNumber"
|
||||
],
|
||||
"description": "Whether to show the divergence from the base branch in the branches view.\nOne of: 'none' | 'onlyArrow' | 'arrowAndNumber'",
|
||||
"default": "none"
|
||||
},
|
||||
"commandLogSize": {
|
||||
"type": "integer",
|
||||
"minimum": 0,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue