diff options
Diffstat (limited to 'pkg')
-rw-r--r-- | pkg/commands/git.go | 68 | ||||
-rw-r--r-- | pkg/commands/git_test.go | 77 | ||||
-rw-r--r-- | pkg/gui/branches_panel.go | 54 | ||||
-rw-r--r-- | pkg/gui/commit_files_panel.go | 12 | ||||
-rw-r--r-- | pkg/gui/commits_panel.go | 17 | ||||
-rw-r--r-- | pkg/gui/files_panel.go | 43 | ||||
-rw-r--r-- | pkg/gui/gui.go | 80 | ||||
-rw-r--r-- | pkg/gui/merge_panel.go | 2 | ||||
-rw-r--r-- | pkg/gui/reflog_panel.go | 13 | ||||
-rw-r--r-- | pkg/gui/remote_branches_panel.go | 20 | ||||
-rw-r--r-- | pkg/gui/remotes_panel.go | 4 | ||||
-rw-r--r-- | pkg/gui/stash_panel.go | 15 | ||||
-rw-r--r-- | pkg/gui/status_panel.go | 2 | ||||
-rw-r--r-- | pkg/gui/tags_panel.go | 23 | ||||
-rw-r--r-- | pkg/gui/tasks_adapter.go | 78 | ||||
-rw-r--r-- | pkg/tasks/tasks.go | 226 |
16 files changed, 490 insertions, 244 deletions
diff --git a/pkg/commands/git.go b/pkg/commands/git.go index f72280d64..fb4ddab79 100644 --- a/pkg/commands/git.go +++ b/pkg/commands/git.go @@ -176,8 +176,8 @@ func stashEntryFromLine(line string, index int) *StashEntry { } // GetStashEntryDiff stash diff -func (c *GitCommand) GetStashEntryDiff(index int) (string, error) { - return c.OSCommand.RunCommandWithOutput("git stash show -p --color stash@{%d}", index) +func (c *GitCommand) ShowStashEntryCmdStr(index int) string { + return fmt.Sprintf("git stash show -p --color stash@{%d}", index) } // GetStatusFiles git status files @@ -538,7 +538,8 @@ func (c *GitCommand) PrepareCommitAmendSubProcess() *exec.Cmd { // Currently it limits the result to 100 commits, but when we get async stuff // working we can do lazy loading func (c *GitCommand) GetBranchGraph(branchName string) (string, error) { - return c.OSCommand.RunCommandWithOutput("git log --graph --color --abbrev-commit --decorate --date=relative --pretty=medium -100 %s", branchName) + cmdStr := c.GetBranchGraphCmdStr(branchName) + return c.OSCommand.RunCommandWithOutput(cmdStr) } func (c *GitCommand) GetUpstreamForBranch(branchName string) (string, error) { @@ -551,41 +552,12 @@ func (c *GitCommand) Ignore(filename string) error { return c.OSCommand.AppendLineToFile(".gitignore", filename) } -// Show shows the diff of a commit -func (c *GitCommand) Show(sha string) (string, error) { - show, err := c.OSCommand.RunCommandWithOutput("git show --color --no-renames %s", sha) - if err != nil { - return "", err - } - - // if this is a merge commit, we need to go a step further and get the diff between the two branches we merged - revList, err := c.OSCommand.RunCommandWithOutput("git rev-list -1 --merges %s^...%s", sha, sha) - if err != nil { - // turns out we get an error here when it's the first commit. We'll just return the original show - return show, nil - } - if len(revList) == 0 { - return show, nil - } - - // we want to pull out 1a6a69a and 3b51d7c from this: - // commit ccc771d8b13d5b0d4635db4463556366470fd4f6 - // Merge: 1a6a69a 3b51d7c - lines := utils.SplitLines(show) - if len(lines) < 2 { - return show, nil - } - - secondLineWords := strings.Split(lines[1], " ") - if len(secondLineWords) < 3 { - return show, nil - } +func (c *GitCommand) ShowCmdStr(sha string) string { + return fmt.Sprintf("git show --color --no-renames %s", sha) +} - mergeDiff, err := c.OSCommand.RunCommandWithOutput("git diff --color %s...%s", secondLineWords[1], secondLineWords[2]) - if err != nil { - return "", err - } - return show + mergeDiff, nil +func (c *GitCommand) GetBranchGraphCmdStr(branchName string) string { + return fmt.Sprintf("git log --graph --color --abbrev-commit --decorate --date=relative --pretty=medium %s", branchName) } // GetRemoteURL returns current repo remote url @@ -606,6 +578,12 @@ func (c *GitCommand) CheckRemoteBranchExists(branch *Branch) bool { // Diff returns the diff of a file func (c *GitCommand) Diff(file *File, plain bool, cached bool) string { + // for now we assume an error means the file was deleted + s, _ := c.OSCommand.RunCommandWithOutput(c.DiffCmdStr(file, plain, cached)) + return s +} + +func (c *GitCommand) DiffCmdStr(file *File, plain bool, cached bool) string { cachedArg := "" trackedArg := "--" colorArg := "--color" @@ -621,9 +599,7 @@ func (c *GitCommand) Diff(file *File, plain bool, cached bool) string { colorArg = "" } - // for now we assume an error means the file was deleted - s, _ := c.OSCommand.RunCommandWithOutput("git diff %s %s %s %s", colorArg, cachedArg, trackedArg, fileName) - return s + return fmt.Sprintf("git diff %s %s %s %s", colorArg, cachedArg, trackedArg, fileName) } func (c *GitCommand) ApplyPatch(patch string, flags ...string) error { @@ -908,11 +884,17 @@ func (c *GitCommand) GetCommitFiles(commitSha string, patchManager *PatchManager // ShowCommitFile get the diff of specified commit file func (c *GitCommand) ShowCommitFile(commitSha, fileName string, plain bool) (string, error) { + cmdStr := c.ShowCommitFileCmdStr(commitSha, fileName, plain) + return c.OSCommand.RunCommandWithOutput(cmdStr) +} + +func (c *GitCommand) ShowCommitFileCmdStr(commitSha, fileName string, plain bool) string { colorArg := "--color" if plain { colorArg = "" } - return c.OSCommand.RunCommandWithOutput("git show --no-renames %s %s -- %s", colorArg, commitSha, fileName) + + return fmt.Sprintf("git show --no-renames %s %s -- %s", colorArg, commitSha, fileName) } // CheckoutFile checks out the file for the given commit @@ -1098,10 +1080,6 @@ func (c *GitCommand) CreateLightweightTag(tagName string, commitSha string) erro return c.OSCommand.RunCommand("git tag %s %s", tagName, commitSha) } -func (c *GitCommand) ShowTag(tagName string) (string, error) { - return c.OSCommand.RunCommandWithOutput("git tag -n99 %s", tagName) -} - func (c *GitCommand) DeleteTag(tagName string) error { return c.OSCommand.RunCommand("git tag -d %s", tagName) } diff --git a/pkg/commands/git_test.go b/pkg/commands/git_test.go index 0429165de..ceaadc576 100644 --- a/pkg/commands/git_test.go +++ b/pkg/commands/git_test.go @@ -318,21 +318,6 @@ func TestGitCommandGetStashEntries(t *testing.T) { } } -// TestGitCommandGetStashEntryDiff is a function. -func TestGitCommandGetStashEntryDiff(t *testing.T) { - gitCmd := NewDummyGitCommand() - gitCmd.OSCommand.command = func(cmd string, args ...string) *exec.Cmd { - assert.EqualValues(t, "git", cmd) - assert.EqualValues(t, []string{"stash", "show", "-p", "--color", "stash@{1}"}, args) - - return exec.Command("echo") - } - - _, err := gitCmd.GetStashEntryDiff(1) - - assert.NoError(t, err) -} - // TestGitCommandGetStatusFiles is a function. func TestGitCommandGetStatusFiles(t *testing.T) { type scenario struct { @@ -1411,66 +1396,6 @@ func TestGitCommandDiscardAllFileChanges(t *testing.T) { } } -// TestGitCommandShow is a function. -func TestGitCommandShow(t *testing.T) { - type scenario struct { - testName string - arg string - command func(string, ...string) *exec.Cmd - test func(string, error) - } - - scenarios := []scenario{ - { - "regular commit", - "456abcde", - test.CreateMockCommand(t, []*test.CommandSwapper{ - { - Expect: "git show --color --no-renames 456abcde", - Replace: "echo \"commit ccc771d8b13d5b0d4635db4463556366470fd4f6\nblah\"", - }, - { - Expect: "git rev-list -1 --merges 456abcde^...456abcde", - Replace: "echo", - }, - }), - func(result string, err error) { - assert.NoError(t, err) - assert.Equal(t, "commit ccc771d8b13d5b0d4635db4463556366470fd4f6\nblah\n", result) - }, - }, - { - "merge commit", - "456abcde", - test.CreateMockCommand(t, []*test.CommandSwapper{ - { - Expect: "git show --color --no-renames 456abcde", - Replace: "echo \"commit ccc771d8b13d5b0d4635db4463556366470fd4f6\nMerge: 1a6a69a 3b51d7c\"", - }, - { - Expect: "git rev-list -1 --merges 456abcde^...456abcde", - Replace: "echo aa30e006433628ba9281652952b34d8aacda9c01", - }, - { - Expect: "git diff --color 1a6a69a...3b51d7c", - Replace: "echo blah", - }, - }), - func(result string, err error) { - assert.NoError(t, err) - assert.Equal(t, "commit ccc771d8b13d5b0d4635db4463556366470fd4f6\nMerge: 1a6a69a 3b51d7c\nblah\n", result) - }, - }, - } - - gitCmd := NewDummyGitCommand() - - for _, s := range scenarios { - gitCmd.OSCommand.command = s.command - s.test(gitCmd.Show(s.arg)) - } -} - // TestGitCommandCheckout is a function. func TestGitCommandCheckout(t *testing.T) { type scenario struct { @@ -1523,7 +1448,7 @@ func TestGitCommandGetBranchGraph(t *testing.T) { gitCmd := NewDummyGitCommand() gitCmd.OSCommand.command = func(cmd string, args ...string) *exec.Cmd { assert.EqualValues(t, "git", cmd) - assert.EqualValues(t, []string{"log", "--graph", "--color", "--abbrev-commit", "--decorate", "--date=relative", "--pretty=medium", "-100", "test"}, args) + assert.EqualValues(t, []string{"log", "--graph", "--color", "--abbrev-commit", "--decorate", "--date=relative", "--pretty=medium", "test"}, args) return exec.Command("echo") } diff --git a/pkg/gui/branches_panel.go b/pkg/gui/branches_panel.go index 1bf408026..ff77c9cb4 100644 --- a/pkg/gui/branches_panel.go +++ b/pkg/gui/branches_panel.go @@ -4,7 +4,6 @@ import ( "fmt" "strings" - "github.com/fatih/color" "github.com/jesseduffield/gocui" "github.com/jesseduffield/lazygit/pkg/commands" "github.com/jesseduffield/lazygit/pkg/utils" @@ -37,40 +36,45 @@ 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")) + return gui.newStringTask("main", gui.Tr.SLocalize("NoBranchesThisRepo")) } branch := gui.getSelectedBranch() if err := gui.focusPoint(0, gui.State.Panels.Branches.SelectedLine, len(gui.State.Branches), v); err != nil { return err } - go func() { - _ = gui.RenderSelectedBranchUpstreamDifferences() - }() - go func() { - upstream, _ := gui.GitCommand.GetUpstreamForBranch(branch.Name) - if strings.Contains(upstream, "no upstream configured for branch") || strings.Contains(upstream, "unknown revision or path not in the working tree") { - upstream = gui.Tr.SLocalize("notTrackingRemote") - } - 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", fmt.Sprintf("%s → %s\n\n%s", utils.ColoredString(branch.Name, color.FgGreen), utils.ColoredString(upstream, color.FgRed), graph)) - }() + if err := gui.RenderSelectedBranchUpstreamDifferences(); err != nil { + return err + } + + cmd := gui.OSCommand.ExecutableFromString( + gui.GitCommand.GetBranchGraphCmdStr(branch.Name), + ) + if err := gui.newCmdTask("main", cmd); err != nil { + gui.Log.Error(err) + } 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 - } + return gui.newTask("branches", func(stop chan struct{}) 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.State.Branches) + branch := gui.getSelectedBranch() + branch.Pushables, branch.Pullables = gui.GitCommand.GetBranchUpstreamDifferenceCount(branch.Name) + + select { + case <-stop: + return nil + default: + } + + return gui.renderListPanel(gui.getBranchesView(), gui.State.Branches) + }) } // gui.refreshStatus is called at the end of this because that's when we can diff --git a/pkg/gui/commit_files_panel.go b/pkg/gui/commit_files_panel.go index 1dee4a3cd..42afc6c94 100644 --- a/pkg/gui/commit_files_panel.go +++ b/pkg/gui/commit_files_panel.go @@ -43,11 +43,15 @@ func (gui *Gui) handleCommitFileSelect(g *gocui.Gui, v *gocui.View) error { if err := gui.focusPoint(0, gui.State.Panels.CommitFiles.SelectedLine, len(gui.State.CommitFiles), v); err != nil { return err } - commitText, err := gui.GitCommand.ShowCommitFile(commitFile.Sha, commitFile.Name, false) - if err != nil { - return err + + cmd := gui.OSCommand.ExecutableFromString( + gui.GitCommand.ShowCommitFileCmdStr(commitFile.Sha, commitFile.Name, false), + ) + if err := gui.newCmdTask("main", cmd); err != nil { + gui.Log.Error(err) } - return gui.renderString(g, "main", commitText) + + return nil } func (gui *Gui) handleSwitchToCommitsPanel(g *gocui.Gui, v *gocui.View) error { diff --git a/pkg/gui/commits_panel.go b/pkg/gui/commits_panel.go index 32672a40b..abc6b47ec 100644 --- a/pkg/gui/commits_panel.go +++ b/pkg/gui/commits_panel.go @@ -53,7 +53,7 @@ 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")) + return gui.newStringTask("main", gui.Tr.SLocalize("NoCommitsThisBranch")) } if err := gui.focusPoint(0, gui.State.Panels.Commits.SelectedLine, len(gui.State.Commits), v); err != nil { @@ -65,11 +65,14 @@ func (gui *Gui) handleCommitSelect(g *gocui.Gui, v *gocui.View) error { return nil } - commitText, err := gui.GitCommand.Show(commit.Sha) - if err != nil { - return err + cmd := gui.OSCommand.ExecutableFromString( + gui.GitCommand.ShowCmdStr(commit.Sha), + ) + if err := gui.newCmdTask("main", cmd); err != nil { + gui.Log.Error(err) } - return gui.renderString(g, "main", commitText) + + return nil } func (gui *Gui) refreshCommits(g *gocui.Gui) error { @@ -463,7 +466,7 @@ func (gui *Gui) handleToggleDiffCommit(g *gocui.Gui, v *gocui.View) error { // get selected commit commit := gui.getSelectedCommit(g) if commit == nil { - return gui.renderString(g, "main", gui.Tr.SLocalize("NoCommitsThisBranch")) + return gui.newStringTask("main", gui.Tr.SLocalize("NoCommitsThisBranch")) } // if already selected commit delete @@ -486,7 +489,7 @@ func (gui *Gui) handleToggleDiffCommit(g *gocui.Gui, v *gocui.View) error { return gui.createErrorPanel(gui.g, err.Error()) } - return gui.renderString(g, "main", commitText) + return gui.newStringTask("main", commitText) } return nil diff --git a/pkg/gui/files_panel.go b/pkg/gui/files_panel.go index 38622efa1..47e7bae1f 100644 --- a/pkg/gui/files_panel.go +++ b/pkg/gui/files_panel.go @@ -32,7 +32,7 @@ func (gui *Gui) selectFile(alreadySelected bool) error { if err != gui.Errors.ErrNoFiles { return err } - return gui.renderString(gui.g, "main", gui.Tr.SLocalize("NoChangedFiles")) + return gui.newStringTask("main", gui.Tr.SLocalize("NoChangedFiles")) } if err := gui.focusPoint(0, gui.State.Panels.Files.SelectedLine, len(gui.State.Files), gui.getFilesView()); err != nil { @@ -45,37 +45,40 @@ func (gui *Gui) selectFile(alreadySelected bool) error { return gui.refreshMergePanel() } - content := gui.GitCommand.Diff(file, false, false) - contentCached := gui.GitCommand.Diff(file, false, true) - leftContent := content + if !alreadySelected { + if err := gui.resetOrigin(gui.getMainView()); err != nil { + return err + } + if err := gui.resetOrigin(gui.getSecondaryView()); err != nil { + return err + } + } + if file.HasStagedChanges && file.HasUnstagedChanges { gui.State.SplitMainPanel = true gui.getMainView().Title = gui.Tr.SLocalize("UnstagedChanges") gui.getSecondaryView().Title = gui.Tr.SLocalize("StagedChanges") + cmdStr := gui.GitCommand.DiffCmdStr(file, false, true) + cmd := gui.OSCommand.ExecutableFromString(cmdStr) + if err := gui.newCmdTask("secondary", cmd); err != nil { + return err + } } else { gui.State.SplitMainPanel = false if file.HasUnstagedChanges { - leftContent = content gui.getMainView().Title = gui.Tr.SLocalize("UnstagedChanges") } else { - leftContent = contentCached gui.getMainView().Title = gui.Tr.SLocalize("StagedChanges") } } - if alreadySelected { - gui.g.Update(func(*gocui.Gui) error { - if err := gui.setViewContent(gui.g, gui.getSecondaryView(), contentCached); err != nil { - return err - } - return gui.setViewContent(gui.g, gui.getMainView(), leftContent) - }) - return nil - } - if err := gui.renderString(gui.g, "secondary", contentCached); err != nil { + cmdStr := gui.GitCommand.DiffCmdStr(file, false, !file.HasUnstagedChanges && file.HasStagedChanges) + cmd := gui.OSCommand.ExecutableFromString(cmdStr) + if err := gui.newCmdTask("main", cmd); err != nil { return err } - return gui.renderString(gui.g, "main", leftContent) + + return nil } func (gui *Gui) refreshFiles() error { @@ -369,15 +372,15 @@ func (gui *Gui) catSelectedFile(g *gocui.Gui) (string, error) { if err != gui.Errors.ErrNoFiles { return "", err } - return "", gui.renderString(g, "main", gui.Tr.SLocalize("NoFilesDisplay")) + return "", gui.newStringTask("main", gui.Tr.SLocalize("NoFilesDisplay")) } if item.Type != "file" { - return "", gui.renderString(g, "main", gui.Tr.SLocalize("NotAFile")) + return "", gui.newStringTask("main", gui.Tr.SLocalize("NotAFile")) } cat, err := gui.GitCommand.CatFile(item.Name) if err != nil { gui.Log.Error(err) - return "", gui.renderString(g, "main", err.Error()) + return "", gui.newStringTask("main", err.Error()) } return cat, nil } diff --git a/pkg/gui/gui.go b/pkg/gui/gui.go index 2bdb66e0f..d748b4d72 100644 --- a/pkg/gui/gui.go +++ b/pkg/gui/gui.go @@ -25,6 +25,7 @@ import ( "github.com/jesseduffield/lazygit/pkg/commands" "github.com/jesseduffield/lazygit/pkg/config" "github.com/jesseduffield/lazygit/pkg/i18n" + "github.com/jesseduffield/lazygit/pkg/tasks" "github.com/jesseduffield/lazygit/pkg/theme" "github.com/jesseduffield/lazygit/pkg/updates" "github.com/jesseduffield/lazygit/pkg/utils" @@ -68,20 +69,21 @@ type Teml i18n.Teml // Gui wraps the gocui Gui object which handles rendering and events type Gui struct { - g *gocui.Gui - Log *logrus.Entry - GitCommand *commands.GitCommand - OSCommand *commands.OSCommand - SubProcess *exec.Cmd - State guiState - Config config.AppConfigurer - Tr *i18n.Localizer - Errors SentinelErrors - Updater *updates.Updater - statusManager *statusManager - credentials credentials - waitForIntro sync.WaitGroup - fileWatcher *fileWatcher + g *gocui.Gui + Log *logrus.Entry + GitCommand *commands.GitCommand + OSCommand *commands.OSCommand + SubProcess *exec.Cmd + State guiState + Config config.AppConfigurer + Tr *i18n.Localizer + Errors SentinelErrors + Updater *updates.Updater + statusManager *statusManager + credentials credentials + waitForIntro sync.WaitGroup + fileWatcher *fileWatcher + viewBufferManagerMap map[string]*tasks.ViewBufferManager } // for now the staging panel state, unlike the other panel states, is going to be @@ -229,14 +231,15 @@ func NewGui(log *logrus.Entry, gitCommand *commands.GitCommand, oSCommand *comma } gui := &Gui{ - Log: log, - GitCommand: gitCommand, - OSCommand: oSCommand, - State: initialState, - Config: config, - Tr: tr, - Updater: updater, - statusManager: &statusManager{}, + Log: log, + GitCommand: gitCommand, + OSCommand: oSCommand, + State: initialState, + Config: config, + Tr: tr, + Updater: updater, + statusManager: &statusManager{}, + viewBufferManagerMap: map[string]*tasks.ViewBufferManager{}, } gui.watchFilesForChanges() @@ -261,8 +264,14 @@ func (gui *Gui) scrollDownView(viewName string) error { _, sy := mainView.Size() y += sy } + scrollHeight := gui.Config.GetUserConfig().GetInt("gui.scrollHeight") if y < len(mainView.BufferLines()) { - return mainView.SetOrigin(ox, oy+gui.Config.GetUserConfig().GetInt("gui.scrollHeight")) + if err := mainView.SetOrigin(ox, oy+scrollHeight); err != nil { + return err + } + } + if manager, ok := gui.viewBufferManagerMap[viewName]; ok { + manager.ReadLines(scrollHeight) } return nil } @@ -465,7 +474,23 @@ func (gui *Gui) layout(g *gocui.Gui) error { secondary = "main" } - v, err := g.SetView(main, leftSideWidth+panelSpacing, 0, panelSplitX, height-2, gocui.LEFT) + // reading more lines into main view buffers upon resize + mainHeight := height - 2 + prevMainView, err := gui.g.View("main") + if err == nil { + _, prevMainHeight := prevMainView.Size() + heightDiff := mainHeight - 1 - prevMainHeight + if heightDiff > 0 { + if manager, ok := gui.viewBufferManagerMap["main"]; ok { + manager.ReadLines(heightDiff) + } + if manager, ok := gui.viewBufferManagerMap["secondary"]; ok { + manager.ReadLines(heightDiff) + } + } + } + + v, err := g.SetView(main, leftSideWidth+panelSpacing, 0, panelSplitX, mainHeight, gocui.LEFT) if err != nil { if err.Error() != "unknown view" { return err @@ -479,7 +504,7 @@ func (gui *Gui) layout(g *gocui.Gui) error { if !gui.State.SplitMainPanel { hiddenViewOffset = 9999 } - secondaryView, err := g.SetView(secondary, panelSplitX+1+hiddenViewOffset, hiddenViewOffset, width-1+hiddenViewOffset, height-2+hiddenViewOffset, gocui.LEFT) + secondaryView, err := g.SetView(secondary, panelSplitX+1+hiddenViewOffset, hiddenViewOffset, width-1+hiddenViewOffset, mainHeight+hiddenViewOffset, gocui.LEFT) if err != nil { if err.Error() != "unknown view" { return err @@ -843,6 +868,11 @@ func (gui *Gui) Run() error { func (gui *Gui) RunWithSubprocesses() error { for { if err := gui.Run(); err != nil { + for _, manager := range gui.viewBufferManagerMap { + manager.Close() + } + gui.viewBufferManagerMap = map[string]*tasks.ViewBufferManager{} + if err == gocui.ErrQuit { if !gui.State.RetainOriginalDir { if err := gui.recordCurrentDirectory(); err != nil { diff --git a/pkg/gui/merge_panel.go b/pkg/gui/merge_panel.go index 25238ce4f..4b86cf6c0 100644 --- a/pkg/gui/merge_panel.go +++ b/pkg/gui/merge_panel.go @@ -212,7 +212,7 @@ func (gui *Gui) refreshMergePanel() error { if err != nil { return err } - if err := gui.renderString(gui.g, "main", content); err != nil { + if err := gui.newStringTask("main", content); err != nil { return err } if err := gui.scrollToConflict(gui.g); err != nil { diff --git a/pkg/gui/reflog_panel.go b/pkg/gui/reflog_panel.go index 33577c073..e766070fb 100644 --- a/pkg/gui/reflog_panel.go +++ b/pkg/gui/reflog_panel.go @@ -31,17 +31,20 @@ func (gui *Gui) handleReflogCommitSelect(g *gocui.Gui, v *gocui.View) error { commit := gui.getSelectedReflogCommit() if commit == nil { - return gui.renderString(g, "main", "No reflog history") + return gui.newStringTask("main", "No reflog history") } if err := gui.focusPoint(0, gui.State.Panels.ReflogCommits.SelectedLine, len(gui.State.ReflogCommits), v); err != nil { return err } - commitText, err := gui.GitCommand.Show(commit.Sha) - if err != nil { - return err + cmd := gui.OSCommand.ExecutableFromString( + gui.GitCommand.ShowCmdStr(commit.Sha), + ) + if err := gui.newCmdTask("main", cmd); err != nil { + gui.Log.Error(err) } - return gui.renderString(g, "main", commitText) + + return nil } func (gui *Gui) refreshReflogCommits() error { diff --git a/pkg/gui/remote_branches_panel.go b/pkg/gui/remote_branches_panel.go index 4b8658df7..fbe299fd9 100644 --- a/pkg/gui/remote_branches_panel.go +++ b/pkg/gui/remote_branches_panel.go @@ -2,12 +2,9 @@ package gui import ( "fmt" - "strings" - "github.com/fatih/color" "github.com/jesseduffield/gocui" "github.com/jesseduffield/lazygit/pkg/commands" - "github.com/jesseduffield/lazygit/pkg/utils" ) // list panel functions @@ -37,7 +34,7 @@ func (gui *Gui) handleRemoteBranchSelect(g *gocui.Gui, v *gocui.View) error { remote := gui.getSelectedRemote() remoteBranch := gui.getSelectedRemoteBranch() if remoteBranch == nil { - return gui.renderString(g, "main", "No branches for this remote") + return gui.newStringTask("main", "No branches for this remote") } gui.focusPoint(0, gui.State.Panels.Menu.SelectedLine, gui.State.MenuItemCount, v) @@ -45,13 +42,14 @@ func (gui *Gui) handleRemoteBranchSelect(g *gocui.Gui, v *gocui.View) error { return err } - go func() { - graph, err := gui.GitCommand.GetBranchGraph(fmt.Sprintf("%s/%s", remote.Name, remoteBranch.Name)) - if err != nil && strings.HasPrefix(graph, "fatal: ambiguous argument") { - graph = gui.Tr.SLocalize("NoTrackingThisBranch") - } - _ = gui.renderString(g, "main", fmt.Sprintf("%s/%s\n\n%s", utils.ColoredString(remote.Name, color.FgRed), utils.ColoredString(remoteBranch.Name, color.FgGreen), graph)) - }() + branchName := fmt.Sprintf("%s/%s", remote.Name, remoteBranch.Name) + + cmd := gui.OSCommand.ExecutableFromString( + gui.GitCommand.GetBranchGraphCmdStr(branchName), + ) + if err := gui.newCmdTask("main", cmd); err != nil { + gui.Log.Error(err) + } return nil } diff --git a/pkg/gui/remotes_panel.go b/pkg/gui/remotes_panel.go index a646462d9..ca3e3aae1 100644 --- a/pkg/gui/remotes_panel.go +++ b/pkg/gui/remotes_panel.go @@ -36,13 +36,13 @@ func (gui *Gui) handleRemoteSelect(g *gocui.Gui, v *gocui.View) error { remote := gui.getSelectedRemote() if remote == nil { - return gui.renderString(g, "main", "No remotes") + return gui.newStringTask("main", "No remotes") } if err := gui.focusPoint(0, gui.State.Panels.Remotes.SelectedLine, len(gui.State.Remotes), v); err != nil { return err } - return gui.renderString(g, "main", fmt.Sprintf("%s\nUrls:\n%s", utils.ColoredString(remote.Name, color.FgGreen), strings.Join(remote.Urls, "\n"))) + return gui.newStringTask("main", fmt.Sprintf("%s\nUrls:\n%s", utils.ColoredString(remote.Name, color.FgGreen), strings.Join(remote.Urls, "\n"))) } func (gui *Gui) refreshRemotes() error { diff --git a/pkg/gui/stash_panel.go b/pkg/gui/stash_panel.go index 8ccdc9880..23ecaba60 100644 --- a/pkg/gui/stash_panel.go +++ b/pkg/gui/stash_panel.go @@ -34,16 +34,19 @@ func (gui *Gui) handleStashEntrySelect(g *gocui.Gui, v *gocui.View) error { stashEntry := gui.getSelectedStashEntry(v) if stashEntry == nil { - return gui.renderString(g, "main", gui.Tr.SLocalize("NoStashEntries")) + return gui.newStringTask("main", gui.Tr.SLocalize("NoStashEntries")) } if err := gui.focusPoint(0, gui.State.Panels.Stash.SelectedLine, len(gui.State.StashEntries), v); err != nil { return err } - go func() { - // doing this asynchronously cos it can take time - diff, _ := gui.GitCommand.GetStashEntryDiff(stashEntry.Index) - _ = gui.renderString(g, "main", diff) - }() + + cmd := gui.OSCommand.ExecutableFromString( + gui.GitCommand.ShowStashEntryCmdStr(stashEntry.Index), + ) + if err := gui.newCmdTask("main", cmd); err != nil { + gui.Log.Error(err) + } + return nil } diff --git a/pkg/gui/status_panel.go b/pkg/gui/status_panel.go index c351f24e8..8eb6a92f9 100644 --- a/pkg/gui/status_panel.go +++ b/pkg/gui/status_panel.go @@ -111,7 +111,7 @@ func (gui *Gui) handleStatusSelect(g *gocui.Gui, v *gocui.View) error { magenta.Sprint("Become a sponsor (github is matching all donations for 12 months): https://github.com/sponsors/jesseduffield"), // caffeine ain't free }, "\n\n") - return gui.renderString(g, "mai |