1
0
mirror of https://github.com/jesseduffield/lazygit.git synced 2025-06-17 00:18:05 +02:00

use go-errors package to display stacktrace of errors that cause panics

This commit is contained in:
Jesse Duffield
2019-02-11 21:30:27 +11:00
parent 3a607061a2
commit cfe3605e6b
13 changed files with 55 additions and 37 deletions

View File

@ -5,7 +5,7 @@ package commands
import ( import (
"bufio" "bufio"
"bytes" "bytes"
"errors" "github.com/go-errors/errors"
"os" "os"
"os/exec" "os/exec"
"strings" "strings"

View File

@ -1,12 +1,13 @@
package commands package commands
import ( import (
"errors"
"fmt" "fmt"
"os" "os"
"os/exec" "os/exec"
"strings" "strings"
"github.com/go-errors/errors"
"github.com/jesseduffield/lazygit/pkg/i18n" "github.com/jesseduffield/lazygit/pkg/i18n"
"github.com/jesseduffield/lazygit/pkg/utils" "github.com/jesseduffield/lazygit/pkg/utils"
"github.com/sirupsen/logrus" "github.com/sirupsen/logrus"
@ -27,11 +28,11 @@ func navigateToRepoRootDirectory(stat func(string) (os.FileInfo, error), chdir f
} }
if !os.IsNotExist(err) { if !os.IsNotExist(err) {
return err return errors.Wrap(err, 0)
} }
if err = chdir(".."); err != nil { if err = chdir(".."); err != nil {
return err return errors.Wrap(err, 0)
} }
} }
} }

View File

@ -1,13 +1,14 @@
package commands package commands
import ( import (
"errors"
"io/ioutil" "io/ioutil"
"os" "os"
"os/exec" "os/exec"
"regexp" "regexp"
"strings" "strings"
"github.com/go-errors/errors"
"github.com/jesseduffield/lazygit/pkg/config" "github.com/jesseduffield/lazygit/pkg/config"
"github.com/jesseduffield/lazygit/pkg/utils" "github.com/jesseduffield/lazygit/pkg/utils"
"github.com/mgutz/str" "github.com/mgutz/str"
@ -122,7 +123,7 @@ func sanitisedCommandOutput(output []byte, err error) (string, error) {
// errors like 'exit status 1' are not very useful so we'll create an error // errors like 'exit status 1' are not very useful so we'll create an error
// from the combined output // from the combined output
if outputString == "" { if outputString == "" {
return "", err return "", errors.Wrap(err, 0)
} }
return outputString, errors.New(outputString) return outputString, errors.New(outputString)
} }
@ -201,12 +202,12 @@ func (c *OSCommand) Unquote(message string) string {
func (c *OSCommand) AppendLineToFile(filename, line string) error { func (c *OSCommand) AppendLineToFile(filename, line string) error {
f, err := os.OpenFile(filename, os.O_APPEND|os.O_WRONLY|os.O_CREATE, 0600) f, err := os.OpenFile(filename, os.O_APPEND|os.O_WRONLY|os.O_CREATE, 0600)
if err != nil { if err != nil {
return err return errors.Wrap(err, 0)
} }
defer f.Close() defer f.Close()
_, err = f.WriteString("\n" + line) _, err = f.WriteString("\n" + line)
return err return errors.Wrap(err, 0)
} }
// CreateTempFile writes a string to a new temp file and returns the file's name // CreateTempFile writes a string to a new temp file and returns the file's name
@ -214,16 +215,16 @@ func (c *OSCommand) CreateTempFile(filename, content string) (string, error) {
tmpfile, err := ioutil.TempFile("", filename) tmpfile, err := ioutil.TempFile("", filename)
if err != nil { if err != nil {
c.Log.Error(err) c.Log.Error(err)
return "", err return "", errors.Wrap(err, 0)
} }
if _, err := tmpfile.WriteString(content); err != nil { if _, err := tmpfile.WriteString(content); err != nil {
c.Log.Error(err) c.Log.Error(err)
return "", err return "", errors.Wrap(err, 0)
} }
if err := tmpfile.Close(); err != nil { if err := tmpfile.Close(); err != nil {
c.Log.Error(err) c.Log.Error(err)
return "", err return "", errors.Wrap(err, 0)
} }
return tmpfile.Name(), nil return tmpfile.Name(), nil
@ -231,5 +232,6 @@ func (c *OSCommand) CreateTempFile(filename, content string) (string, error) {
// RemoveFile removes a file at the specified path // RemoveFile removes a file at the specified path
func (c *OSCommand) RemoveFile(filename string) error { func (c *OSCommand) RemoveFile(filename string) error {
return os.Remove(filename) err := os.Remove(filename)
return errors.Wrap(err, 0)
} }

View File

@ -1,9 +1,10 @@
package commands package commands
import ( import (
"errors"
"fmt" "fmt"
"strings" "strings"
"github.com/go-errors/errors"
) )
// Service is a service that repository is on (Github, Bitbucket, ...) // Service is a service that repository is on (Github, Bitbucket, ...)

View File

@ -1,11 +1,12 @@
package git package git
import ( import (
"errors"
"regexp" "regexp"
"strconv" "strconv"
"strings" "strings"
"github.com/go-errors/errors"
"github.com/jesseduffield/lazygit/pkg/i18n" "github.com/jesseduffield/lazygit/pkg/i18n"
"github.com/jesseduffield/lazygit/pkg/utils" "github.com/jesseduffield/lazygit/pkg/utils"
"github.com/sirupsen/logrus" "github.com/sirupsen/logrus"

View File

@ -1,9 +1,10 @@
package gui package gui
import ( import (
"errors"
"fmt" "fmt"
"github.com/go-errors/errors"
"github.com/jesseduffield/gocui" "github.com/jesseduffield/gocui"
"github.com/jesseduffield/lazygit/pkg/commands" "github.com/jesseduffield/lazygit/pkg/commands"
"github.com/jesseduffield/lazygit/pkg/utils" "github.com/jesseduffield/lazygit/pkg/utils"

View File

@ -6,7 +6,6 @@ import (
// "io" // "io"
// "io/ioutil" // "io/ioutil"
"errors"
"io/ioutil" "io/ioutil"
"log" "log"
"os" "os"
@ -14,6 +13,8 @@ import (
"strings" "strings"
"time" "time"
"github.com/go-errors/errors"
// "strings" // "strings"
"github.com/fatih/color" "github.com/fatih/color"
@ -568,7 +569,9 @@ func (gui *Gui) RunWithSubprocesses() {
gui.SubProcess.Stdin = nil gui.SubProcess.Stdin = nil
gui.SubProcess = nil gui.SubProcess = nil
} else { } else {
log.Panicln(err) newErr := errors.Wrap(err, 0)
stackTrace := newErr.ErrorStack()
log.Panicln(stackTrace)
} }
} }
} }

View File

@ -1,7 +1,7 @@
package gui package gui
import ( import (
"errors" "github.com/go-errors/errors"
"github.com/jesseduffield/gocui" "github.com/jesseduffield/gocui"
) )

View File

@ -1,7 +1,7 @@
package gui package gui
import ( import (
"errors" "github.com/go-errors/errors"
"github.com/jesseduffield/gocui" "github.com/jesseduffield/gocui"
"github.com/jesseduffield/lazygit/pkg/git" "github.com/jesseduffield/lazygit/pkg/git"

View File

@ -1,7 +1,7 @@
package test package test
import ( import (
"errors" "github.com/go-errors/errors"
"os" "os"
"os/exec" "os/exec"
"path/filepath" "path/filepath"

View File

@ -2,7 +2,6 @@ package updates
import ( import (
"encoding/json" "encoding/json"
"errors"
"fmt" "fmt"
"io/ioutil" "io/ioutil"
"net/http" "net/http"
@ -13,6 +12,8 @@ import (
"strings" "strings"
"time" "time"
"github.com/go-errors/errors"
"github.com/kardianos/osext" "github.com/kardianos/osext"
getter "github.com/jesseduffield/go-getter" getter "github.com/jesseduffield/go-getter"

View File

@ -2,7 +2,6 @@ package utils
import ( import (
"encoding/json" "encoding/json"
"errors"
"fmt" "fmt"
"log" "log"
"os" "os"
@ -11,6 +10,8 @@ import (
"strings" "strings"
"time" "time"
"github.com/go-errors/errors"
"github.com/fatih/color" "github.com/fatih/color"
) )

View File

@ -1,7 +1,6 @@
package utils package utils
import ( import (
"errors"
"testing" "testing"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
@ -233,9 +232,9 @@ func TestGetDisplayStringArrays(t *testing.T) {
// TestRenderDisplayableList is a function. // TestRenderDisplayableList is a function.
func TestRenderDisplayableList(t *testing.T) { func TestRenderDisplayableList(t *testing.T) {
type scenario struct { type scenario struct {
input []Displayable input []Displayable
expectedString string expectedString string
expectedError error expectedErrorMessage string
} }
scenarios := []scenario{ scenarios := []scenario{
@ -245,7 +244,7 @@ func TestRenderDisplayableList(t *testing.T) {
Displayable(&myDisplayable{[]string{}}), Displayable(&myDisplayable{[]string{}}),
}, },
"\n", "\n",
nil, "",
}, },
{ {
[]Displayable{ []Displayable{
@ -253,7 +252,7 @@ func TestRenderDisplayableList(t *testing.T) {
Displayable(&myDisplayable{[]string{"c", "d"}}), Displayable(&myDisplayable{[]string{"c", "d"}}),
}, },
"aa b\nc d", "aa b\nc d",
nil, "",
}, },
{ {
[]Displayable{ []Displayable{
@ -261,23 +260,27 @@ func TestRenderDisplayableList(t *testing.T) {
Displayable(&myDisplayable{[]string{"b", "c"}}), Displayable(&myDisplayable{[]string{"b", "c"}}),
}, },
"", "",
errors.New("Each item must return the same number of strings to display"), "Each item must return the same number of strings to display",
}, },
} }
for _, s := range scenarios { for _, s := range scenarios {
str, err := renderDisplayableList(s.input) str, err := renderDisplayableList(s.input)
assert.EqualValues(t, s.expectedString, str) assert.EqualValues(t, s.expectedString, str)
assert.EqualValues(t, s.expectedError, err) if s.expectedErrorMessage != "" {
assert.EqualError(t, err, s.expectedErrorMessage)
} else {
assert.NoError(t, err)
}
} }
} }
// TestRenderList is a function. // TestRenderList is a function.
func TestRenderList(t *testing.T) { func TestRenderList(t *testing.T) {
type scenario struct { type scenario struct {
input interface{} input interface{}
expectedString string expectedString string
expectedError error expectedErrorMessage string
} }
scenarios := []scenario{ scenarios := []scenario{
@ -287,7 +290,7 @@ func TestRenderList(t *testing.T) {
{[]string{"c", "d"}}, {[]string{"c", "d"}},
}, },
"aa b\nc d", "aa b\nc d",
nil, "",
}, },
{ {
[]*myStruct{ []*myStruct{
@ -295,19 +298,23 @@ func TestRenderList(t *testing.T) {
{}, {},
}, },
"", "",
errors.New("item does not implement the Displayable interface"), "item does not implement the Displayable interface",
}, },
{ {
&myStruct{}, &myStruct{},
"", "",
errors.New("RenderList given a non-slice type"), "RenderList given a non-slice type",
}, },
} }
for _, s := range scenarios { for _, s := range scenarios {
str, err := RenderList(s.input) str, err := RenderList(s.input)
assert.EqualValues(t, s.expectedString, str) assert.EqualValues(t, s.expectedString, str)
assert.EqualValues(t, s.expectedError, err) if s.expectedErrorMessage != "" {
assert.EqualError(t, err, s.expectedErrorMessage)
} else {
assert.NoError(t, err)
}
} }
} }