mirror of
https://github.com/jesseduffield/lazygit.git
synced 2026-09-28 18:26:03 -04:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
46cce28758 | ||
|
|
5611d9a3ef | ||
|
|
40bec49de8 | ||
|
|
f99d5f74d4 | ||
|
|
30a066aa41 | ||
|
|
1dcc3363d0 | ||
|
|
c6948582e6 | ||
|
|
196c83d058 |
@@ -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",
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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
|
||||
@@ -292,19 +329,14 @@ func (c *CommitListBuilder) getMergeBase() (string, error) {
|
||||
return 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)
|
||||
// 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
|
||||
return "", err
|
||||
}
|
||||
for _, p := range utils.SplitLines(o) {
|
||||
pushables[p] = true
|
||||
}
|
||||
|
||||
return pushables
|
||||
return strings.TrimSpace(output), nil
|
||||
}
|
||||
|
||||
// getLog gets the git log.
|
||||
@@ -319,5 +351,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,
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
@@ -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()),
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+12
-4
@@ -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
|
||||
|
||||
@@ -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",
|
||||
},
|
||||
{
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
@@ -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
|
||||
}
|
||||
|
||||
@@ -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{
|
||||
|
||||
@@ -1176,6 +1176,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.",
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user