Compare commits
16 Commits
create-pul
...
rebase-ont
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3dc960b475 | ||
|
|
de7ee9af21 | ||
|
|
eded3ccf54 | ||
|
|
b3252ee7c8 | ||
|
|
f2e8e3fcc1 | ||
|
|
7acf96bd0d | ||
|
|
9ede2f025e | ||
|
|
f58b7da7dc | ||
|
|
b23ea3b190 | ||
|
|
4d2177725f | ||
|
|
6d2ec43596 | ||
|
|
6eaece3696 | ||
|
|
316ea99d67 | ||
|
|
e7ac70c415 | ||
|
|
aba0290e51 | ||
|
|
2ae1bea20a |
@@ -74,6 +74,7 @@ gui:
|
||||
showListFooter: true # for seeing the '5 of 20' message in list panels
|
||||
showRandomTip: true
|
||||
showBranchCommitHash: false # show commit hashes alongside branch names
|
||||
showDivergenceFromBaseBranch: onlyBehind # one of 'off' | 'onlyBehind' | 'behindAndAhead'
|
||||
showBottomLine: true # for hiding the bottom information line (unless it has important information to tell you)
|
||||
showPanelJumps: true # for showing the jump-to-panel keybindings as panel subtitles
|
||||
showCommandLog: true
|
||||
|
||||
@@ -5,7 +5,10 @@ import (
|
||||
"regexp"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/go-errors/errors"
|
||||
"github.com/jesseduffield/generics/set"
|
||||
"github.com/jesseduffield/go-git/v5/config"
|
||||
"github.com/jesseduffield/lazygit/pkg/commands/models"
|
||||
@@ -60,7 +63,7 @@ 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, existingMainBranches *ExistingMainBranches, oldBranches []*models.Branch, onWorker func(func() error), renderFunc func()) ([]*models.Branch, error) {
|
||||
branches := self.obtainBranches()
|
||||
|
||||
if self.AppState.LocalBranchSortOrder == "recency" {
|
||||
@@ -119,11 +122,109 @@ func (self *BranchLoader) Load(reflogCommits []*models.Commit) ([]*models.Branch
|
||||
branch.UpstreamRemote = match.Remote
|
||||
branch.UpstreamBranch = match.Merge.Short()
|
||||
}
|
||||
|
||||
if oldBranch, found := lo.Find(oldBranches, func(b *models.Branch) bool {
|
||||
return b.Name == branch.Name
|
||||
}); found {
|
||||
branch.BehindBaseBranch.Store(oldBranch.BehindBaseBranch.Load())
|
||||
branch.AheadOfBaseBranch.Store(oldBranch.AheadOfBaseBranch.Load())
|
||||
}
|
||||
}
|
||||
|
||||
onWorker(func() error {
|
||||
mainBranches := existingMainBranches.Get()
|
||||
if len(mainBranches) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
t := time.Now()
|
||||
wg := sync.WaitGroup{}
|
||||
for _, branch := range branches {
|
||||
branch := branch
|
||||
wg.Add(1)
|
||||
onWorker(func() error {
|
||||
defer wg.Done()
|
||||
baseBranch, err := self.GetBaseBranch(branch, existingMainBranches)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if baseBranch == "" {
|
||||
return nil
|
||||
}
|
||||
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
|
||||
}
|
||||
aheadBehindStr := strings.Split(strings.TrimSpace(output), "\t")
|
||||
if len(aheadBehindStr) != 2 {
|
||||
return errors.New("unexpected output from git rev-list")
|
||||
}
|
||||
if ahead, err := strconv.Atoi(aheadBehindStr[0]); err == nil {
|
||||
if behind, err := strconv.Atoi(aheadBehindStr[1]); err == nil {
|
||||
|
||||
branch.AheadOfBaseBranch.Store(int32(ahead))
|
||||
branch.BehindBaseBranch.Store(int32(behind))
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
}
|
||||
wg.Wait()
|
||||
self.Log.Infof("time to get ahead/behind base branch for all branches: %s", time.Since(t))
|
||||
renderFunc()
|
||||
|
||||
return nil
|
||||
})
|
||||
|
||||
return branches, nil
|
||||
}
|
||||
|
||||
func (self *BranchLoader) GetBaseBranch(branch *models.Branch, existingMainBranches *ExistingMainBranches) (string, error) {
|
||||
mainBranches := existingMainBranches.Get()
|
||||
if len(mainBranches) == 0 {
|
||||
return "", nil
|
||||
}
|
||||
|
||||
output, err := self.cmd.New(
|
||||
NewGitCmd("merge-base").Arg(branch.FullRefName()).Arg(mainBranches...).
|
||||
ToArgv(),
|
||||
).DontLog().RunWithOutput()
|
||||
if err != nil {
|
||||
// If there's an error, it must be because one of the main branches that
|
||||
// used to exist when we called getExistingMainBranches() was deleted
|
||||
// meanwhile. To fix this for next time, throw away our cache.
|
||||
existingMainBranches.Clear()
|
||||
return "", nil
|
||||
}
|
||||
mergeBase := ignoringWarnings(output)
|
||||
|
||||
output, err = self.cmd.New(
|
||||
NewGitCmd("for-each-ref").
|
||||
Arg("--contains").
|
||||
Arg(mergeBase).
|
||||
Arg("--format=%(refname)").
|
||||
Arg(mainBranches...).
|
||||
ToArgv(),
|
||||
).DontLog().RunWithOutput()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
trimmedOutput := strings.TrimSpace(output)
|
||||
split := strings.Split(trimmedOutput, "\n")
|
||||
if len(split) == 0 || split[0] == "" {
|
||||
return "", nil
|
||||
}
|
||||
baseBranch := split[0]
|
||||
return baseBranch, nil
|
||||
}
|
||||
|
||||
func (self *BranchLoader) obtainBranches() []*models.Branch {
|
||||
output, err := self.getRawBranches()
|
||||
if err != nil {
|
||||
|
||||
@@ -35,11 +35,6 @@ type CommitLoader struct {
|
||||
readFile func(filename string) ([]byte, error)
|
||||
walkFiles func(root string, fn filepath.WalkFunc) error
|
||||
dotGitDir string
|
||||
// List of main branches that exist in the repo.
|
||||
// We use these to obtain the merge base of the branch.
|
||||
// When nil, we're yet to obtain the list of existing main branches.
|
||||
// When an empty slice, we've obtained the list and it's empty.
|
||||
mainBranches []string
|
||||
*GitCommon
|
||||
}
|
||||
|
||||
@@ -56,7 +51,6 @@ func NewCommitLoader(
|
||||
getRebaseMode: getRebaseMode,
|
||||
readFile: os.ReadFile,
|
||||
walkFiles: filepath.Walk,
|
||||
mainBranches: nil,
|
||||
GitCommon: gitCommon,
|
||||
}
|
||||
}
|
||||
@@ -72,6 +66,7 @@ type GetCommitsOptions struct {
|
||||
All bool
|
||||
// If non-empty, show divergence from this ref (left-right log)
|
||||
RefToShowDivergenceFrom string
|
||||
ExistingMainBranches *ExistingMainBranches
|
||||
}
|
||||
|
||||
// GetCommits obtains the commits of the current branch
|
||||
@@ -108,9 +103,9 @@ func (self *CommitLoader) GetCommits(opts GetCommitsOptions) ([]*models.Commit,
|
||||
go utils.Safe(func() {
|
||||
defer wg.Done()
|
||||
|
||||
ancestor = self.getMergeBase(opts.RefName)
|
||||
ancestor = self.getMergeBase(opts.RefName, opts.ExistingMainBranches)
|
||||
if opts.RefToShowDivergenceFrom != "" {
|
||||
remoteAncestor = self.getMergeBase(opts.RefToShowDivergenceFrom)
|
||||
remoteAncestor = self.getMergeBase(opts.RefToShowDivergenceFrom, opts.ExistingMainBranches)
|
||||
}
|
||||
})
|
||||
|
||||
@@ -471,12 +466,9 @@ func setCommitMergedStatuses(ancestor string, commits []*models.Commit) {
|
||||
}
|
||||
}
|
||||
|
||||
func (self *CommitLoader) getMergeBase(refName string) string {
|
||||
if self.mainBranches == nil {
|
||||
self.mainBranches = self.getExistingMainBranches()
|
||||
}
|
||||
|
||||
if len(self.mainBranches) == 0 {
|
||||
func (self *CommitLoader) getMergeBase(refName string, existingMainBranches *ExistingMainBranches) string {
|
||||
mainBranches := existingMainBranches.Get()
|
||||
if len(mainBranches) == 0 {
|
||||
return ""
|
||||
}
|
||||
|
||||
@@ -484,69 +476,18 @@ func (self *CommitLoader) getMergeBase(refName string) string {
|
||||
// return the base commit for the closest one.
|
||||
|
||||
output, err := self.cmd.New(
|
||||
NewGitCmd("merge-base").Arg(refName).Arg(self.mainBranches...).
|
||||
NewGitCmd("merge-base").Arg(refName).Arg(mainBranches...).
|
||||
ToArgv(),
|
||||
).DontLog().RunWithOutput()
|
||||
if err != nil {
|
||||
// If there's an error, it must be because one of the main branches that
|
||||
// used to exist when we called getExistingMainBranches() was deleted
|
||||
// meanwhile. To fix this for next time, throw away our cache.
|
||||
self.mainBranches = nil
|
||||
existingMainBranches.Clear()
|
||||
}
|
||||
return ignoringWarnings(output)
|
||||
}
|
||||
|
||||
func (self *CommitLoader) getExistingMainBranches() []string {
|
||||
var existingBranches []string
|
||||
var wg sync.WaitGroup
|
||||
|
||||
mainBranches := self.UserConfig.Git.MainBranches
|
||||
existingBranches = make([]string, len(mainBranches))
|
||||
|
||||
for i, branchName := range mainBranches {
|
||||
wg.Add(1)
|
||||
go utils.Safe(func() {
|
||||
defer wg.Done()
|
||||
|
||||
// Try to determine upstream of local main branch
|
||||
if ref, err := self.cmd.New(
|
||||
NewGitCmd("rev-parse").Arg("--symbolic-full-name", branchName+"@{u}").ToArgv(),
|
||||
).DontLog().RunWithOutput(); err == nil {
|
||||
existingBranches[i] = strings.TrimSpace(ref)
|
||||
return
|
||||
}
|
||||
|
||||
// If this failed, a local branch for this main branch doesn't exist or it
|
||||
// has no upstream configured. Try looking for one in the "origin" remote.
|
||||
ref := "refs/remotes/origin/" + branchName
|
||||
if err := self.cmd.New(
|
||||
NewGitCmd("rev-parse").Arg("--verify", "--quiet", ref).ToArgv(),
|
||||
).DontLog().Run(); err == nil {
|
||||
existingBranches[i] = ref
|
||||
return
|
||||
}
|
||||
|
||||
// If this failed as well, try if we have the main branch as a local
|
||||
// branch. This covers the case where somebody is using git locally
|
||||
// for something, but never pushing anywhere.
|
||||
ref = "refs/heads/" + branchName
|
||||
if err := self.cmd.New(
|
||||
NewGitCmd("rev-parse").Arg("--verify", "--quiet", ref).ToArgv(),
|
||||
).DontLog().Run(); err == nil {
|
||||
existingBranches[i] = ref
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
wg.Wait()
|
||||
|
||||
existingBranches = lo.Filter(existingBranches, func(branch string, _ int) bool {
|
||||
return branch != ""
|
||||
})
|
||||
|
||||
return existingBranches
|
||||
}
|
||||
|
||||
func ignoringWarnings(commandOutput string) string {
|
||||
trimmedOutput := strings.TrimSpace(commandOutput)
|
||||
split := strings.Split(trimmedOutput, "\n")
|
||||
|
||||
@@ -307,10 +307,11 @@ func TestGetCommits(t *testing.T) {
|
||||
common := utils.NewDummyCommon()
|
||||
common.AppState = &config.AppState{}
|
||||
common.AppState.GitLogOrder = scenario.logOrder
|
||||
cmd := oscommands.NewDummyCmdObjBuilder(scenario.runner)
|
||||
|
||||
builder := &CommitLoader{
|
||||
Common: common,
|
||||
cmd: oscommands.NewDummyCmdObjBuilder(scenario.runner),
|
||||
cmd: cmd,
|
||||
getRebaseMode: func() (enums.RebaseMode, error) { return scenario.rebaseMode, nil },
|
||||
dotGitDir: ".git",
|
||||
readFile: func(filename string) ([]byte, error) {
|
||||
@@ -322,7 +323,9 @@ func TestGetCommits(t *testing.T) {
|
||||
}
|
||||
|
||||
common.UserConfig.Git.MainBranches = scenario.mainBranches
|
||||
commits, err := builder.GetCommits(scenario.opts)
|
||||
opts := scenario.opts
|
||||
opts.ExistingMainBranches = NewExistingMainBranches(scenario.mainBranches, cmd)
|
||||
commits, err := builder.GetCommits(opts)
|
||||
|
||||
assert.Equal(t, scenario.expectedCommits, commits)
|
||||
assert.Equal(t, scenario.expectedError, err)
|
||||
|
||||
99
pkg/commands/git_commands/existing_main_branches.go
Normal file
99
pkg/commands/git_commands/existing_main_branches.go
Normal file
@@ -0,0 +1,99 @@
|
||||
package git_commands
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"github.com/jesseduffield/lazygit/pkg/commands/oscommands"
|
||||
"github.com/jesseduffield/lazygit/pkg/utils"
|
||||
"github.com/samber/lo"
|
||||
"github.com/sasha-s/go-deadlock"
|
||||
)
|
||||
|
||||
type ExistingMainBranches struct {
|
||||
configuredMainBranches []string
|
||||
existingBranches []string
|
||||
|
||||
cmd oscommands.ICmdObjBuilder
|
||||
mutex *deadlock.Mutex
|
||||
}
|
||||
|
||||
func NewExistingMainBranches(
|
||||
configuredMainBranches []string,
|
||||
cmd oscommands.ICmdObjBuilder,
|
||||
) *ExistingMainBranches {
|
||||
return &ExistingMainBranches{
|
||||
configuredMainBranches: configuredMainBranches,
|
||||
existingBranches: nil,
|
||||
cmd: cmd,
|
||||
mutex: &deadlock.Mutex{},
|
||||
}
|
||||
}
|
||||
|
||||
func (self *ExistingMainBranches) Get() []string {
|
||||
self.mutex.Lock()
|
||||
defer self.mutex.Unlock()
|
||||
|
||||
if self.existingBranches == nil {
|
||||
self.existingBranches = self.determineMainBranches()
|
||||
}
|
||||
|
||||
return self.existingBranches
|
||||
}
|
||||
|
||||
func (self *ExistingMainBranches) Clear() {
|
||||
self.mutex.Lock()
|
||||
defer self.mutex.Unlock()
|
||||
|
||||
self.existingBranches = nil
|
||||
}
|
||||
|
||||
func (self *ExistingMainBranches) determineMainBranches() []string {
|
||||
var existingBranches []string
|
||||
var wg sync.WaitGroup
|
||||
|
||||
existingBranches = make([]string, len(self.configuredMainBranches))
|
||||
|
||||
for i, branchName := range self.configuredMainBranches {
|
||||
wg.Add(1)
|
||||
go utils.Safe(func() {
|
||||
defer wg.Done()
|
||||
|
||||
// Try to determine upstream of local main branch
|
||||
if ref, err := self.cmd.New(
|
||||
NewGitCmd("rev-parse").Arg("--symbolic-full-name", branchName+"@{u}").ToArgv(),
|
||||
).DontLog().RunWithOutput(); err == nil {
|
||||
existingBranches[i] = strings.TrimSpace(ref)
|
||||
return
|
||||
}
|
||||
|
||||
// If this failed, a local branch for this main branch doesn't exist or it
|
||||
// has no upstream configured. Try looking for one in the "origin" remote.
|
||||
ref := "refs/remotes/origin/" + branchName
|
||||
if err := self.cmd.New(
|
||||
NewGitCmd("rev-parse").Arg("--verify", "--quiet", ref).ToArgv(),
|
||||
).DontLog().Run(); err == nil {
|
||||
existingBranches[i] = ref
|
||||
return
|
||||
}
|
||||
|
||||
// If this failed as well, try if we have the main branch as a local
|
||||
// branch. This covers the case where somebody is using git locally
|
||||
// for something, but never pushing anywhere.
|
||||
ref = "refs/heads/" + branchName
|
||||
if err := self.cmd.New(
|
||||
NewGitCmd("rev-parse").Arg("--verify", "--quiet", ref).ToArgv(),
|
||||
).DontLog().Run(); err == nil {
|
||||
existingBranches[i] = ref
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
wg.Wait()
|
||||
|
||||
existingBranches = lo.Filter(existingBranches, func(branch string, _ int) bool {
|
||||
return branch != ""
|
||||
})
|
||||
|
||||
return existingBranches
|
||||
}
|
||||
@@ -1,6 +1,9 @@
|
||||
package models
|
||||
|
||||
import "fmt"
|
||||
import (
|
||||
"fmt"
|
||||
"sync/atomic"
|
||||
)
|
||||
|
||||
// Branch : A git branch
|
||||
// duplicating this for now
|
||||
@@ -28,6 +31,17 @@ 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
|
||||
|
||||
// How far our branch is ahead of its base branch. 0 means either not
|
||||
// determined yet, or there are no commits on this branch yet, or the branch
|
||||
// is already merged. (We don't need to distinguish these, as we don't draw
|
||||
// anything in all these cases.)
|
||||
AheadOfBaseBranch atomic.Int32
|
||||
}
|
||||
|
||||
func (b *Branch) FullRefName() string {
|
||||
|
||||
@@ -127,6 +127,8 @@ 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.
|
||||
ShowDivergenceFromBaseBranch string `yaml:"showDivergenceFromBaseBranch" jsonschema:"enum=off,enum=onlyBehindArrow,enum=onlyBehindArrowAndNumber,enum=behindAndAheadArrows,enum=behindAndAheadArrowsAndNumbers"`
|
||||
// Height of the command log view
|
||||
CommandLogSize int `yaml:"commandLogSize" jsonschema:"minimum=0"`
|
||||
// Whether to split the main window when viewing file changes.
|
||||
@@ -668,26 +670,27 @@ 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,
|
||||
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: "onlyBehindArrowAndNumber",
|
||||
CommandLogSize: 8,
|
||||
SplitDiff: "auto",
|
||||
SkipRewordInEditorWarning: false,
|
||||
Border: "rounded",
|
||||
AnimateExplosion: true,
|
||||
PortraitMode: "auto",
|
||||
FilterMode: "substring",
|
||||
Spinner: SpinnerConfig{
|
||||
Frames: []string{"|", "/", "-", "\\"},
|
||||
Rate: 50,
|
||||
|
||||
@@ -100,14 +100,13 @@ func (self *BranchesController) GetKeybindings(opts types.KeybindingsOpts) []*ty
|
||||
DisplayOnScreen: true,
|
||||
},
|
||||
{
|
||||
Key: opts.GetKey(opts.Config.Branches.RebaseBranch),
|
||||
Handler: opts.Guards.OutsideFilterMode(self.rebase),
|
||||
GetDisabledReason: self.require(
|
||||
self.singleItemSelected(self.notRebasingOntoSelf),
|
||||
),
|
||||
Description: self.c.Tr.RebaseBranch,
|
||||
Tooltip: self.c.Tr.RebaseBranchTooltip,
|
||||
DisplayOnScreen: true,
|
||||
Key: opts.GetKey(opts.Config.Branches.RebaseBranch),
|
||||
Handler: opts.Guards.OutsideFilterMode(self.withItem(self.rebase)),
|
||||
GetDisabledReason: self.require(self.singleItemSelected()),
|
||||
Description: self.c.Tr.RebaseBranch,
|
||||
Tooltip: self.c.Tr.RebaseBranchTooltip,
|
||||
OpensMenu: true,
|
||||
DisplayOnScreen: true,
|
||||
},
|
||||
{
|
||||
Key: opts.GetKey(opts.Config.Branches.MergeIntoCurrentBranch),
|
||||
@@ -205,6 +204,40 @@ func (self *BranchesController) viewUpstreamOptions(selectedBranch *models.Branc
|
||||
},
|
||||
}
|
||||
|
||||
var disabledReason *types.DisabledReason
|
||||
baseBranch, err := self.c.Git().Loaders.BranchLoader.GetBaseBranch(selectedBranch, self.c.Model().ExistingMainBranches)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if baseBranch == "" {
|
||||
baseBranch = self.c.Tr.BaseBranch
|
||||
disabledReason = &types.DisabledReason{Text: self.c.Tr.NoMainBranches}
|
||||
}
|
||||
shortBaseBranchName := strings.TrimPrefix(baseBranch, "refs/remotes/")
|
||||
label := utils.ResolvePlaceholderString(
|
||||
self.c.Tr.ViewDivergenceFromBaseBranch,
|
||||
map[string]string{"baseBranch": shortBaseBranchName},
|
||||
)
|
||||
viewDivergenceFromBaseBranchItem := &types.MenuItem{
|
||||
LabelColumns: []string{label},
|
||||
Key: 'b',
|
||||
OnPress: func() error {
|
||||
branch := self.context().GetSelected()
|
||||
if branch == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
return self.c.Helpers().SubCommits.ViewSubCommits(helpers.ViewSubCommitsOpts{
|
||||
Ref: branch,
|
||||
TitleRef: fmt.Sprintf("%s <-> %s", branch.RefName(), shortBaseBranchName),
|
||||
RefToShowDivergenceFrom: baseBranch,
|
||||
Context: self.context(),
|
||||
ShowBranchHeads: false,
|
||||
})
|
||||
},
|
||||
DisabledReason: disabledReason,
|
||||
}
|
||||
|
||||
unsetUpstreamItem := &types.MenuItem{
|
||||
LabelColumns: []string{self.c.Tr.UnsetUpstream},
|
||||
OnPress: func() error {
|
||||
@@ -312,6 +345,7 @@ func (self *BranchesController) viewUpstreamOptions(selectedBranch *models.Branc
|
||||
|
||||
options := []*types.MenuItem{
|
||||
viewDivergenceItem,
|
||||
viewDivergenceFromBaseBranchItem,
|
||||
unsetUpstreamItem,
|
||||
setUpstreamItem,
|
||||
upstreamResetItem,
|
||||
@@ -598,19 +632,8 @@ func (self *BranchesController) merge() error {
|
||||
return self.c.Helpers().MergeAndRebase.MergeRefIntoCheckedOutBranch(selectedBranchName)
|
||||
}
|
||||
|
||||
func (self *BranchesController) rebase() error {
|
||||
selectedBranchName := self.context().GetSelected().Name
|
||||
return self.c.Helpers().MergeAndRebase.RebaseOntoRef(selectedBranchName)
|
||||
}
|
||||
|
||||
func (self *BranchesController) notRebasingOntoSelf(branch *models.Branch) *types.DisabledReason {
|
||||
selectedBranchName := branch.Name
|
||||
checkedOutBranch := self.c.Helpers().Refs.GetCheckedOutRef().Name
|
||||
if selectedBranchName == checkedOutBranch {
|
||||
return &types.DisabledReason{Text: self.c.Tr.CantRebaseOntoSelf}
|
||||
}
|
||||
|
||||
return nil
|
||||
func (self *BranchesController) rebase(branch *models.Branch) error {
|
||||
return self.c.Helpers().MergeAndRebase.RebaseOntoRef(branch.Name)
|
||||
}
|
||||
|
||||
func (self *BranchesController) fastForward(branch *models.Branch) error {
|
||||
|
||||
@@ -234,11 +234,29 @@ func (self *MergeAndRebaseHelper) PromptToContinueRebase() error {
|
||||
}
|
||||
|
||||
func (self *MergeAndRebaseHelper) RebaseOntoRef(ref string) error {
|
||||
checkedOutBranch := self.refsHelper.GetCheckedOutRef().Name
|
||||
checkedOutBranch := self.refsHelper.GetCheckedOutRef()
|
||||
checkedOutBranchName := self.refsHelper.GetCheckedOutRef().Name
|
||||
var disabledReason, baseBranchDisabledReason *types.DisabledReason
|
||||
if checkedOutBranchName == ref {
|
||||
disabledReason = &types.DisabledReason{Text: self.c.Tr.CantRebaseOntoSelf}
|
||||
}
|
||||
|
||||
baseBranch, err := self.c.Git().Loaders.BranchLoader.GetBaseBranch(checkedOutBranch, self.refsHelper.c.Model().ExistingMainBranches)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if baseBranch == "" {
|
||||
baseBranch = self.c.Tr.CouldNotDetermineBaseBranch
|
||||
baseBranchDisabledReason = &types.DisabledReason{Text: self.c.Tr.CouldNotDetermineBaseBranch}
|
||||
}
|
||||
|
||||
menuItems := []*types.MenuItem{
|
||||
{
|
||||
Label: self.c.Tr.SimpleRebase,
|
||||
Key: 's',
|
||||
Label: utils.ResolvePlaceholderString(self.c.Tr.SimpleRebase,
|
||||
map[string]string{"ref": ref},
|
||||
),
|
||||
Key: 's',
|
||||
DisabledReason: disabledReason,
|
||||
OnPress: func() error {
|
||||
self.c.LogAction(self.c.Tr.Actions.RebaseBranch)
|
||||
return self.c.WithWaitingStatus(self.c.Tr.RebasingStatus, func(task gocui.Task) error {
|
||||
@@ -258,9 +276,12 @@ func (self *MergeAndRebaseHelper) RebaseOntoRef(ref string) error {
|
||||
},
|
||||
},
|
||||
{
|
||||
Label: self.c.Tr.InteractiveRebase,
|
||||
Key: 'i',
|
||||
Tooltip: self.c.Tr.InteractiveRebaseTooltip,
|
||||
Label: utils.ResolvePlaceholderString(self.c.Tr.InteractiveRebase,
|
||||
map[string]string{"ref": ref},
|
||||
),
|
||||
Key: 'i',
|
||||
DisabledReason: disabledReason,
|
||||
Tooltip: self.c.Tr.InteractiveRebaseTooltip,
|
||||
OnPress: func() error {
|
||||
self.c.LogAction(self.c.Tr.Actions.RebaseBranch)
|
||||
baseCommit := self.c.Modes().MarkedBaseCommit.GetHash()
|
||||
@@ -279,6 +300,31 @@ func (self *MergeAndRebaseHelper) RebaseOntoRef(ref string) error {
|
||||
return self.c.PushContext(self.c.Contexts().LocalCommits)
|
||||
},
|
||||
},
|
||||
{
|
||||
Label: utils.ResolvePlaceholderString(self.c.Tr.RebaseOntoBaseBranch,
|
||||
map[string]string{"baseBranch": strings.TrimPrefix(baseBranch, "refs/remotes/")},
|
||||
),
|
||||
Key: 'b',
|
||||
DisabledReason: baseBranchDisabledReason,
|
||||
Tooltip: self.c.Tr.RebaseOntoBaseBranchTooltip,
|
||||
OnPress: func() error {
|
||||
self.c.LogAction(self.c.Tr.Actions.RebaseBranch)
|
||||
return self.c.WithWaitingStatus(self.c.Tr.RebasingStatus, func(task gocui.Task) error {
|
||||
baseCommit := self.c.Modes().MarkedBaseCommit.GetHash()
|
||||
var err error
|
||||
if baseCommit != "" {
|
||||
err = self.c.Git().Rebase.RebaseBranchFromBaseCommit(baseBranch, baseCommit)
|
||||
} else {
|
||||
err = self.c.Git().Rebase.RebaseBranch(baseBranch)
|
||||
}
|
||||
err = self.CheckMergeOrRebase(err)
|
||||
if err == nil {
|
||||
return self.ResetMarkedBaseCommit()
|
||||
}
|
||||
return err
|
||||
})
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
title := utils.ResolvePlaceholderString(
|
||||
@@ -286,8 +332,7 @@ func (self *MergeAndRebaseHelper) RebaseOntoRef(ref string) error {
|
||||
self.c.Tr.RebasingFromBaseCommitTitle,
|
||||
self.c.Tr.RebasingTitle),
|
||||
map[string]string{
|
||||
"checkedOutBranch": checkedOutBranch,
|
||||
"ref": ref,
|
||||
"checkedOutBranch": checkedOutBranchName,
|
||||
},
|
||||
)
|
||||
|
||||
|
||||
@@ -326,6 +326,7 @@ func (self *RefreshHelper) refreshCommitsWithLimit() error {
|
||||
RefName: self.refForLog(),
|
||||
RefForPushedStatus: checkedOutBranchName,
|
||||
All: self.c.Contexts().LocalCommits.GetShowWholeGitGraph(),
|
||||
ExistingMainBranches: self.c.Model().ExistingMainBranches,
|
||||
},
|
||||
)
|
||||
if err != nil {
|
||||
@@ -352,6 +353,7 @@ func (self *RefreshHelper) refreshSubCommitsWithLimit() error {
|
||||
RefName: self.c.Contexts().SubCommits.GetRef().FullRefName(),
|
||||
RefToShowDivergenceFrom: self.c.Contexts().SubCommits.GetRefToShowDivergenceFrom(),
|
||||
RefForPushedStatus: self.c.Contexts().SubCommits.GetRef().FullRefName(),
|
||||
ExistingMainBranches: self.c.Model().ExistingMainBranches,
|
||||
},
|
||||
)
|
||||
if err != nil {
|
||||
@@ -450,7 +452,20 @@ 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().ExistingMainBranches, self.c.Model().Branches,
|
||||
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)
|
||||
}
|
||||
return nil
|
||||
})
|
||||
})
|
||||
if err != nil {
|
||||
self.c.Log.Error(err)
|
||||
}
|
||||
|
||||
@@ -44,6 +44,7 @@ func (self *SubCommitsHelper) ViewSubCommits(opts ViewSubCommitsOpts) error {
|
||||
RefName: opts.Ref.FullRefName(),
|
||||
RefForPushedStatus: opts.Ref.FullRefName(),
|
||||
RefToShowDivergenceFrom: opts.RefToShowDivergenceFrom,
|
||||
ExistingMainBranches: self.c.Model().ExistingMainBranches,
|
||||
},
|
||||
)
|
||||
if err != nil {
|
||||
|
||||
@@ -12,6 +12,7 @@ import (
|
||||
"github.com/jesseduffield/lazygit/pkg/gui/presentation"
|
||||
"github.com/jesseduffield/lazygit/pkg/gui/style"
|
||||
"github.com/jesseduffield/lazygit/pkg/gui/types"
|
||||
"github.com/jesseduffield/lazygit/pkg/utils"
|
||||
"github.com/samber/lo"
|
||||
)
|
||||
|
||||
@@ -116,7 +117,7 @@ func (self *StatusController) onClick(opts gocui.ViewMouseBindingOpts) error {
|
||||
return err
|
||||
}
|
||||
|
||||
upstreamStatus := presentation.BranchStatus(currentBranch, types.ItemOperationNone, self.c.Tr, time.Now(), self.c.UserConfig)
|
||||
upstreamStatus := utils.Decolorise(presentation.BranchStatus(currentBranch, types.ItemOperationNone, self.c.Tr, time.Now(), self.c.UserConfig))
|
||||
repoName := self.c.Git().RepoPaths.RepoName()
|
||||
workingTreeState := self.c.Git().Status.WorkingTreeState()
|
||||
switch workingTreeState {
|
||||
|
||||
@@ -386,6 +386,7 @@ func (gui *Gui) resetState(startArgs appTypes.StartArgs) types.Context {
|
||||
BisectInfo: git_commands.NewNullBisectInfo(),
|
||||
FilesTrie: patricia.NewTrie(),
|
||||
Authors: map[string]*models.Author{},
|
||||
ExistingMainBranches: git_commands.NewExistingMainBranches(gui.UserConfig.Git.MainBranches, gui.os.Cmd),
|
||||
},
|
||||
Modes: &types.Modes{
|
||||
Filtering: filtering.New(startArgs.FilterPath, ""),
|
||||
|
||||
@@ -56,7 +56,7 @@ func getBranchDisplayStrings(
|
||||
// Recency is always three characters, plus one for the space
|
||||
availableWidth := viewWidth - 4
|
||||
if len(branchStatus) > 0 {
|
||||
availableWidth -= runewidth.StringWidth(branchStatus) + 1
|
||||
availableWidth -= runewidth.StringWidth(utils.Decolorise(branchStatus)) + 1
|
||||
}
|
||||
if icons.IsIconEnabled() {
|
||||
availableWidth -= 2 // one for the icon, one for the space
|
||||
@@ -89,8 +89,7 @@ func getBranchDisplayStrings(
|
||||
coloredName = fmt.Sprintf("%s %s", coloredName, style.FgDefault.Sprint(worktreeIcon))
|
||||
}
|
||||
if len(branchStatus) > 0 {
|
||||
coloredStatus := branchStatusColor(b, itemOperation).Sprint(branchStatus)
|
||||
coloredName = fmt.Sprintf("%s %s", coloredName, coloredStatus)
|
||||
coloredName = fmt.Sprintf("%s %s", coloredName, branchStatus)
|
||||
}
|
||||
|
||||
recencyColor := style.FgCyan
|
||||
@@ -144,30 +143,6 @@ func GetBranchTextStyle(name string) style.TextStyle {
|
||||
}
|
||||
}
|
||||
|
||||
func branchStatusColor(branch *models.Branch, itemOperation types.ItemOperation) style.TextStyle {
|
||||
colour := style.FgYellow
|
||||
if itemOperation != types.ItemOperationNone {
|
||||
colour = style.FgCyan
|
||||
} else if branch.UpstreamGone {
|
||||
colour = style.FgRed
|
||||
} else if branch.MatchesUpstream() {
|
||||
colour = style.FgGreen
|
||||
} else if branch.RemoteBranchNotStoredLocally() {
|
||||
colour = style.FgMagenta
|
||||
}
|
||||
|
||||
return colour
|
||||
}
|
||||
|
||||
func ColoredBranchStatus(
|
||||
branch *models.Branch,
|
||||
itemOperation types.ItemOperation,
|
||||
tr *i18n.TranslationSet,
|
||||
userConfig *config.UserConfig,
|
||||
) string {
|
||||
return branchStatusColor(branch, itemOperation).Sprint(BranchStatus(branch, itemOperation, tr, time.Now(), userConfig))
|
||||
}
|
||||
|
||||
func BranchStatus(
|
||||
branch *models.Branch,
|
||||
itemOperation types.ItemOperation,
|
||||
@@ -177,30 +152,70 @@ func BranchStatus(
|
||||
) string {
|
||||
itemOperationStr := ItemOperationToString(itemOperation, tr)
|
||||
if itemOperationStr != "" {
|
||||
return itemOperationStr + " " + utils.Loader(now, userConfig.Gui.Spinner)
|
||||
}
|
||||
|
||||
if !branch.IsTrackingRemote() {
|
||||
return ""
|
||||
}
|
||||
|
||||
if branch.UpstreamGone {
|
||||
return tr.UpstreamGone
|
||||
}
|
||||
|
||||
if branch.MatchesUpstream() {
|
||||
return "✓"
|
||||
}
|
||||
if branch.RemoteBranchNotStoredLocally() {
|
||||
return "?"
|
||||
return style.FgCyan.Sprintf("%s %s", itemOperationStr, utils.Loader(now, userConfig.Gui.Spinner))
|
||||
}
|
||||
|
||||
result := ""
|
||||
if branch.HasCommitsToPush() {
|
||||
result = fmt.Sprintf("↑%s", branch.Pushables)
|
||||
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.HasCommitsToPull() && branch.HasCommitsToPush() {
|
||||
result = style.FgYellow.Sprintf("↓%s↑%s", branch.Pullables, branch.Pushables)
|
||||
} else if branch.HasCommitsToPull() {
|
||||
result = style.FgYellow.Sprintf("↓%s", branch.Pullables)
|
||||
} else if branch.HasCommitsToPush() {
|
||||
result = style.FgYellow.Sprintf("↑%s", branch.Pushables)
|
||||
}
|
||||
}
|
||||
if branch.HasCommitsToPull() {
|
||||
result = fmt.Sprintf("%s↓%s", result, branch.Pullables)
|
||||
|
||||
if userConfig.Gui.ShowDivergenceFromBaseBranch != "off" {
|
||||
showNumbers := userConfig.Gui.ShowDivergenceFromBaseBranch == "onlyBehindArrowAndNumber" ||
|
||||
userConfig.Gui.ShowDivergenceFromBaseBranch == "behindAndAheadArrowsAndNumbers"
|
||||
|
||||
behind := branch.BehindBaseBranch.Load()
|
||||
if userConfig.Gui.ShowDivergenceFromBaseBranch == "onlyBehindArrow" ||
|
||||
userConfig.Gui.ShowDivergenceFromBaseBranch == "onlyBehindArrowAndNumber" {
|
||||
if behind != 0 {
|
||||
if result != "" {
|
||||
result += " "
|
||||
}
|
||||
if showNumbers {
|
||||
result += style.FgCyan.Sprintf("↓%d", behind)
|
||||
} else {
|
||||
result += style.FgCyan.Sprintf("↓")
|
||||
}
|
||||
}
|
||||
} else {
|
||||
ahead := branch.AheadOfBaseBranch.Load()
|
||||
if ahead != 0 || behind != 0 {
|
||||
if result != "" {
|
||||
result += " "
|
||||
}
|
||||
if ahead != 0 && behind != 0 {
|
||||
if showNumbers {
|
||||
result += style.FgCyan.Sprintf("↓%d↑%d", behind, ahead)
|
||||
} else {
|
||||
result += style.FgCyan.Sprint("↕")
|
||||
}
|
||||
} else if behind != 0 {
|
||||
if showNumbers {
|
||||
result += style.FgCyan.Sprintf("↓%d", behind)
|
||||
} else {
|
||||
result += style.FgCyan.Sprint("↓")
|
||||
}
|
||||
} else {
|
||||
if showNumbers {
|
||||
result += style.FgCyan.Sprintf("↑%d", ahead)
|
||||
} else {
|
||||
result += style.FgCyan.Sprint("↑")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result
|
||||
|
||||
@@ -81,7 +81,7 @@ func Test_getBranchDisplayStrings(t *testing.T) {
|
||||
viewWidth: 100,
|
||||
useIcons: false,
|
||||
checkedOutByWorktree: true,
|
||||
expected: []string{"1m", "branch_name (worktree) ↑3↓5"},
|
||||
expected: []string{"1m", "branch_name (worktree) ↓5↑3"},
|
||||
},
|
||||
{
|
||||
branch: &models.Branch{Name: "branch_name", Recency: "1m"},
|
||||
@@ -167,7 +167,7 @@ func Test_getBranchDisplayStrings(t *testing.T) {
|
||||
viewWidth: 30,
|
||||
useIcons: false,
|
||||
checkedOutByWorktree: true,
|
||||
expected: []string{"1m", "branch_na… (worktree) ↑3↓5"},
|
||||
expected: []string{"1m", "branch_na… (worktree) ↓5↑3"},
|
||||
},
|
||||
{
|
||||
branch: &models.Branch{Name: "branch_name", Recency: "1m"},
|
||||
|
||||
@@ -2,6 +2,7 @@ package presentation
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/jesseduffield/lazygit/pkg/commands/models"
|
||||
"github.com/jesseduffield/lazygit/pkg/commands/types/enums"
|
||||
@@ -24,7 +25,10 @@ func FormatStatus(
|
||||
status := ""
|
||||
|
||||
if currentBranch.IsRealBranch() {
|
||||
status += ColoredBranchStatus(currentBranch, itemOperation, tr, userConfig) + " "
|
||||
status += BranchStatus(currentBranch, itemOperation, tr, time.Now(), userConfig)
|
||||
if status != "" {
|
||||
status += " "
|
||||
}
|
||||
}
|
||||
|
||||
if workingTreeState != enums.REBASE_MODE_NONE {
|
||||
@@ -40,7 +44,7 @@ func FormatStatus(
|
||||
}
|
||||
repoName = fmt.Sprintf("%s(%s%s)", repoName, icon, style.FgCyan.Sprint(linkedWorktreeName))
|
||||
}
|
||||
status += fmt.Sprintf("%s → %s ", repoName, name)
|
||||
status += fmt.Sprintf("%s → %s", repoName, name)
|
||||
|
||||
return status
|
||||
}
|
||||
|
||||
@@ -281,6 +281,8 @@ type Model struct {
|
||||
// we're on a detached head because we're rebasing or bisecting.
|
||||
CheckedOutBranch string
|
||||
|
||||
ExistingMainBranches *git_commands.ExistingMainBranches
|
||||
|
||||
// for displaying suggestions while typing in a file name
|
||||
FilesTrie *patricia.Trie
|
||||
|
||||
|
||||
@@ -289,7 +289,9 @@ type TranslationSet struct {
|
||||
RebasingFromBaseCommitTitle string
|
||||
SimpleRebase string
|
||||
InteractiveRebase string
|
||||
RebaseOntoBaseBranch string
|
||||
InteractiveRebaseTooltip string
|
||||
RebaseOntoBaseBranchTooltip string
|
||||
MustSelectTodoCommits string
|
||||
ConfirmMerge string
|
||||
FwdNoUpstream string
|
||||
@@ -468,6 +470,10 @@ type TranslationSet struct {
|
||||
SetUpstream string
|
||||
UnsetUpstream string
|
||||
ViewDivergenceFromUpstream string
|
||||
ViewDivergenceFromBaseBranch string
|
||||
NoMainBranches string
|
||||
BaseBranch string
|
||||
CouldNotDetermineBaseBranch string
|
||||
DivergenceSectionHeaderLocal string
|
||||
DivergenceSectionHeaderRemote string
|
||||
ViewUpstreamResetOptions string
|
||||
@@ -1251,11 +1257,13 @@ func EnglishTranslationSet() TranslationSet {
|
||||
KeybindingsMenuSectionLocal: "Local",
|
||||
KeybindingsMenuSectionGlobal: "Global",
|
||||
KeybindingsMenuSectionNavigation: "Navigation",
|
||||
RebasingTitle: "Rebase '{{.checkedOutBranch}}' onto '{{.ref}}'",
|
||||
RebasingFromBaseCommitTitle: "Rebase '{{.checkedOutBranch}}' from marked base onto '{{.ref}}'",
|
||||
SimpleRebase: "Simple rebase",
|
||||
InteractiveRebase: "Interactive rebase",
|
||||
RebasingTitle: "Rebase '{{.checkedOutBranch}}'",
|
||||
RebasingFromBaseCommitTitle: "Rebase '{{.checkedOutBranch}}' from marked base",
|
||||
SimpleRebase: "Simple rebase onto '{{.ref}}'",
|
||||
InteractiveRebase: "Interactive rebase onto '{{.ref}}'",
|
||||
RebaseOntoBaseBranch: "Rebase onto base branch ({{.baseBranch}})",
|
||||
InteractiveRebaseTooltip: "Begin an interactive rebase with a break at the start, so you can update the TODO commits before continuing.",
|
||||
RebaseOntoBaseBranchTooltip: "Rebase the checked out branch onto its base branch (i.e. the closest main branch).",
|
||||
MustSelectTodoCommits: "When rebasing, this action only works on a selection of TODO commits.",
|
||||
ConfirmMerge: "Are you sure you want to merge '{{.selectedBranch}}' into '{{.checkedOutBranch}}'?",
|
||||
FwdNoUpstream: "Cannot fast-forward a branch with no upstream",
|
||||
@@ -1434,12 +1442,16 @@ func EnglishTranslationSet() TranslationSet {
|
||||
SetUpstream: "Set upstream of selected branch",
|
||||
UnsetUpstream: "Unset upstream of selected branch",
|
||||
ViewDivergenceFromUpstream: "View divergence from upstream",
|
||||
ViewDivergenceFromBaseBranch: "View divergence from base branch ({{.baseBranch}})",
|
||||
NoMainBranches: "There are no main branches",
|
||||
BaseBranch: "base branch",
|
||||
CouldNotDetermineBaseBranch: "couldn't determine base branch",
|
||||
DivergenceSectionHeaderLocal: "Local",
|
||||
DivergenceSectionHeaderRemote: "Remote",
|
||||
ViewUpstreamResetOptions: "Reset checked-out branch onto {{.upstream}}",
|
||||
ViewUpstreamResetOptionsTooltip: "View options for resetting the checked-out branch onto {{upstream}}. Note: this will not reset the selected branch onto the upstream, it will reset the checked-out branch onto the upstream.",
|
||||
ViewUpstreamRebaseOptions: "Rebase checked-out branch onto {{.upstream}}",
|
||||
ViewUpstreamRebaseOptionsTooltip: "View options for rebasing the checked-out branch onto {{upstream}}. Note: this will not rebase the selected branch onto the upstream, it will rebased the checked-out branch onto the upstream.",
|
||||
ViewUpstreamRebaseOptionsTooltip: "View options for rebasing the checked-out branch onto {{upstream}}. Note: this will not rebase the selected branch onto the upstream, it will rebase the checked-out branch onto the upstream.",
|
||||
UpstreamGenericName: "upstream of selected branch",
|
||||
SetUpstreamTitle: "Set upstream branch",
|
||||
SetUpstreamMessage: "Are you sure you want to set the upstream branch of '{{.checkedOut}}' to '{{.selected}}'",
|
||||
|
||||
@@ -274,10 +274,10 @@ func polishTranslationSet() TranslationSet {
|
||||
KeybindingsMenuSectionLocal: "Lokalne",
|
||||
KeybindingsMenuSectionGlobal: "Globalne",
|
||||
KeybindingsMenuSectionNavigation: "Nawigacja",
|
||||
RebasingTitle: "Rebase '{{.checkedOutBranch}}' na '{{.ref}}'",
|
||||
RebasingFromBaseCommitTitle: "Rebase '{{.checkedOutBranch}}' od oznaczonego commita bazowego na '{{.ref}}'",
|
||||
SimpleRebase: "Prosty rebase",
|
||||
InteractiveRebase: "Interaktywny rebase",
|
||||
RebasingTitle: "Rebase '{{.checkedOutBranch}}'",
|
||||
RebasingFromBaseCommitTitle: "Rebase '{{.checkedOutBranch}}' od oznaczonego commita bazowego",
|
||||
SimpleRebase: "Prosty rebase na '{{.ref}}'",
|
||||
InteractiveRebase: "Interaktywny rebase na '{{.ref}}'",
|
||||
InteractiveRebaseTooltip: "Rozpocznij interaktywny rebase z przerwaniem na początku, abyś mógł zaktualizować commity TODO przed kontynuacją.",
|
||||
MustSelectTodoCommits: "Podczas rebase ta akcja działa tylko na zaznaczonych commitach TODO.",
|
||||
ConfirmMerge: "Czy na pewno chcesz scalić '{{.selectedBranch}}' z '{{.checkedOutBranch}}'?",
|
||||
|
||||
@@ -225,9 +225,9 @@ func RussianTranslationSet() TranslationSet {
|
||||
ConflictsResolved: "Все конфликты слияния разрешены. Продолжить?",
|
||||
Continue: "Продолжить",
|
||||
Keybindings: "Связки клавиш",
|
||||
RebasingTitle: "Перебазировать '{{.checkedOutBranch}}' на '{{.ref}}'",
|
||||
SimpleRebase: "Простая перебазировка",
|
||||
InteractiveRebase: "Интерактивная перебазировка",
|
||||
RebasingTitle: "Перебазировать '{{.checkedOutBranch}}'",
|
||||
SimpleRebase: "Простая перебазировка на '{{.ref}}'",
|
||||
InteractiveRebase: "Интерактивная перебазировка на '{{.ref}}'",
|
||||
InteractiveRebaseTooltip: "Начать интерактивную перебазировку с перерыва в начале, чтобы можно было обновить TODO коммиты, прежде чем продолжить.",
|
||||
ConfirmMerge: "Вы уверены, что хотите to merge '{{.selectedBranch}}' into '{{.checkedOutBranch}}'?",
|
||||
FwdNoUpstream: "Невозможно перемотать ветку без upstream-ветки",
|
||||
|
||||
@@ -255,9 +255,9 @@ func traditionalChineseTranslationSet() TranslationSet {
|
||||
ConflictsResolved: "所有合併衝突都已解決。是否繼續?",
|
||||
Continue: "確認",
|
||||
Keybindings: "鍵盤快捷鍵",
|
||||
RebasingTitle: "將 '{{.checkedOutBranch}}' 變基至 '{{.ref}}'",
|
||||
SimpleRebase: "簡單變基",
|
||||
InteractiveRebase: "互動變基",
|
||||
RebasingTitle: "將 '{{.checkedOutBranch}}'",
|
||||
SimpleRebase: "簡單變基 變基至 '{{.ref}}'",
|
||||
InteractiveRebase: "互動變基 變基至 '{{.ref}}'",
|
||||
InteractiveRebaseTooltip: "開始一個互動變基,以中斷開始,這樣你可以在繼續之前更新TODO提交",
|
||||
ConfirmMerge: "是否將 '{{.selectedBranch}}' 合併至 '{{.checkedOutBranch}}' ?",
|
||||
FwdNoUpstream: "無法快進無上游分支",
|
||||
|
||||
@@ -44,7 +44,7 @@ var DeleteRemoteBranchWithCredentialPrompt = NewIntegrationTest(NewIntegrationTe
|
||||
Confirm()
|
||||
}
|
||||
|
||||
t.Views().Status().Content(Contains("✓ repo → mybranch"))
|
||||
t.Views().Status().Content(Equals("✓ repo → mybranch"))
|
||||
|
||||
deleteBranch()
|
||||
|
||||
@@ -66,7 +66,7 @@ var DeleteRemoteBranchWithCredentialPrompt = NewIntegrationTest(NewIntegrationTe
|
||||
Content(Contains("incorrect username/password")).
|
||||
Confirm()
|
||||
|
||||
t.Views().Status().Content(Contains("✓ repo → mybranch"))
|
||||
t.Views().Status().Content(Equals("✓ repo → mybranch"))
|
||||
|
||||
// try again with correct password
|
||||
deleteBranch()
|
||||
@@ -81,7 +81,7 @@ var DeleteRemoteBranchWithCredentialPrompt = NewIntegrationTest(NewIntegrationTe
|
||||
Type("password").
|
||||
Confirm()
|
||||
|
||||
t.Views().Status().Content(Contains("repo → mybranch").DoesNotContain("✓"))
|
||||
t.Views().Status().Content(Equals("(upstream gone) repo → mybranch"))
|
||||
t.Views().Branches().TopLines(Contains("mybranch (upstream gone)"))
|
||||
},
|
||||
})
|
||||
|
||||
@@ -31,7 +31,7 @@ var Rebase = NewIntegrationTest(NewIntegrationTestArgs{
|
||||
Press(keys.Branches.RebaseBranch)
|
||||
|
||||
t.ExpectPopup().Menu().
|
||||
Title(Equals("Rebase 'first-change-branch' onto 'second-change-branch'")).
|
||||
Title(Equals("Rebase 'first-change-branch'")).
|
||||
Select(Contains("Simple rebase")).
|
||||
Confirm()
|
||||
|
||||
|
||||
@@ -31,7 +31,7 @@ var RebaseAbortOnConflict = NewIntegrationTest(NewIntegrationTestArgs{
|
||||
Press(keys.Branches.RebaseBranch)
|
||||
|
||||
t.ExpectPopup().Menu().
|
||||
Title(Equals("Rebase 'first-change-branch' onto 'second-change-branch'")).
|
||||
Title(Equals("Rebase 'first-change-branch'")).
|
||||
Select(Contains("Simple rebase")).
|
||||
Confirm()
|
||||
|
||||
|
||||
@@ -37,7 +37,7 @@ var RebaseAndDrop = NewIntegrationTest(NewIntegrationTestArgs{
|
||||
Press(keys.Branches.RebaseBranch)
|
||||
|
||||
t.ExpectPopup().Menu().
|
||||
Title(Equals("Rebase 'first-change-branch' onto 'second-change-branch'")).
|
||||
Title(Equals("Rebase 'first-change-branch'")).
|
||||
Select(Contains("Simple rebase")).
|
||||
Confirm()
|
||||
|
||||
|
||||
@@ -31,7 +31,7 @@ var RebaseCancelOnConflict = NewIntegrationTest(NewIntegrationTestArgs{
|
||||
Press(keys.Branches.RebaseBranch)
|
||||
|
||||
t.ExpectPopup().Menu().
|
||||
Title(Equals("Rebase 'first-change-branch' onto 'second-change-branch'")).
|
||||
Title(Equals("Rebase 'first-change-branch'")).
|
||||
Select(Contains("Simple rebase")).
|
||||
Confirm()
|
||||
|
||||
|
||||
@@ -42,7 +42,7 @@ var RebaseCopiedBranch = NewIntegrationTest(NewIntegrationTestArgs{
|
||||
Press(keys.Branches.RebaseBranch).
|
||||
Tap(func() {
|
||||
t.ExpectPopup().Menu().
|
||||
Title(Equals("Rebase 'branch2' onto 'master'")).
|
||||
Title(Equals("Rebase 'branch2'")).
|
||||
Select(Contains("Simple rebase")).
|
||||
Confirm()
|
||||
})
|
||||
|
||||
@@ -40,7 +40,7 @@ var RebaseDoesNotAutosquash = NewIntegrationTest(NewIntegrationTestArgs{
|
||||
Press(keys.Branches.RebaseBranch)
|
||||
|
||||
t.ExpectPopup().Menu().
|
||||
Title(Equals("Rebase 'my-branch' onto 'master'")).
|
||||
Title(Equals("Rebase 'my-branch'")).
|
||||
Select(Contains("Simple rebase")).
|
||||
Confirm()
|
||||
|
||||
|
||||
@@ -61,7 +61,7 @@ var RebaseFromMarkedBase = NewIntegrationTest(NewIntegrationTestArgs{
|
||||
Press(keys.Branches.RebaseBranch)
|
||||
|
||||
t.ExpectPopup().Menu().
|
||||
Title(Equals("Rebase 'active-branch' from marked base onto 'target-branch'")).
|
||||
Title(Equals("Rebase 'active-branch' from marked base")).
|
||||
Select(Contains("Simple rebase")).
|
||||
Confirm()
|
||||
|
||||
|
||||
@@ -67,7 +67,7 @@ var RebaseToUpstream = NewIntegrationTest(NewIntegrationTestArgs{
|
||||
Select(Contains("Rebase checked-out branch onto origin/master...")).
|
||||
Confirm()
|
||||
t.ExpectPopup().Menu().
|
||||
Title(Equals("Rebase 'target' onto 'origin/master'")).
|
||||
Title(Equals("Rebase 'target'")).
|
||||
Select(Contains("Simple rebase")).
|
||||
Confirm()
|
||||
})
|
||||
|
||||
@@ -39,7 +39,7 @@ var AdvancedInteractiveRebase = NewIntegrationTest(NewIntegrationTestArgs{
|
||||
Press(keys.Branches.RebaseBranch)
|
||||
|
||||
t.ExpectPopup().Menu().
|
||||
Title(Equals(fmt.Sprintf("Rebase '%s' onto '%s'", TOP_BRANCH, BASE_BRANCH))).
|
||||
Title(Equals(fmt.Sprintf("Rebase '%s'", TOP_BRANCH))).
|
||||
Select(Contains("Interactive rebase")).
|
||||
Confirm()
|
||||
t.Views().Commits().
|
||||
|
||||
@@ -26,7 +26,7 @@ var ForcePush = NewIntegrationTest(NewIntegrationTestArgs{
|
||||
Contains("one"),
|
||||
)
|
||||
|
||||
t.Views().Status().Content(Contains("↓1 repo → master"))
|
||||
t.Views().Status().Content(Equals("↓1 repo → master"))
|
||||
|
||||
t.Views().Files().IsFocused().Press(keys.Universal.Push)
|
||||
|
||||
@@ -40,7 +40,7 @@ var ForcePush = NewIntegrationTest(NewIntegrationTestArgs{
|
||||
Contains("one"),
|
||||
)
|
||||
|
||||
t.Views().Status().Content(Contains("✓ repo → master"))
|
||||
t.Views().Status().Content(Equals("✓ ↓1 repo → master"))
|
||||
|
||||
t.Views().Remotes().Focus().
|
||||
Lines(Contains("origin")).
|
||||
|
||||
@@ -22,7 +22,7 @@ var ForcePushMultipleMatching = NewIntegrationTest(NewIntegrationTestArgs{
|
||||
Contains("one"),
|
||||
)
|
||||
|
||||
t.Views().Status().Content(Contains("↓1 repo → master"))
|
||||
t.Views().Status().Content(Equals("↓1 repo → master"))
|
||||
|
||||
t.Views().Branches().
|
||||
Lines(
|
||||
@@ -42,7 +42,7 @@ var ForcePushMultipleMatching = NewIntegrationTest(NewIntegrationTestArgs{
|
||||
Contains("one"),
|
||||
)
|
||||
|
||||
t.Views().Status().Content(Contains("✓ repo → master"))
|
||||
t.Views().Status().Content(Equals("✓ ↓1 repo → master"))
|
||||
|
||||
t.Views().Branches().
|
||||
Lines(
|
||||
|
||||
@@ -21,7 +21,7 @@ var ForcePushMultipleUpstream = NewIntegrationTest(NewIntegrationTestArgs{
|
||||
Contains("one"),
|
||||
)
|
||||
|
||||
t.Views().Status().Content(Contains("↓1 repo → master"))
|
||||
t.Views().Status().Content(Equals("↓1 repo → master"))
|
||||
|
||||
t.Views().Branches().
|
||||
Lines(
|
||||
@@ -41,7 +41,7 @@ var ForcePushMultipleUpstream = NewIntegrationTest(NewIntegrationTestArgs{
|
||||
Contains("one"),
|
||||
)
|
||||
|
||||
t.Views().Status().Content(Contains("✓ repo → master"))
|
||||
t.Views().Status().Content(Equals("✓ ↓1 repo → master"))
|
||||
|
||||
t.Views().Branches().
|
||||
Lines(
|
||||
|
||||
@@ -26,7 +26,7 @@ var Pull = NewIntegrationTest(NewIntegrationTestArgs{
|
||||
Contains("one"),
|
||||
)
|
||||
|
||||
t.Views().Status().Content(Contains("↓1 repo → master"))
|
||||
t.Views().Status().Content(Equals("↓1 repo → master"))
|
||||
|
||||
t.Views().Files().IsFocused().Press(keys.Universal.Pull)
|
||||
|
||||
@@ -36,6 +36,6 @@ var Pull = NewIntegrationTest(NewIntegrationTestArgs{
|
||||
Contains("one"),
|
||||
)
|
||||
|
||||
t.Views().Status().Content(Contains("✓ repo → master"))
|
||||
t.Views().Status().Content(Equals("✓ ↓1 repo → master"))
|
||||
},
|
||||
})
|
||||
|
||||
@@ -25,7 +25,7 @@ var PullAndSetUpstream = NewIntegrationTest(NewIntegrationTestArgs{
|
||||
Contains("one"),
|
||||
)
|
||||
|
||||
t.Views().Status().Content(Contains("repo → master"))
|
||||
t.Views().Status().Content(Equals("repo → master"))
|
||||
|
||||
t.Views().Files().IsFocused().Press(keys.Universal.Pull)
|
||||
|
||||
@@ -40,6 +40,6 @@ var PullAndSetUpstream = NewIntegrationTest(NewIntegrationTestArgs{
|
||||
Contains("one"),
|
||||
)
|
||||
|
||||
t.Views().Status().Content(Contains("✓ repo → master"))
|
||||
t.Views().Status().Content(Equals("✓ ↓1 repo → master"))
|
||||
},
|
||||
})
|
||||
|
||||
@@ -33,13 +33,13 @@ var PullMerge = NewIntegrationTest(NewIntegrationTestArgs{
|
||||
Contains("one"),
|
||||
)
|
||||
|
||||
t.Views().Status().Content(Contains("↓2 repo → master"))
|
||||
t.Views().Status().Content(Equals("↓2↑1 repo → master"))
|
||||
|
||||
t.Views().Files().
|
||||
IsFocused().
|
||||
Press(keys.Universal.Pull)
|
||||
|
||||
t.Views().Status().Content(Contains("↑2 repo → master"))
|
||||
t.Views().Status().Content(Equals("↑2 ↓2 repo → master"))
|
||||
|
||||
t.Views().Commits().
|
||||
Lines(
|
||||
|
||||
@@ -34,7 +34,7 @@ var PullMergeConflict = NewIntegrationTest(NewIntegrationTestArgs{
|
||||
Contains("one"),
|
||||
)
|
||||
|
||||
t.Views().Status().Content(Contains("↓2 repo → master"))
|
||||
t.Views().Status().Content(Equals("↓2↑1 repo → master"))
|
||||
|
||||
t.Views().Files().
|
||||
IsFocused().
|
||||
@@ -62,7 +62,7 @@ var PullMergeConflict = NewIntegrationTest(NewIntegrationTestArgs{
|
||||
|
||||
t.Common().ContinueOnConflictsResolved()
|
||||
|
||||
t.Views().Status().Content(Contains("↑2 repo → master"))
|
||||
t.Views().Status().Content(Equals("↑2 ↓2 repo → master"))
|
||||
|
||||
t.Views().Commits().
|
||||
Focus().
|
||||
|
||||
@@ -35,13 +35,13 @@ var PullRebase = NewIntegrationTest(NewIntegrationTestArgs{
|
||||
Contains("one"),
|
||||
)
|
||||
|
||||
t.Views().Status().Content(Contains("↓2 repo → master"))
|
||||
t.Views().Status().Content(Equals("↓2↑1 repo → master"))
|
||||
|
||||
t.Views().Files().
|
||||
IsFocused().
|
||||
Press(keys.Universal.Pull)
|
||||
|
||||
t.Views().Status().Content(Contains("↑1 repo → master"))
|
||||
t.Views().Status().Content(Equals("↑1 ↓2 repo → master"))
|
||||
|
||||
t.Views().Commits().
|
||||
Lines(
|
||||
|
||||
@@ -34,7 +34,7 @@ var PullRebaseConflict = NewIntegrationTest(NewIntegrationTestArgs{
|
||||
Contains("one"),
|
||||
)
|
||||
|
||||
t.Views().Status().Content(Contains("↓2 repo → master"))
|
||||
t.Views().Status().Content(Equals("↓2↑1 repo → master"))
|
||||
|
||||
t.Views().Files().
|
||||
IsFocused().
|
||||
@@ -63,7 +63,7 @@ var PullRebaseConflict = NewIntegrationTest(NewIntegrationTestArgs{
|
||||
|
||||
t.Common().ContinueOnConflictsResolved()
|
||||
|
||||
t.Views().Status().Content(Contains("↑1 repo → master"))
|
||||
t.Views().Status().Content(Equals("↑1 ↓2 repo → master"))
|
||||
|
||||
t.Views().Commits().
|
||||
Focus().
|
||||
|
||||
@@ -38,7 +38,7 @@ var PullRebaseInteractiveConflict = NewIntegrationTest(NewIntegrationTestArgs{
|
||||
Contains("one"),
|
||||
)
|
||||
|
||||
t.Views().Status().Content(Contains("↓2 repo → master"))
|
||||
t.Views().Status().Content(Equals("↓2↑2 repo → master"))
|
||||
|
||||
t.Views().Files().
|
||||
IsFocused().
|
||||
@@ -76,7 +76,7 @@ var PullRebaseInteractiveConflict = NewIntegrationTest(NewIntegrationTestArgs{
|
||||
|
||||
t.Common().ContinueOnConflictsResolved()
|
||||
|
||||
t.Views().Status().Content(Contains("↑2 repo → master"))
|
||||
t.Views().Status().Content(Equals("↑2 ↓2 repo → master"))
|
||||
|
||||
t.Views().Commits().
|
||||
Focus().
|
||||
|
||||
@@ -38,7 +38,7 @@ var PullRebaseInteractiveConflictDrop = NewIntegrationTest(NewIntegrationTestArg
|
||||
Contains("one"),
|
||||
)
|
||||
|
||||
t.Views().Status().Content(Contains("↓2 repo → master"))
|
||||
t.Views().Status().Content(Equals("↓2↑2 repo → master"))
|
||||
|
||||
t.Views().Files().
|
||||
IsFocused().
|
||||
@@ -85,7 +85,7 @@ var PullRebaseInteractiveConflictDrop = NewIntegrationTest(NewIntegrationTestArg
|
||||
|
||||
t.Common().ContinueOnConflictsResolved()
|
||||
|
||||
t.Views().Status().Content(Contains("↑1 repo → master"))
|
||||
t.Views().Status().Content(Equals("↑1 ↓2 repo → master"))
|
||||
|
||||
t.Views().Commits().
|
||||
Focus().
|
||||
|
||||
@@ -21,7 +21,7 @@ var Push = NewIntegrationTest(NewIntegrationTestArgs{
|
||||
shell.EmptyCommit("two")
|
||||
},
|
||||
Run: func(t *TestDriver, keys config.KeybindingConfig) {
|
||||
t.Views().Status().Content(Contains("↑1 repo → master"))
|
||||
t.Views().Status().Content(Equals("↑1 repo → master"))
|
||||
|
||||
t.Views().Files().
|
||||
IsFocused().
|
||||
|
||||
@@ -22,7 +22,7 @@ var PushAndAutoSetUpstream = NewIntegrationTest(NewIntegrationTestArgs{
|
||||
},
|
||||
Run: func(t *TestDriver, keys config.KeybindingConfig) {
|
||||
// assert no mention of upstream/downstream changes
|
||||
t.Views().Status().Content(MatchesRegexp(`^\s+repo → master`))
|
||||
t.Views().Status().Content(Equals("repo → master"))
|
||||
|
||||
t.Views().Files().
|
||||
IsFocused().
|
||||
|
||||
@@ -19,7 +19,7 @@ var PushAndSetUpstream = NewIntegrationTest(NewIntegrationTestArgs{
|
||||
},
|
||||
Run: func(t *TestDriver, keys config.KeybindingConfig) {
|
||||
// assert no mention of upstream/downstream changes
|
||||
t.Views().Status().Content(MatchesRegexp(`^\s+repo → master`))
|
||||
t.Views().Status().Content(Equals("repo → master"))
|
||||
|
||||
t.Views().Files().
|
||||
IsFocused().
|
||||
|
||||
@@ -24,13 +24,13 @@ var PushFollowTags = NewIntegrationTest(NewIntegrationTestArgs{
|
||||
shell.SetConfig("push.followTags", "true")
|
||||
},
|
||||
Run: func(t *TestDriver, keys config.KeybindingConfig) {
|
||||
t.Views().Status().Content(Contains("↑1 repo → master"))
|
||||
t.Views().Status().Content(Equals("↑1 repo → master"))
|
||||
|
||||
t.Views().Files().
|
||||
IsFocused().
|
||||
Press(keys.Universal.Push)
|
||||
|
||||
t.Views().Status().Content(Contains("✓ repo → master"))
|
||||
t.Views().Status().Content(Equals("✓ repo → master"))
|
||||
|
||||
t.Views().Remotes().
|
||||
Focus().
|
||||
|
||||
@@ -22,13 +22,13 @@ var PushNoFollowTags = NewIntegrationTest(NewIntegrationTestArgs{
|
||||
shell.CreateAnnotatedTag("mytag", "message", "HEAD")
|
||||
},
|
||||
Run: func(t *TestDriver, keys config.KeybindingConfig) {
|
||||
t.Views().Status().Content(Contains("✓ repo → master"))
|
||||
t.Views().Status().Content(Equals("✓ repo → master"))
|
||||
|
||||
t.Views().Files().
|
||||
IsFocused().
|
||||
Press(keys.Universal.Push)
|
||||
|
||||
t.Views().Status().Content(Contains("✓ repo → master"))
|
||||
t.Views().Status().Content(Equals("✓ repo → master"))
|
||||
|
||||
t.Views().Remotes().
|
||||
Focus().
|
||||
|
||||
@@ -26,7 +26,7 @@ var PushWithCredentialPrompt = NewIntegrationTest(NewIntegrationTestArgs{
|
||||
shell.CopyHelpFile("pre-push", ".git/hooks/pre-push")
|
||||
},
|
||||
Run: func(t *TestDriver, keys config.KeybindingConfig) {
|
||||
t.Views().Status().Content(Contains("↑1 repo → master"))
|
||||
t.Views().Status().Content(Equals("↑1 repo → master"))
|
||||
|
||||
t.Views().Files().
|
||||
IsFocused().
|
||||
@@ -50,7 +50,7 @@ var PushWithCredentialPrompt = NewIntegrationTest(NewIntegrationTestArgs{
|
||||
Content(Contains("incorrect username/password")).
|
||||
Confirm()
|
||||
|
||||
t.Views().Status().Content(Contains("↑1 repo → master"))
|
||||
t.Views().Status().Content(Equals("↑1 repo → master"))
|
||||
|
||||
// try again with correct password
|
||||
t.Views().Files().
|
||||
@@ -67,7 +67,7 @@ var PushWithCredentialPrompt = NewIntegrationTest(NewIntegrationTestArgs{
|
||||
Type("password").
|
||||
Confirm()
|
||||
|
||||
t.Views().Status().Content(Contains("✓ repo → master"))
|
||||
t.Views().Status().Content(Equals("✓ repo → master"))
|
||||
|
||||
assertSuccessfullyPushed(t)
|
||||
},
|
||||
|
||||
@@ -24,7 +24,7 @@ func createTwoBranchesReadyToForcePush(shell *Shell) {
|
||||
}
|
||||
|
||||
func assertSuccessfullyPushed(t *TestDriver) {
|
||||
t.Views().Status().Content(Contains("✓ repo → master"))
|
||||
t.Views().Status().Content(Equals("✓ repo → master"))
|
||||
|
||||
t.Views().Remotes().
|
||||
Focus().
|
||||
|
||||
@@ -319,6 +319,18 @@
|
||||
"type": "boolean",
|
||||
"description": "If true, show commit hashes alongside branch names in the branches view."
|
||||
},
|
||||
"showDivergenceFromBaseBranch": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"off",
|
||||
"onlyBehindArrow",
|
||||
"onlyBehindArrowAndNumber",
|
||||
"behindAndAheadArrows",
|
||||
"behindAndAheadArrowsAndNumbers"
|
||||
],
|
||||
"description": "Whether to show the divergence from the base branch in the branches view.",
|
||||
"default": "onlyBehind"
|
||||
},
|
||||
"commandLogSize": {
|
||||
"type": "integer",
|
||||
"minimum": 0,
|
||||
|
||||
Reference in New Issue
Block a user