diff options
author | Mark Kopenga <mkopenga@gmail.com> | 2018-12-08 16:41:39 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2018-12-08 16:41:39 +0100 |
commit | 19a6a32625d59c61ecfe91ef8626390eb34a922a (patch) | |
tree | b02d1a9c8477d2614f99cc80b40b54accf28c127 /pkg | |
parent | 270658fc009dc254a80501fc1c9f5f82acd27239 (diff) | |
parent | ff856b763033a241370bfde98d7386b43b7d0893 (diff) |
Merge branch 'master' into https-ask-for-username-password
Diffstat (limited to 'pkg')
-rw-r--r-- | pkg/app/app.go | 5 | ||||
-rw-r--r-- | pkg/commands/branch.go | 15 | ||||
-rw-r--r-- | pkg/commands/git.go | 34 | ||||
-rw-r--r-- | pkg/commands/git_test.go | 6 | ||||
-rw-r--r-- | pkg/gui/branches_panel.go | 187 | ||||
-rw-r--r-- | pkg/gui/commit_message_panel.go | 10 | ||||
-rw-r--r-- | pkg/gui/commits_panel.go | 124 | ||||
-rw-r--r-- | pkg/gui/confirmation_panel.go | 11 | ||||
-rw-r--r-- | pkg/gui/files_panel.go | 137 | ||||
-rw-r--r-- | pkg/gui/gui.go | 95 | ||||
-rw-r--r-- | pkg/gui/keybindings.go | 36 | ||||
-rw-r--r-- | pkg/gui/menu_panel.go | 35 | ||||
-rw-r--r-- | pkg/gui/merge_panel.go | 7 | ||||
-rw-r--r-- | pkg/gui/staging_panel.go | 62 | ||||
-rw-r--r-- | pkg/gui/stash_panel.go | 72 | ||||
-rw-r--r-- | pkg/gui/status_panel.go | 15 | ||||
-rw-r--r-- | pkg/gui/view_helpers.go | 209 | ||||
-rw-r--r-- | pkg/i18n/dutch.go | 4 | ||||
-rw-r--r-- | pkg/i18n/english.go | 10 | ||||
-rw-r--r-- | pkg/i18n/polish.go | 4 | ||||
-rw-r--r-- | pkg/utils/utils.go | 6 | ||||
-rw-r--r-- | pkg/utils/utils_test.go | 11 |
22 files changed, 688 insertions, 407 deletions
diff --git a/pkg/app/app.go b/pkg/app/app.go index 65acd2e35..74152b08b 100644 --- a/pkg/app/app.go +++ b/pkg/app/app.go @@ -52,6 +52,11 @@ func newLogger(config config.AppConfigurer) *logrus.Entry { } else { log = newProductionLogger(config) } + + // highly recommended: tail -f development.log | humanlog + // https://github.com/aybabtme/humanlog + log.Formatter = &logrus.JSONFormatter{} + if config.GetUserConfig().GetString("reporting") == "on" { // this isn't really a secret token: it only has permission to push new rollbar items hook := rollrus.NewHook("23432119147a4367abf7c0de2aa99a2d", environment) diff --git a/pkg/commands/branch.go b/pkg/commands/branch.go index 19553a26b..49655c41a 100644 --- a/pkg/commands/branch.go +++ b/pkg/commands/branch.go @@ -1,6 +1,7 @@ package commands import ( + "fmt" "strings" "github.com/fatih/color" @@ -10,13 +11,21 @@ import ( // Branch : A git branch // duplicating this for now type Branch struct { - Name string - Recency string + Name string + Recency string + Pushables string + Pullables string + Selected bool } // GetDisplayStrings returns the dispaly string of branch func (b *Branch) GetDisplayStrings() []string { - return []string{b.Recency, utils.ColoredString(b.Name, b.GetColor())} + displayName := utils.ColoredString(b.Name, b.GetColor()) + if b.Selected && b.Pushables != "" && b.Pullables != "" { + displayName = fmt.Sprintf("ā%sā%s %s", b.Pushables, b.Pullables, displayName) + } + + return []string{b.Recency, displayName} } // GetColor branch color diff --git a/pkg/commands/git.go b/pkg/commands/git.go index 584558d7e..d9230c4eb 100644 --- a/pkg/commands/git.go +++ b/pkg/commands/git.go @@ -154,7 +154,6 @@ func (c *GitCommand) GetStatusFiles() []*File { } files = append(files, file) } - c.Log.Info(files) // TODO: use a dumper-esque log here return files } @@ -208,19 +207,33 @@ func includesInt(list []int, a int) bool { return false } -// ResetHard does the equivalent of `git reset --hard HEAD` -func (c *GitCommand) ResetHard() error { - return c.Worktree.Reset(&gogit.ResetOptions{Mode: gogit.HardReset}) +// ResetAndClean removes all unstaged changes and removes all untracked files +func (c *GitCommand) ResetAndClean() error { + if err := c.OSCommand.RunCommand("git reset --hard HEAD"); err != nil { + return err + } + + return c.OSCommand.RunCommand("git clean -fd") +} + +func (c *GitCommand) GetCurrentBranchUpstreamDifferenceCount() (string, string) { + return c.GetCommitDifferences("HEAD", "@{u}") } -// UpstreamDifferenceCount checks how many pushables/pullables there are for the +func (c *GitCommand) GetBranchUpstreamDifferenceCount(branchName string) (string, string) { + upstream := "origin" // hardcoded for now + return c.GetCommitDifferences(branchName, fmt.Sprintf("%s/%s", upstream, branchName)) +} + +// GetCommitDifferences checks how many pushables/pullables there are for the // current branch -func (c *GitCommand) UpstreamDifferenceCount() (string, string) { - pushableCount, err := c.OSCommand.RunCommandWithOutput("git rev-list @{u}..HEAD --count") +func (c *GitCommand) GetCommitDifferences(from, to string) (string, string) { + command := "git rev-list %s..%s --count" + pushableCount, err := c.OSCommand.RunCommandWithOutput(fmt.Sprintf(command, to, from)) if err != nil { return "?", "?" } - pullableCount, err := c.OSCommand.RunCommandWithOutput("git rev-list HEAD..@{u} --count") + pullableCount, err := c.OSCommand.RunCommandWithOutput(fmt.Sprintf(command, from, to)) if err != nil { return "?", "?" } @@ -609,3 +622,8 @@ func (c *GitCommand) ApplyPatch(patch string) (string, error) { return c.OSCommand.RunCommandWithOutput(fmt.Sprintf("git apply --cached %s", filename)) } + +func (c *GitCommand) FastForward(branchName string) error { + upstream := "origin" // hardcoding for now + return c.OSCommand.RunCommand(fmt.Sprintf("git fetch %s %s:%s", upstream, branchName, branchName)) +} diff --git a/pkg/commands/git_test.go b/pkg/commands/git_test.go index da6a90c98..7d0a503d7 100644 --- a/pkg/commands/git_test.go +++ b/pkg/commands/git_test.go @@ -557,8 +557,8 @@ func TestGitCommandMergeStatusFiles(t *testing.T) { } } -// TestGitCommandUpstreamDifferentCount is a function. -func TestGitCommandUpstreamDifferentCount(t *testing.T) { +// TestGitCommandGetCommitDifferences is a function. +func TestGitCommandGetCommitDifferences(t *testing.T) { type scenario struct { testName string command func(string, ...string) *exec.Cmd @@ -610,7 +610,7 @@ func TestGitCommandUpstreamDifferentCount(t *testing.T) { t.Run(s.testName, func(t *testing.T) { gitCmd := newDummyGitCommand() gitCmd.OSCommand.command = s.command - s.test(gitCmd.UpstreamDifferenceCount()) + s.test(gitCmd.GetCommitDifferences("HEAD", "@{u}")) }) } } diff --git a/pkg/gui/branches_panel.go b/pkg/gui/branches_panel.go index 059f0af50..e54d6e8c1 100644 --- a/pkg/gui/branches_panel.go +++ b/pkg/gui/branches_panel.go @@ -7,25 +7,116 @@ import ( "github.com/jesseduffield/gocui" "github.com/jesseduffield/lazygit/pkg/commands" "github.com/jesseduffield/lazygit/pkg/git" - "github.com/jesseduffield/lazygit/pkg/utils" ) +// list panel functions + +func (gui *Gui) getSelectedBranch() *commands.Branch { + selectedLine := gui.State.Panels.Branches.SelectedLine + if selectedLine == -1 { + return nil + } + + return gui.State.Branches[selectedLine] +} + +// may want to standardise how these select methods work +func (gui *Gui) handleBranchSelect(g *gocui.Gui, v *gocui.View) error { + // This really shouldn't happen: there should always be a master branch + if len(gui.State.Branches) == 0 { + return gui.renderString(g, "main", gui.Tr.SLocalize("NoBranchesThisRepo")) + } + branch := gui.getSelectedBranch() + if err := gui.focusPoint(0, gui.State.Panels.Branches.SelectedLine, v); err != nil { + return err + } + go func() { + _ = gui.RenderSelectedBranchUpstreamDifferences() + }() + go func() { + graph, err := gui.GitCommand.GetBranchGraph(branch.Name) + if err != nil && strings.HasPrefix(graph, "fatal: ambiguous argument") { + graph = gui.Tr.SLocalize("NoTrackingThisBranch") + } + _ = gui.renderString(g, "main", graph) + }() + return nil +} + +func (gui *Gui) RenderSelectedBranchUpstreamDifferences() error { + // here we tell the selected branch that it is selected. + // this is necessary for showing stats on a branch that is selected, because + // the displaystring function doesn't have access to gui state to tell if it's selected + for i, branch := range gui.State.Branches { + branch.Selected = i == gui.State.Panels.Branches.SelectedLine + } + + branch := gui.getSelectedBranch() + branch.Pushables, branch.Pullables = gui.GitCommand.GetBranchUpstreamDifferenceCount(branch.Name) + return gui.renderListPanel(gui.getBranchesView(gui.g), gui.State.Branches) +} + +// gui.refreshStatus is called at the end of this because that's when we can +// be sure there is a state.Branches array to pick the current branch from +func (gui *Gui) refreshBranches(g *gocui.Gui) error { + g.Update(func(g *gocui.Gui) error { + builder, err := git.NewBranchListBuilder(gui.Log, gui.GitCommand) + if err != nil { + return err + } + gui.State.Branches = builder.Build() + + gui.refreshSelectedLine(&gui.State.Panels.Branches.SelectedLine, len(gui.State.Branches)) + if err := gui.resetOrigin(gui.getBranchesView(gui.g)); err != nil { + return err + } + if err := gui.RenderSelectedBranchUpstreamDifferences(); err != nil { + return err + } + + return gui.refreshStatus(g) + }) + return nil +} + +func (gui *Gui) handleBranchesNextLine(g *gocui.Gui, v *gocui.View) error { + panelState := gui.State.Panels.Branches + gui.changeSelectedLine(&panelState.SelectedLine, len(gui.State.Branches), false) + return gui.handleBranchSelect(gui.g, v) +} + +func (gui *Gui) handleBranchesPrevLine(g *gocui.Gui, v *gocui.View) error { + panelState := gui.State.Panels.Branches + gui.changeSelectedLine(&panelState.SelectedLine, len(gui.State.Branches), true) + + return gui.handleBranchSelect(gui.g, v) +} + +// specific functions + func (gui *Gui) handleBranchPress(g *gocui.Gui, v *gocui.View) error { - index := gui.getItemPosition(gui.getBranchesView(g)) - if index == 0 { + if gui.State.Panels.Branches.SelectedLine == -1 { + return nil + } + if gui.State.Panels.Branches.SelectedLine == 0 { return gui.createErrorPanel(g, gui.Tr.SLocalize("AlreadyCheckedOutBranch")) } - branch := gui.getSelectedBranch(gui.getBranchesView(g)) + branch := gui.getSelectedBranch() if err := gui.GitCommand.Checkout(branch.Name, false); err != nil { - gui.createErrorPanel(g, err.Error()) + if err := gui.createErrorPanel(g, err.Error()); err != nil { + return err + } + } else { + gui.State.Panels.Branches.SelectedLine = 0 } + return gui.refreshSidePanels(g) } func (gui *Gui) handleCreatePullRequestPress(g *gocui.Gui, v *gocui.View) error { - branch := gui.getSelectedBranch(gui.getBranchesView(g)) pullRequest := commands.NewPullRequest(gui.GitCommand) + branch := gui.getSelectedBranch() if err := pullRequest.Create(branch); err != nil { return gui.createErrorPanel(g, err.Error()) } @@ -60,7 +151,7 @@ func (gui *Gui) handleGitFetch(g *gocui.Gui, v *gocui.View) error { } func (gui *Gui) handleForceCheckout(g *gocui.Gui, v *gocui.View) error { - branch := gui.getSelectedBranch(v) + branch := gui.getSelectedBranch() message := gui.Tr.SLocalize("SureForceCheckout") title := gui.Tr.SLocalize("ForceCheckoutBranch") return gui.createConfirmationPanel(g, v, title, message, func(g *gocui.Gui, v *gocui.View) error { @@ -108,8 +199,11 @@ func (gui *Gui) handleForceDeleteBranch(g *gocui.Gui, v *gocui.View) error { } func (gui *Gui) deleteBranch(g *gocui.Gui, v *gocui.View, force bool) error { + selectedBranch := gui.getSelectedBranch() + if selectedBranch == nil { + return nil + } checkedOutBranch := gui.State.Branches[0] - selectedBranch := gui.getSelectedBranch(v) if checkedOutBranch.Name == selectedBranch.Name { return gui.createErrorPanel(g, gui.Tr.SLocalize("CantDeleteCheckOutBranch")) } @@ -144,7 +238,7 @@ func (gui *Gui) deleteNamedBranch(g *gocui.Gui, v *gocui.View, selectedBranch *c func (gui *Gui) handleMerge(g *gocui.Gui, v *gocui.View) error { checkedOutBranch := gui.State.Branches[0] - selectedBranch := gui.getSelectedBranch(v) + selectedBranch := gui.getSelectedBranch() defer gui.refreshSidePanels(g) if checkedOutBranch.Name == selectedBranch.Name { return gui.createErrorPanel(g, gui.Tr.SLocalize("CantMergeBranchIntoItself")) @@ -155,59 +249,36 @@ func (gui *Gui) handleMerge(g *gocui.Gui, v *gocui.View) error { return nil } -func (gui *Gui) getSelectedBranch(v *gocui.View) *commands.Branch { - lineNumber := gui.getItemPosition(v) - return gui.State.Branches[lineNumber] -} - -func (gui *Gui) renderBranchesOptions(g *gocui.Gui) error { - return gui.renderGlobalOptions(g) -} - -// may want to standardise how these select methods work -func (gui *Gui) handleBranchSelect(g *gocui.Gui, v *gocui.View) error { - if err := gui.renderBranchesOptions(g); err != nil { - return err +func (gui *Gui) handleFastForward(g *gocui.Gui, v *gocui.View) error { + branch := gui.getSelectedBranch() + if branch == nil { + return nil } - // This really shouldn't happen: there should always be a master branch - if len(gui.State.Branches) == 0 { - return gui.renderString(g, "main", gui.Tr.SLocalize("NoBranchesThisRepo")) + if branch.Pushables == "" { + return nil + } + if branch.Pushables == "?" { + return gui.createErrorPanel(gui.g, "Cannot fast-forward a branch with no upstream") + } + if branch.Pushables != "0" { + return gui.createErrorPanel(gui.g, "Cannot fast-forward a branch with commits to push") } + upstream := "origin" // hardcoding for now + message := gui.Tr.TemplateLocalize( + "Fetching", + Teml{ + "from": fmt.Sprintf("%s/%s", upstream, branch.Name), + "to": branch.Name, + }, + ) go func() { - branch := gui.getSelectedBranch(v) - diff, err := gui.GitCommand.GetBranchGraph(branch.Name) - if err != nil && strings.HasPrefix(diff, "fatal: ambiguous argument") { - diff = gui.Tr.SLocalize("NoTrackingThisBranch") + _ = gui.createMessagePanel(gui.g, v, "", message) + if err := gui.GitCommand.FastForward(branch.Name); err != nil { + _ = gui.createErrorPanel(gui.g, err.Error()) + } else { + _ = gui.closeConfirmationPrompt(gui.g) + _ = gui.RenderSelectedBranchUpstreamDifferences() } - gui.renderString(g, "main", diff) }() return nil } - -// gui.refreshStatus is called at the end of this because that's when we can -// be sure there is a state.Branches array to pick the current branch from -func (gui *Gui) refreshBranches(g *gocui.Gui) error { - g.Update(func(g *gocui.Gui) error { - v, err := g.View("branches") - if err != nil { - panic(err) - } - builder, err := git.NewBranchListBuilder(gui.Log, gui.GitCommand) - if err != nil { - return err - } - gui.State.Branches = builder.Build() - - v.Clear() - list, err := utils.RenderList(gui.State.Branches) - if err != nil { - return err - } - - fmt.Fprint(v, list) - - gui.resetOrigin(v) - return gui.refreshStatus(g) - }) - return nil -} diff --git a/pkg/gui/commit_message_panel.go b/pkg/gui/commit_message_panel.go index 14e3ab795..85497ef87 100644 --- a/pkg/gui/commit_message_panel.go +++ b/pkg/gui/commit_message_panel.go @@ -23,12 +23,12 @@ func (gui *Gui) handleCommitConfirm(g *gocui.Gui, v *gocui.View) error { gui.SubProcess = sub return gui.Errors.ErrSubProcess } - gui.refreshFiles(g) v.Clear() - v.SetCursor(0, 0) - g.SetViewOnBottom("commitMessage") - gui.switchFocus(g, v, gui.getFilesView(g)) - return gui.refreshCommits(g) + _ = v.SetCursor(0, 0) + _ = v.SetOrigin(0, 0) + _, _ = g.SetViewOnBottom("commitMessage") + _ = gui.switchFocus(g, v, gui.getFilesView(g)) + return gui.refreshSidePanels(g) } func (gui *Gui) handleCommitClose(g *gocui.Gui, v *gocui.View) error { diff --git a/pkg/gui/commits_panel.go b/pkg/gui/commits_panel.go index ee7f191a7..4ff79960d 100644 --- a/pkg/gui/commits_panel.go +++ b/pkg/gui/commits_panel.go @@ -9,29 +9,54 @@ import ( "github.com/jesseduffield/lazygit/pkg/utils" ) +// list panel functions + +func (gui *Gui) getSelectedCommit(g *gocui.Gui) *commands.Commit { + selectedLine := gui.State.Panels.Commits.SelectedLine + if selectedLine == -1 { + return nil + } + + return gui.State.Commits[selectedLine] +} + +func (gui *Gui) handleCommitSelect(g *gocui.Gui, v *gocui.View) error { + commit := gui.getSelectedCommit(g) + if commit == nil { + return gui.renderString(g, "main", gui.Tr.SLocalize("NoCommitsThisBranch")) + } + + if err := gui.focusPoint(0, gui.State.Panels.Commits.SelectedLine, v); err != nil { + return err + } + commitText, err := gui.GitCommand.Show(commit.Sha) + if err != nil { + return err + } + return gui.renderString(g, "main", commitText) +} + func (gui *Gui) refreshCommits(g *gocui.Gui) error { g.Update(func(*gocui.Gui) error { commits, err := gui.GitCommand.GetCommits() if err != nil { return err } - gui.State.Commits = commits - v, err := g.View("commits") - if err != nil { - return err - } - v.Clear() + gui.refreshSelectedLine(&gui.State.Panels.Commits.SelectedLine, len(gui.State.Commits)) list, err := utils.RenderList(gui.State.Commits) if err != nil { return err } + + v := gui.getCommitsView(gui.g) + v.Clear() fmt.Fprint(v, list) gui.refreshStatus(g) - if g.CurrentView().Name() == "commits" { + if v == g.CurrentView() { gui.handleCommitSelect(g, v) } return nil @@ -39,11 +64,27 @@ func (gui *Gui) refreshCommits(g *gocui.Gui) error { return nil } +func (gui *Gui) handleCommitsNextLine(g *gocui.Gui, v *gocui.View) error { + panelState := gui.State.Panels.Commits + gui.changeSelectedLine(&panelState.SelectedLine, len(gui.State.Commits), false) + + return gui.handleCommitSelect(gui.g, v) +} + +func (gui *Gui) handleCommitsPrevLine(g *gocui.Gui, v *gocui.View) error { + panelState := gui.State.Panels.Commits + gui.changeSelectedLine(&panelState.SelectedLine, len(gui.State.Commits), true) + + return gui.handleCommitSelect(gui.g, v) +} + +// specific functions + func (gui *Gui) handleResetToCommit(g *gocui.Gui, commitView *gocui.View) error { return gui.createConfirmationPanel(g, commitView, gui.Tr.SLocalize("ResetToCommit"), gui.Tr.SLocalize("SureResetThisCommit"), func(g *gocui.Gui, v *gocui.View) error { - commit, err := gui.getSelectedCommit(g) - if err != nil { - panic(err) + commit := gui.getSelectedCommit(g) + if commit == nil { + panic(errors.New(gui.Tr.SLocalize("NoCommitsThisBranch"))) } if err := gui.GitCommand.ResetToCommit(commit.Sha); err != nil { return gui.createErrorPanel(g, err.Error()) @@ -55,42 +96,21 @@ func (gui *Gui) handleResetToCommit(g *gocui.Gui, commitView *gocui.View) error panic(err) } gui.resetOrigin(commitView) - return gui.handleCommitSelect(g, nil) + gui.State.Panels.Commits.SelectedLine = 0 + return gui.handleCommitSelect(g, commitView) }, nil) } -func (gui *Gui) renderCommitsOptions(g *gocui.Gui) error { - return gui.renderGlobalOptions(g) -} - -func (gui *Gui) handleCommitSelect(g *gocui.Gui, v *gocui.View) error { - if err := gui.renderCommitsOptions(g); err != nil { - return err - } - commit, err := gui.getSelectedCommit(g) - if err != nil { - if err.Error() != gui.Tr.SLocalize("NoCommitsThisBranch") { - return err - } - return gui.renderString(g, "main", gui.Tr.SLocalize("NoCommitsThisBranch")) - } - commitText, err := gui.GitCommand.Show(commit.Sha) - if err != nil { - return err - } - return gui.renderString(g, "main", commitText) -} - func (gui *Gui) handleCommitSquashDown(g *gocui.Gui, v *gocui.View) error { - if gui.getItemPosition(v) != 0 { + if gui.State.Panels.Commits.SelectedLine != 0 { return gui.createErrorPanel(g, gui.Tr.SLocalize("OnlySquashTopmostCommit")) } - if len(gui.State.Commits) == 1 { + if len(gui.State.Commits) <= 1 { return gui.createErrorPanel(g, gui.Tr.SLocalize("YouNoCommitsToSquash")) } - commit, err := gui.getSelectedCommit(g) - if err != nil { - return err + commit := gui.getSelectedCommit(g) + if commit == nil { + return errors.New(gui.Tr.SLocalize("NoCommitsThisBranch")) } if err := gui.GitCommand.SquashPreviousTwoCommits(commit.Name); err != nil { return gui.createErrorPanel(g, err.Error()) @@ -113,16 +133,16 @@ func (gui *Gui) anyUnStagedChanges(files []*commands.File) bool { } func (gui *Gui) handleCommitFixup(g *gocui.Gui, v *gocui.View) error { - if len(gui.State.Commits) == 1 { + if len(gui.State.Commits) <= 1 { return gui.createErrorPanel(g, gui.Tr.SLocalize("YouNoCommitsToSquash")) } if gui.anyUnStagedChanges(gui.State.Files) { return gui.createErrorPanel(g, gui.Tr.SLocalize("CantFixupWhileUnstagedChanges")) } branch := gui.State.Branches[0] - commit, err := gui.getSelectedCommit(g) - if err != nil { - return err + commit := gui.getSelectedCommit(g) + if commit == nil { + return gui.createErrorPanel(g, gui.Tr.SLocalize("NoCommitsThisBranch")) } message := gui.Tr.SLocalize("SureFixupThisCommit") gui.createConfirmationPanel(g, v, gui.Tr.SLocalize("Fixup"), message, func(g *gocui.Gui, v *gocui.View) error { @@ -138,7 +158,7 @@ func (gui *Gui) handleCommitFixup(g *gocui.Gui, v *gocui.View) error { } func (gui *Gui) handleRenameCommit(g *gocui.Gui, v *gocui.View) error { - if gui.getItemPosition(gui.getCommitsView(g)) != 0 { + if gui.State.Panels.Commits.SelectedLine != 0 { return gui.createErrorPanel(g, gui.Tr.SLocalize("OnlyRenameTopCommit")) } return gui.createPromptPanel(g, v, gui.Tr.SLocalize("renameCommit"), func(g *gocui.Gui, v *gocui.View) error { @@ -153,7 +173,7 @@ func (gui *Gui) handleRenameCommit(g *gocui.Gui, v *gocui.View) error { } func (gui *Gui) handleRenameCommitEditor(g *gocui.Gui, v *gocui.View) error { - if gui.getItemPosition(gui.getCommitsView(g)) != 0 { + if gui.State.Panels.Commits.SelectedLine != 0 { return gui.createErrorPanel(g, gui.Tr.SLocalize("OnlyRenameTopCommit")) } @@ -164,19 +184,3 @@ func (gui *Gui) handleRenameCommitEditor(g *gocui.Gui, v *gocui.View) error { return nil } - -func (gui *Gui) getSelectedCommit(g *gocui.Gui) (*commands.Commit, error) { - v, err := g.View("commits") - if err != nil { - panic(err) - } - if len(gui.State.Commits) == 0 { - return &commands.Commit{}, errors.New(gui.Tr.SLocalize("NoCommitsThisBranch")) - } - lineNumber := gui.getItemPosition(v) - if lineNumber > len(gui.State.Commits)-1 { - gui.Log.Info(gui.Tr.SLocalize("PotentialErrInGetselectedCommit"), gui.State.Commits, lineNumber) - return gui.State.Commits[len(gui.State.Commits)-1], nil - } - return gui.State.Commits[lineNumber], nil -} diff --git a/pkg/gui/confirmation_panel.go b/pkg/gui/confirmation_panel.go index 75349777c..521bd827d 100644 --- a/pkg/gui/confirmation_panel.go +++ b/pkg/gui/confirmation_panel.go @@ -28,7 +28,7 @@ func (gui *Gui) wrappedConfirmationFunction(function func(*gocui.Gui, *gocui.Vie func (gui *Gui) closeConfirmationPrompt(g *gocui.Gui) error { view, err := g.View("confirmation") if err != nil { - panic(err) + return nil // if it's already been closed we can just return } if err := gui.returnFocus(g, view); err != nil { panic(err) @@ -77,11 +77,10 @@ func (gui *Gui) prepareConfirmationPanel(currentView *gocui.View, title, prompt confirmationView.Wrap = true confirmationView.FgColor = gocui.ColorWhite } - confirmationView.Clear() - - if err := gui.switchFocus(gui.g, currentView, confirmationView); err != nil { - return nil, err - } + gui.g.Update(func(g *gocui.Gui) error { + confirmationView.Clear() + return gui.switchFocus(gui.g, currentView, confirmationView) + }) return confirmationView, nil } diff --git a/pkg/gui/files_panel.go b/pkg/gui/files_panel.go index cd8df1859..7942e421b 100644 --- a/pkg/gui/files_panel.go +++ b/pkg/gui/files_panel.go @@ -15,6 +15,79 @@ import ( "github.com/jesseduffield/lazygit/pkg/utils" ) +// list panel functions + +func (gui *Gui) getSelectedFile(g *gocui.Gui) (*commands.File, error) { + selectedLine := gui.State.Panels.Files.SelectedLine + if selectedLine == -1 { + return &commands.File{}, gui.Errors.ErrNoFiles + } + + return gui.State.Files[selectedLine], nil +} + +func (gui *Gui) handleFileSelect(g *gocui.Gui, v *gocui.View) error { + file, err := gui.getSelectedFile(g) + if err != nil { + if err != gui.Errors.ErrNoFiles { + return err + } + return gui.renderString(g, "main", gui.Tr.SLocalize("NoChangedFiles")) + } + + if file.HasMergeConflicts { + return gui.refreshMergePanel(g) + } + + if err := gui.focusPoint(0, gui.State.Panels.Files.SelectedLine, v); err != nil { + return err + } + + content := gui.GitCommand.Diff(file, false) + return gui.renderString(g, "main", content) +} + +func (gui *Gui) refreshFiles(g *gocui.Gui) error { + filesView, err := g.View("files") + if err != nil { + return err + } + gui.refreshStateFiles() + + gui.g.Update(func(g *gocui.Gui) error { + + filesView.Clear() + list, err := utils.RenderList(gui.State.Files) + if err != nil { + return err + } + fmt.Fprint(filesView, list) + + if filesView == g.CurrentView() { + return gui.handleFileSelect(g, filesView) + } + return nil + }) + + return nil +} + +func (gui *Gui) handleFilesNextLine(g *gocui.Gui, v *gocui.View) error { + panelState := gui.State.Panels.Files + gui.changeSelectedLine(&panelState.SelectedLine, len(gui.State.Files), false) + + return gui.handleFileSelect(gui.g, v) +} + +func (gui *Gui) handleFilesPrevLine(g *gocui.Gui, v *gocui.View) error { + panelState := gui.State.Panels.Files + gui.changeSelectedLine(&panelState.SelectedLine, len(gui.State.Files), true) + + return gui.handleFileSelect(gui.g, v) +} + +// specific functions + func (gui *Gui) stagedFiles() []*commands.File { files := gui.State.Files result := make([]*commands.File, 0) @@ -139,18 +212,6 @@ func (gui *Gui) handleAddPatch(g *gocui.Gui, v *gocui.View) error { return gui.Errors.ErrSubProcess } -func (gui *Gui) getSelectedFile(g *gocui.Gui) (*commands.File, error) { - if len(gui.State.Files) == 0 { - return &commands.File{}, gui.Errors.ErrNoFiles - } - filesView, err := g.View("files") - if err != nil { - panic(err) - } - lineNumber := gui.getItemPosition(filesView) - return gui.State.Files[lineNumber], nil -} - func (gui *Gui) handleFileRemove(g *gocui.Gui, v *gocui.View) error { file, err := gui.getSelectedFile(g) if err != nil { @@ -194,30 +255,6 @@ func (gui *Gui) handleIgnoreFile(g *gocui.Gui, v *gocui.View) error { return gui.refreshFiles(g) } -func (gui *Gui) renderfilesOptions(g *gocui.Gui, file *commands.File) error { - return gui.renderGlobalOptions(g) -} - -func (gui *Gui) handleFileSelect(g *gocui.Gui, v *gocui.View) error { - file, err := gui.getSelectedFile(g) - if err != nil { - if err != gui.Errors.ErrNoFiles { - return err - } - gui.renderString(g, "main", gui.Tr.SLocalize("NoChangedFiles")) - return gui.renderfilesOptions(g, nil) - } - if err := gui.renderfilesOptions(g, file); err != nil { - return err - } - if file.HasMergeConflicts { - return gui.refreshMergePanel(g) - } - - content := gui.GitCommand.Diff(file, false) - return gui.renderString(g, "main", content) -} - func (gui *Gui) handleCommitPress(g *gocui.Gui, filesView *gocui.View) error { if len(gui.stagedFiles()) == 0 && !gui.State.HasMergeConflicts { return gui.createErrorPanel(g, gui.Tr.SLocalize("NoStagedFilesToCommit")) @@ -309,6 +346,7 @@ func (gui *Gui) refreshStateFiles() { // get files to stage files := gui.GitCommand.GetStatusFiles() gui.State.Files = gui.GitCommand.MergeStatusFiles(gui.State.File |