Compare commits

...
18 Commits
Author SHA1 Message Date
Jesse Duffield 14c8b80494 show loading state when amending top commit 2020-09-18 07:58:16 +10:00
Lakshay Garg 10dde518bc Fix numbering in Dutch IntroPopupMessage 2020-09-18 07:47:01 +10:00
Lakshay Garg 1e1c90c92e Fix numbering in English IntroPopupMessage 2020-09-18 07:47:01 +10:00
Jesse Duffield 4954791443 fix test 2020-09-18 07:46:12 +10:00
Jesse Duffield c471f4927a fix test 2020-09-02 20:55:53 +10:00
Jesse Duffield 9eba98302e ensure that when a branch name is ambiguous we still show the correct colours 2020-09-02 10:40:50 +00:00
Francisco Miamoto 250fe740b2 use GetBool instead of casting 2020-08-31 09:22:39 +10:00
Francisco Miamoto 70eda031dc implement config option for disabling force pushing 2020-08-31 09:22:39 +10:00
Francisco Miamoto 86f296a898 add config for disabling force pushing 2020-08-31 09:22:39 +10:00
Jesse Duffield 71ff18318d fast UI update when moving commits in rebase mode 2020-08-29 00:19:31 +00:00
Jesse Duffield 46cce28758 restore donate link 2020-08-28 09:52:56 +10:00
Jesse Duffield 5611d9a3ef gracefully fail due to git version less than 2.0 2020-08-27 12:21:37 +00:00
Jesse Duffield 40bec49de8 more efficient refreshing of rebase commits 2020-08-27 21:51:07 +10:00
Jesse Duffield f99d5f74d4 drop merge commits when interactive rebasing just like git CLI 2020-08-27 21:51:07 +10:00
Jesse Duffield 30a066aa41 remove redundant test 2020-08-27 19:29:22 +10:00
Jesse Duffield 1dcc3363d0 support branches with no upstream 2020-08-27 17:05:07 +10:00
Jesse Duffield c6948582e6 better way of knowing which commits are unpushed 2020-08-26 22:45:55 +00:00
Jesse Duffield 196c83d058 fix bug where cancelling search in menu caused issue 2020-08-26 09:32:57 +00:00
18 changed files with 267 additions and 131 deletions
+1
View File
@@ -49,6 +49,7 @@ Default path for the config file:
autoFetch: true
branchLogCmd: "git log --graph --color=always --abbrev-commit --decorate --date=relative --pretty=medium {{branchName}} --"
overrideGpg: false # prevents lazygit from spawning a separate process when using GPG
disableForcePushing: false
update:
method: prompt # can be: prompt | background | never
days: 14 # how often an update is checked for
+36
View File
@@ -2,11 +2,13 @@ package app
import (
"bufio"
"errors"
"fmt"
"io"
"io/ioutil"
"os"
"path/filepath"
"strconv"
"strings"
"github.com/jesseduffield/lazygit/pkg/commands"
@@ -129,7 +131,33 @@ func NewApp(config config.AppConfigurer, filterPath string) (*App, error) {
return app, nil
}
func (app *App) validateGitVersion() error {
output, err := app.OSCommand.RunCommandWithOutput("git --version")
// if we get an error anywhere here we'll show the same status
minVersionError := errors.New(app.Tr.SLocalize("minGitVersionError"))
if err != nil {
return minVersionError
}
// output should be something like: 'git version 2.23.0'
// first number in the string should be greater than 0
split := strings.Split(output, " ")
gitVersion := split[len(split)-1]
majorVersion, err := strconv.Atoi(gitVersion[0:1])
if err != nil {
return minVersionError
}
if majorVersion < 2 {
return minVersionError
}
return nil
}
func (app *App) setupRepo() (bool, error) {
if err := app.validateGitVersion(); err != nil {
return false, err
}
// if we are not in a git repo, we ask if we want to `git init`
if err := app.OSCommand.RunCommand("git status"); err != nil {
cwd, err := os.Getwd()
@@ -216,6 +244,14 @@ func (app *App) Close() error {
func (app *App) KnownError(err error) (string, bool) {
errorMessage := err.Error()
knownErrorMessages := []string{app.Tr.SLocalize("minGitVersionError")}
for _, message := range knownErrorMessages {
if errorMessage == message {
return message, true
}
}
mappings := []errorMapping{
{
originalError: "fatal: not a git repository",
+3
View File
@@ -12,6 +12,9 @@ type Commit struct {
ExtraInfo string // something like 'HEAD -> master, tag: v0.15.2'
Author string
UnixTimestamp int64
// IsMerge tells us whether we're dealing with a merge commit i.e. a commit with two parents
IsMerge bool
}
func (c *Commit) ShortSha() string {
+103 -47
View File
@@ -12,7 +12,6 @@ import (
"github.com/fatih/color"
"github.com/jesseduffield/lazygit/pkg/i18n"
"github.com/jesseduffield/lazygit/pkg/utils"
"github.com/sirupsen/logrus"
)
@@ -29,21 +28,19 @@ const SEPARATION_CHAR = "|"
// CommitListBuilder returns a list of Branch objects for the current repo
type CommitListBuilder struct {
Log *logrus.Entry
GitCommand *GitCommand
OSCommand *OSCommand
Tr *i18n.Localizer
CherryPickedCommits []*Commit
Log *logrus.Entry
GitCommand *GitCommand
OSCommand *OSCommand
Tr *i18n.Localizer
}
// NewCommitListBuilder builds a new commit list builder
func NewCommitListBuilder(log *logrus.Entry, gitCommand *GitCommand, osCommand *OSCommand, tr *i18n.Localizer, cherryPickedCommits []*Commit) *CommitListBuilder {
func NewCommitListBuilder(log *logrus.Entry, gitCommand *GitCommand, osCommand *OSCommand, tr *i18n.Localizer) *CommitListBuilder {
return &CommitListBuilder{
Log: log,
GitCommand: gitCommand,
OSCommand: osCommand,
Tr: tr,
CherryPickedCommits: cherryPickedCommits,
Log: log,
GitCommand: gitCommand,
OSCommand: osCommand,
Tr: tr,
}
}
@@ -58,7 +55,9 @@ func (c *CommitListBuilder) extractCommitFromLine(line string) *Commit {
unixTimestamp := split[1]
author := split[2]
extraInfo := strings.TrimSpace(split[3])
message := strings.Join(split[4:], SEPARATION_CHAR)
parentHashes := split[4]
message := strings.Join(split[5:], SEPARATION_CHAR)
tags := []string{}
if extraInfo != "" {
@@ -71,6 +70,10 @@ func (c *CommitListBuilder) extractCommitFromLine(line string) *Commit {
unitTimestampInt, _ := strconv.Atoi(unixTimestamp)
// Any commit with multiple parents is a merge commit.
// If there's a space then it means there must be more than one parent hash
isMerge := strings.Contains(parentHashes, " ")
return &Commit{
Sha: sha,
Name: message,
@@ -78,6 +81,7 @@ func (c *CommitListBuilder) extractCommitFromLine(line string) *Commit {
ExtraInfo: extraInfo,
UnixTimestamp: int64(unitTimestampInt),
Author: author,
IsMerge: isMerge,
}
}
@@ -88,38 +92,71 @@ type GetCommitsOptions struct {
RefName string // e.g. "HEAD" or "my_branch"
}
func (c *CommitListBuilder) MergeRebasingCommits(commits []*Commit) ([]*Commit, error) {
// chances are we have as many commits as last time so we'll set the capacity to be the old length
result := make([]*Commit, 0, len(commits))
for i, commit := range commits {
if commit.Status != "rebasing" { // removing the existing rebase commits so we can add the refreshed ones
result = append(result, commits[i:]...)
break
}
}
rebaseMode, err := c.GitCommand.RebaseMode()
if err != nil {
return nil, err
}
if rebaseMode == "" {
// not in rebase mode so return original commits
return result, nil
}
rebasingCommits, err := c.getRebasingCommits(rebaseMode)
if err != nil {
return nil, err
}
if len(rebasingCommits) > 0 {
result = append(rebasingCommits, result...)
}
return result, nil
}
// GetCommits obtains the commits of the current branch
func (c *CommitListBuilder) GetCommits(opts GetCommitsOptions) ([]*Commit, error) {
commits := []*Commit{}
var rebasingCommits []*Commit
rebaseMode := ""
rebaseMode, err := c.GitCommand.RebaseMode()
if err != nil {
return nil, err
}
if opts.IncludeRebaseCommits {
if opts.IncludeRebaseCommits && opts.FilterPath == "" {
var err error
rebaseMode, err = c.GitCommand.RebaseMode()
rebasingCommits, err = c.MergeRebasingCommits(commits)
if err != nil {
return nil, err
}
if rebaseMode != "" && opts.FilterPath == "" {
// here we want to also prepend the commits that we're in the process of rebasing
rebasingCommits, err = c.getRebasingCommits(rebaseMode)
if err != nil {
return nil, err
}
if len(rebasingCommits) > 0 {
commits = append(commits, rebasingCommits...)
}
}
commits = append(commits, rebasingCommits...)
}
passedFirstPushedCommit := false
firstPushedCommit, err := c.getFirstPushedCommit(opts.RefName)
if err != nil {
// must have no upstream branch so we'll consider everything as pushed
passedFirstPushedCommit = true
}
unpushedCommits := c.getUnpushedCommits(opts.RefName)
cmd := c.getLogCmd(opts)
err := RunLineOutputCmd(cmd, func(line string) (bool, error) {
err = RunLineOutputCmd(cmd, func(line string) (bool, error) {
if strings.Split(line, " ")[0] != "gpg:" {
commit := c.extractCommitFromLine(line)
_, unpushed := unpushedCommits[commit.ShortSha()]
commit.Status = map[bool]string{true: "unpushed", false: "pushed"}[unpushed]
if commit.Sha == firstPushedCommit {
passedFirstPushedCommit = true
}
commit.Status = map[bool]string{true: "unpushed", false: "pushed"}[!passedFirstPushedCommit]
commits = append(commits, commit)
}
return false, nil
@@ -135,7 +172,7 @@ func (c *CommitListBuilder) GetCommits(opts GetCommitsOptions) ([]*Commit, error
currentCommit.Name = fmt.Sprintf("%s %s", youAreHere, currentCommit.Name)
}
commits, err = c.setCommitMergedStatuses(commits)
commits, err = c.setCommitMergedStatuses(opts.RefName, commits)
if err != nil {
return nil, err
}
@@ -253,8 +290,8 @@ func (c *CommitListBuilder) commitFromPatch(content string) (*Commit, error) {
}, nil
}
func (c *CommitListBuilder) setCommitMergedStatuses(commits []*Commit) ([]*Commit, error) {
ancestor, err := c.getMergeBase()
func (c *CommitListBuilder) setCommitMergedStatuses(refName string, commits []*Commit) ([]*Commit, error) {
ancestor, err := c.getMergeBase(refName)
if err != nil {
return nil, err
}
@@ -276,7 +313,7 @@ func (c *CommitListBuilder) setCommitMergedStatuses(commits []*Commit) ([]*Commi
return commits, nil
}
func (c *CommitListBuilder) getMergeBase() (string, error) {
func (c *CommitListBuilder) getMergeBase(refName string) (string, error) {
currentBranch, _, err := c.GitCommand.CurrentBranchName()
if err != nil {
return "", err
@@ -288,23 +325,29 @@ func (c *CommitListBuilder) getMergeBase() (string, error) {
}
// swallowing error because it's not a big deal; probably because there are no commits yet
output, _ := c.OSCommand.RunCommandWithOutput("git merge-base HEAD %s", baseBranch)
return output, nil
output, _ := c.OSCommand.RunCommandWithOutput("git merge-base %s %s", refName, baseBranch)
return ignoringWarnings(output), nil
}
// getUnpushedCommits Returns the sha's of the commits that have not yet been pushed
// to the remote branch of the current branch, a map is returned to ease look up
func (c *CommitListBuilder) getUnpushedCommits(refName string) map[string]bool {
pushables := map[string]bool{}
o, err := c.OSCommand.RunCommandWithOutput("git rev-list %s@{u}..%s --abbrev-commit --abbrev=8", refName, refName)
func ignoringWarnings(commandOutput string) string {
trimmedOutput := strings.TrimSpace(commandOutput)
split := strings.Split(trimmedOutput, "\n")
// need to get last line in case the first line is a warning about how the error is ambiguous.
// At some point we should find a way to make it unambiguous
lastLine := split[len(split)-1]
return lastLine
}
// getFirstPushedCommit returns the first commit SHA which has been pushed to the ref's upstream.
// all commits above this are deemed unpushed and marked as such.
func (c *CommitListBuilder) getFirstPushedCommit(refName string) (string, error) {
output, err := c.OSCommand.RunCommandWithOutput("git merge-base %s %s@{u}", refName, refName)
if err != nil {
return pushables
}
for _, p := range utils.SplitLines(o) {
pushables[p] = true
return "", err
}
return pushables
return ignoringWarnings(output), nil
}
// getLog gets the git log.
@@ -319,5 +362,18 @@ func (c *CommitListBuilder) getLogCmd(opts GetCommitsOptions) *exec.Cmd {
filterFlag = fmt.Sprintf(" --follow -- %s", c.OSCommand.Quote(opts.FilterPath))
}
return c.OSCommand.ExecutableFromString(fmt.Sprintf("git log %s --oneline --pretty=format:\"%%H%s%%at%s%%aN%s%%d%s%%s\" %s --abbrev=%d --date=unix %s", opts.RefName, SEPARATION_CHAR, SEPARATION_CHAR, SEPARATION_CHAR, SEPARATION_CHAR, limitFlag, 20, filterFlag))
return c.OSCommand.ExecutableFromString(
fmt.Sprintf(
"git log %s --oneline --pretty=format:\"%%H%s%%at%s%%aN%s%%d%s%%p%s%%s\" %s --abbrev=%d --date=unix %s",
opts.RefName,
SEPARATION_CHAR,
SEPARATION_CHAR,
SEPARATION_CHAR,
SEPARATION_CHAR,
SEPARATION_CHAR,
limitFlag,
20,
filterFlag,
),
)
}
+7 -47
View File
@@ -13,50 +13,10 @@ func NewDummyCommitListBuilder() *CommitListBuilder {
osCommand := NewDummyOSCommand()
return &CommitListBuilder{
Log: NewDummyLog(),
GitCommand: NewDummyGitCommandWithOSCommand(osCommand),
OSCommand: osCommand,
Tr: i18n.NewLocalizer(NewDummyLog()),
CherryPickedCommits: []*Commit{},
}
}
// TestCommitListBuilderGetUnpushedCommits is a function.
func TestCommitListBuilderGetUnpushedCommits(t *testing.T) {
type scenario struct {
testName string
command func(string, ...string) *exec.Cmd
test func(map[string]bool)
}
scenarios := []scenario{
{
"Can't retrieve pushable commits",
func(string, ...string) *exec.Cmd {
return exec.Command("test")
},
func(pushables map[string]bool) {
assert.EqualValues(t, map[string]bool{}, pushables)
},
},
{
"Retrieve pushable commits",
func(cmd string, args ...string) *exec.Cmd {
return exec.Command("echo", "8a2bb0e\n78976bc")
},
func(pushables map[string]bool) {
assert.Len(t, pushables, 2)
assert.EqualValues(t, map[string]bool{"8a2bb0e": true, "78976bc": true}, pushables)
},
},
}
for _, s := range scenarios {
t.Run(s.testName, func(t *testing.T) {
c := NewDummyCommitListBuilder()
c.OSCommand.SetCommand(s.command)
s.test(c.getUnpushedCommits("HEAD"))
})
Log: NewDummyLog(),
GitCommand: NewDummyGitCommandWithOSCommand(osCommand),
OSCommand: osCommand,
Tr: i18n.NewLocalizer(NewDummyLog()),
}
}
@@ -106,7 +66,7 @@ func TestCommitListBuilderGetMergeBase(t *testing.T) {
},
func(output string, err error) {
assert.NoError(t, err)
assert.Equal(t, "blah\n", output)
assert.Equal(t, "blah", output)
},
},
{
@@ -126,7 +86,7 @@ func TestCommitListBuilderGetMergeBase(t *testing.T) {
},
func(output string, err error) {
assert.NoError(t, err)
assert.Equal(t, "blah\n", output)
assert.Equal(t, "blah", output)
},
},
{
@@ -145,7 +105,7 @@ func TestCommitListBuilderGetMergeBase(t *testing.T) {
t.Run(s.testName, func(t *testing.T) {
c := NewDummyCommitListBuilder()
c.OSCommand.SetCommand(s.command)
s.test(c.getMergeBase())
s.test(c.getMergeBase("HEAD"))
})
}
}
+12 -4
View File
@@ -910,7 +910,8 @@ func (c *GitCommand) PrepareInteractiveRebaseCommand(baseSha string, todo string
debug = "TRUE"
}
splitCmd := str.ToArgv(fmt.Sprintf("git rebase --interactive --autostash --keep-empty --rebase-merges %s", baseSha))
cmdStr := fmt.Sprintf("git rebase --interactive --autostash --keep-empty %s", baseSha)
splitCmd := str.ToArgv(cmdStr)
cmd := c.OSCommand.command(splitCmd[0], splitCmd[1:]...)
@@ -962,11 +963,18 @@ func (c *GitCommand) GenerateGenericRebaseTodo(commits []*Commit, actionIndex in
todo := ""
for i, commit := range commits[0:baseIndex] {
a := "pick"
var commitAction string
if i == actionIndex {
a = action
commitAction = action
} else if commit.IsMerge {
// your typical interactive rebase will actually drop merge commits by default. Damn git CLI, you scary!
// doing this means we don't need to worry about rebasing over merges which always causes problems.
// you typically shouldn't be doing rebases that pass over merge commits anyway.
commitAction = "drop"
} else {
commitAction = "pick"
}
todo = a + " " + commit.Sha + " " + commit.Name + "\n" + todo
todo = commitAction + " " + commit.Sha + " " + commit.Name + "\n" + todo
}
return todo, commits[baseIndex].Sha, nil
+3 -3
View File
@@ -1639,7 +1639,7 @@ func TestGitCommandRebaseBranch(t *testing.T) {
"master",
test.CreateMockCommand(t, []*test.CommandSwapper{
{
Expect: "git rebase --interactive --autostash --keep-empty --rebase-merges master",
Expect: "git rebase --interactive --autostash --keep-empty master",
Replace: "echo",
},
}),
@@ -1652,7 +1652,7 @@ func TestGitCommandRebaseBranch(t *testing.T) {
"master",
test.CreateMockCommand(t, []*test.CommandSwapper{
{
Expect: "git rebase --interactive --autostash --keep-empty --rebase-merges master",
Expect: "git rebase --interactive --autostash --keep-empty master",
Replace: "test",
},
}),
@@ -1775,7 +1775,7 @@ func TestGitCommandDiscardOldFileChanges(t *testing.T) {
"test999.txt",
test.CreateMockCommand(t, []*test.CommandSwapper{
{
Expect: "git rebase --interactive --autostash --keep-empty --rebase-merges abcdef",
Expect: "git rebase --interactive --autostash --keep-empty abcdef",
Replace: "echo",
},
{
+1
View File
@@ -276,6 +276,7 @@ git:
autoFetch: true
branchLogCmd: "git log --graph --color=always --abbrev-commit --decorate --date=relative --pretty=medium {{branchName}} --"
overrideGpg: false # prevents lazygit from spawning a separate process when using GPG
disableForcePushing: false
update:
method: prompt # can be: prompt | background | never
days: 14 # how often a update is checked for
+23 -6
View File
@@ -97,7 +97,10 @@ func (gui *Gui) refreshCommits() error {
}
func (gui *Gui) refreshCommitsWithLimit() error {
builder := commands.NewCommitListBuilder(gui.Log, gui.GitCommand, gui.OSCommand, gui.Tr, gui.State.Modes.CherryPicking.CherryPickedCommits)
gui.State.BranchCommitsMutex.Lock()
defer gui.State.BranchCommitsMutex.Unlock()
builder := commands.NewCommitListBuilder(gui.Log, gui.GitCommand, gui.OSCommand, gui.Tr)
commits, err := builder.GetCommits(
commands.GetCommitsOptions{
@@ -115,6 +118,21 @@ func (gui *Gui) refreshCommitsWithLimit() error {
return gui.postRefreshUpdate(gui.Contexts.BranchCommits.Context)
}
func (gui *Gui) refreshRebaseCommits() error {
gui.State.BranchCommitsMutex.Lock()
defer gui.State.BranchCommitsMutex.Unlock()
builder := commands.NewCommitListBuilder(gui.Log, gui.GitCommand, gui.OSCommand, gui.Tr)
updatedCommits, err := builder.MergeRebasingCommits(gui.State.Commits)
if err != nil {
return err
}
gui.State.Commits = updatedCommits
return gui.postRefreshUpdate(gui.Contexts.BranchCommits.Context)
}
// specific functions
func (gui *Gui) handleCommitSquashDown(g *gocui.Gui, v *gocui.View) error {
@@ -256,9 +274,8 @@ func (gui *Gui) handleMidRebaseCommand(action string) (bool, error) {
if err := gui.GitCommand.EditRebaseTodo(gui.State.Panels.Commits.SelectedLineIdx, action); err != nil {
return false, gui.surfaceError(err)
}
// TODO: consider doing this in a way that is less expensive. We don't actually
// need to reload all the commits, just the TODO commits.
return true, gui.refreshSidePanels(refreshOptions{scope: []int{COMMITS}})
return true, gui.refreshRebaseCommits()
}
func (gui *Gui) handleCommitDelete(g *gocui.Gui, v *gocui.View) error {
@@ -301,7 +318,7 @@ func (gui *Gui) handleCommitMoveDown(g *gocui.Gui, v *gocui.View) error {
return gui.surfaceError(err)
}
gui.State.Panels.Commits.SelectedLineIdx++
return gui.refreshSidePanels(refreshOptions{mode: BLOCK_UI, scope: []int{COMMITS, BRANCHES}})
return gui.refreshRebaseCommits()
}
return gui.WithWaitingStatus(gui.Tr.SLocalize("MovingStatus"), func() error {
@@ -328,7 +345,7 @@ func (gui *Gui) handleCommitMoveUp(g *gocui.Gui, v *gocui.View) error {
return gui.surfaceError(err)
}
gui.State.Panels.Commits.SelectedLineIdx--
return gui.refreshSidePanels(refreshOptions{mode: BLOCK_UI, scope: []int{COMMITS, BRANCHES}})
return gui.refreshRebaseCommits()
}
return gui.WithWaitingStatus(gui.Tr.SLocalize("MovingStatus"), func() error {
+20 -9
View File
@@ -332,15 +332,17 @@ func (gui *Gui) handleAmendCommitPress() error {
title: strings.Title(gui.Tr.SLocalize("AmendLastCommit")),
prompt: gui.Tr.SLocalize("SureToAmend"),
handleConfirm: func() error {
ok, err := gui.runSyncOrAsyncCommand(gui.GitCommand.AmendHead())
if err != nil {
return err
}
if !ok {
return nil
}
return gui.WithWaitingStatus(gui.Tr.SLocalize("AmendingStatus"), func() error {
ok, err := gui.runSyncOrAsyncCommand(gui.GitCommand.AmendHead())
if err != nil {
return err
}
if !ok {
return nil
}
return gui.refreshSidePanels(refreshOptions{mode: ASYNC})
return gui.refreshSidePanels(refreshOptions{mode: ASYNC})
})
},
})
}
@@ -517,6 +519,11 @@ func (gui *Gui) pushWithForceFlag(v *gocui.View, force bool, upstream string, ar
branchName := gui.getCheckedOutBranch().Name
err := gui.GitCommand.Push(branchName, force, upstream, args, gui.promptUserForCredential)
if err != nil && !force && strings.Contains(err.Error(), "Updates were rejected") {
forcePushDisabled := gui.Config.GetUserConfig().GetBool("git.disableForcePushing")
if forcePushDisabled {
gui.createErrorPanel(gui.Tr.SLocalize("UpdatesRejectedAndForcePushDisabled"))
return
}
gui.ask(askOpts{
title: gui.Tr.SLocalize("ForcePush"),
prompt: gui.Tr.SLocalize("ForcePushPrompt"),
@@ -524,7 +531,6 @@ func (gui *Gui) pushWithForceFlag(v *gocui.View, force bool, upstream string, ar
return gui.pushWithForceFlag(v, true, upstream, args)
},
})
return
}
gui.handleCredentialsPopup(err)
@@ -564,6 +570,11 @@ func (gui *Gui) pushFiles(g *gocui.Gui, v *gocui.View) error {
return gui.pushWithForceFlag(v, false, "", "")
}
forcePushDisabled := gui.Config.GetUserConfig().GetBool("git.disableForcePushing")
if forcePushDisabled {
return gui.createErrorPanel(gui.Tr.SLocalize("ForcePushDisabled"))
}
return gui.ask(askOpts{
title: gui.Tr.SLocalize("ForcePush"),
prompt: gui.Tr.SLocalize("ForcePushPrompt"),
+3 -4
View File
@@ -147,12 +147,11 @@ func (gui *Gui) handleInfoClick(g *gocui.Gui, v *gocui.View) error {
cx, _ := v.Cursor()
width, _ := v.Size()
if width-cx > len(gui.Tr.SLocalize("(reset)")) {
return nil
}
for _, mode := range gui.modeStatuses() {
if mode.isActive() {
if width-cx > len(gui.Tr.SLocalize("(reset)")) {
return nil
}
return mode.reset()
}
}
+1
View File
@@ -297,6 +297,7 @@ type guiState struct {
RefreshingFilesMutex sync.Mutex
RefreshingStatusMutex sync.Mutex
FetchMutex sync.Mutex
BranchCommitsMutex sync.Mutex
Searching searchingState
ScreenMode int
SideView *gocui.View
+17 -4
View File
@@ -32,7 +32,6 @@ func getFullDescriptionDisplayStringsForCommit(c *commands.Commit, cherryPickedC
yellow := color.New(color.FgYellow)
green := color.New(color.FgGreen)
blue := color.New(color.FgBlue)
cyan := color.New(color.FgCyan)
defaultColor := color.New(theme.DefaultTextColor)
diffedColor := color.New(theme.DiffTerminalColor)
@@ -66,7 +65,7 @@ func getFullDescriptionDisplayStringsForCommit(c *commands.Commit, cherryPickedC
tagString := ""
secondColumnString := blue.Sprint(utils.UnixToDate(c.UnixTimestamp))
if c.Action != "" {
secondColumnString = cyan.Sprint(c.Action)
secondColumnString = color.New(actionColorMap(c.Action)).Sprint(c.Action)
} else if c.ExtraInfo != "" {
tagColor := color.New(color.FgMagenta, color.Bold)
tagString = utils.ColoredStringDirect(c.ExtraInfo, tagColor) + " "
@@ -82,7 +81,6 @@ func getDisplayStringsForCommit(c *commands.Commit, cherryPickedCommitShaMap map
yellow := color.New(color.FgYellow)
green := color.New(color.FgGreen)
blue := color.New(color.FgBlue)
cyan := color.New(color.FgCyan)
defaultColor := color.New(theme.DefaultTextColor)
diffedColor := color.New(theme.DiffTerminalColor)
@@ -116,7 +114,7 @@ func getDisplayStringsForCommit(c *commands.Commit, cherryPickedCommitShaMap map
actionString := ""
tagString := ""
if c.Action != "" {
actionString = cyan.Sprint(utils.WithPadding(c.Action, 7)) + " "
actionString = color.New(actionColorMap(c.Action)).Sprint(utils.WithPadding(c.Action, 7)) + " "
} else if len(c.Tags) > 0 {
tagColor := color.New(color.FgMagenta, color.Bold)
tagString = utils.ColoredStringDirect(strings.Join(c.Tags, " "), tagColor) + " "
@@ -124,3 +122,18 @@ func getDisplayStringsForCommit(c *commands.Commit, cherryPickedCommitShaMap map
return []string{shaColor.Sprint(c.ShortSha()), actionString + tagString + defaultColor.Sprint(c.Name)}
}
func actionColorMap(str string) color.Attribute {
switch str {
case "pick":
return color.FgCyan
case "drop":
return color.FgRed
case "edit":
return color.FgGreen
case "fixup":
return color.FgMagenta
default:
return color.FgYellow
}
}
+13 -4
View File
@@ -23,11 +23,16 @@ func (gui *Gui) handleOpenSearch(g *gocui.Gui, v *gocui.View) error {
func (gui *Gui) handleSearch(g *gocui.Gui, v *gocui.View) error {
gui.State.Searching.searchString = gui.getSearchView().Buffer()
if err := gui.switchContextToView(gui.State.Searching.view.Name()); err != nil {
if err := gui.returnFromContext(); err != nil {
return err
}
if err := gui.State.Searching.view.Search(gui.State.Searching.searchString); err != nil {
view := gui.State.Searching.view
if view == nil {
return nil
}
if err := view.Search(gui.State.Searching.searchString); err != nil {
return err
}
@@ -86,9 +91,13 @@ func (gui *Gui) onSearchEscape() error {
}
func (gui *Gui) handleSearchEscape(g *gocui.Gui, v *gocui.View) error {
if err := gui.switchContextToView(gui.State.Searching.view.Name()); err != nil {
if err := gui.onSearchEscape(); err != nil {
return err
}
return gui.onSearchEscape()
if err := gui.returnFromContext(); err != nil {
return err
}
return nil
}
+1 -1
View File
@@ -77,7 +77,7 @@ func (gui *Gui) handleViewSubCommitFiles() error {
func (gui *Gui) switchToSubCommitsContext(refName string) error {
// need to populate my sub commits
builder := commands.NewCommitListBuilder(gui.Log, gui.GitCommand, gui.OSCommand, gui.Tr, gui.State.Modes.CherryPicking.CherryPickedCommits)
builder := commands.NewCommitListBuilder(gui.Log, gui.GitCommand, gui.OSCommand, gui.Tr)
commits, err := builder.GetCommits(
commands.GetCommitsOptions{
+7 -1
View File
@@ -418,6 +418,12 @@ func addDutch(i18nObject *i18n.Bundle) error {
}, &i18n.Message{
ID: "ForcePushPrompt",
Other: "Jouw branch is afgeweken van de remote branch. Druk 'esc' om te annuleren, of 'enter' om geforceert te pushen.",
}, &i18n.Message{
ID: "ForcePushDisabled",
Other: "Your branch has diverged from the remote branch and you've disabled force pushing",
}, &i18n.Message{
ID: "UpdatesRejectedAndForcePushDisabled",
Other: "Updates were rejected and you have disabled force pushing",
}, &i18n.Message{
ID: "checkForUpdate",
Other: "check voor updates",
@@ -446,7 +452,7 @@ func addDutch(i18nObject *i18n.Bundle) error {
1) Als je meer van lazygit zijn features wilt leren bekijk dan deze video:
https://youtu.be/CPLdltN7wgE
3) Als je git gebruikt, ben je een programmeur! Met jouw hulp kunnen we lazygit verbeteren, dus overweeg om een ​​donateur te worden en mee te doen aan het plezier op
2) Als je git gebruikt, ben je een programmeur! Met jouw hulp kunnen we lazygit verbeteren, dus overweeg om een ​​donateur te worden en mee te doen aan het plezier op
https://github.com/jesseduffield/lazygit`,
}, &i18n.Message{
ID: "GitconfigParseErr",
+10 -1
View File
@@ -426,6 +426,12 @@ func addEnglish(i18nObject *i18n.Bundle) error {
}, &i18n.Message{
ID: "ForcePushPrompt",
Other: "Your branch has diverged from the remote branch. Press 'esc' to cancel, or 'enter' to force push.",
}, &i18n.Message{
ID: "ForcePushDisabled",
Other: "Your branch has diverged from the remote branch and you've disabled force pushing",
}, &i18n.Message{
ID: "UpdatesRejectedAndForcePushDisabled",
Other: "Updates were rejected and you have disabled force pushing",
}, &i18n.Message{
ID: "checkForUpdate",
Other: "check for update",
@@ -454,7 +460,7 @@ func addEnglish(i18nObject *i18n.Bundle) error {
1) If you want to learn about lazygit's features, watch this vid:
https://youtu.be/CPLdltN7wgE
3) If you're using git, that makes you a programmer! With your help we can make lazygit better, so consider becoming a contributor and joining the fun at
2) If you're using git, that makes you a programmer! With your help we can make lazygit better, so consider becoming a contributor and joining the fun at
https://github.com/jesseduffield/lazygit`,
}, &i18n.Message{
ID: "GitconfigParseErr",
@@ -1176,6 +1182,9 @@ func addEnglish(i18nObject *i18n.Bundle) error {
}, &i18n.Message{
ID: "viewCommits",
Other: "view commits",
}, &i18n.Message{
ID: "minGitVersionError",
Other: "Git version must be at least 2.0 (i.e. from 2014 onwards). Please upgrade your git version. Alternatively raise an issue at https://github.com/jesseduffield/lazygit/issues for lazygit to be more backwards compatible.",
},
)
}
+6
View File
@@ -338,6 +338,12 @@ func addPolish(i18nObject *i18n.Bundle) error {
}, &i18n.Message{
ID: "ForcePushPrompt",
Other: "Twoja gałąź rozeszła się z gałęzią zdalną. Wciśnij 'esc' aby anulować lub 'enter' aby wymusić wypchnięcie.",
}, &i18n.Message{
ID: "ForcePushDisabled",
Other: "Your branch has diverged from the remote branch and you've disabled force pushing",
}, &i18n.Message{
ID: "UpdatesRejectedAndForcePushDisabled",
Other: "Updates were rejected and you have disabled force pushing",
}, &i18n.Message{
ID: "checkForUpdate",
Other: "sprawdź aktualizacje",