@cryptotaxi247 / kubo / commits / eb5bb1daa

feat(debugerror)

License: MIT Signed-off-by: Brian Tiger Chow <brian@perfmode.com> impl errorf License: MIT Signed-off-by: Brian Tiger Chow <brian@perfmode.com> return a debug error License: MIT Signed-off-by: Brian Tiger Chow <brian@perfmode.com>

Brian Tiger Chow committed Nov 14, 2014 at 15:18 UTC eb5bb1daa87df6be45ee2b9fd56e3b58e94b1825
8 files changed +244 -2
Godeps/Godeps.json
+4
@@ -60,6 +60,10 @@
60 "ImportPath": "github.com/coreos/go-semver/semver",
61 "Rev": "6fe83ccda8fb9b7549c9ab4ba47f47858bc950aa"
62 },
63 + {
64 + "ImportPath": "github.com/facebookgo/stackerr",
65 + "Rev": "060fbf9364c89acd41bf710e9e92915a90e7a5b5"
66 + },
67 {
68 "ImportPath": "github.com/gonuts/flag",
69 "Rev": "741a6cbd37a30dedc93f817e7de6aaf0ca38a493"
Godeps/_workspace/src/github.com/facebookgo/stackerr/.travis.yml new
+24
@@ -0,0 +1,24 @@
1 +language: go
2 +
3 +go:
4 + - 1.2
5 + - 1.3
6 +
7 +matrix:
8 + fast_finish: true
9 +
10 +before_install:
11 + - go get -v code.google.com/p/go.tools/cmd/vet
12 + - go get -v github.com/golang/lint/golint
13 + - go get -v code.google.com/p/go.tools/cmd/cover
14 +
15 +install:
16 + - go install -race -v std
17 + - go get -race -t -v ./...
18 + - go install -race -v ./...
19 +
20 +script:
21 + - go vet ./...
22 + - $HOME/gopath/bin/golint .
23 + - go test -cpu=2 -race -v ./...
24 + - go test -cpu=2 -covermode=atomic ./...
Godeps/_workspace/src/github.com/facebookgo/stackerr/readme.md new
+4
@@ -0,0 +1,4 @@
1 +stackerr [![Build Status](https://secure.travis-ci.org/facebookgo/stackerr.png)](http://travis-ci.org/facebookgo/stackerr)
2 +========
3 +
4 +Documentation: https://godoc.org/github.com/facebookgo/stackerr
Godeps/_workspace/src/github.com/facebookgo/stackerr/stackerr.go new
+97
@@ -0,0 +1,97 @@
1 +// Package stackerr provides a way to augment errors with one or more stack
2 +// traces to allow for easier debugging.
3 +package stackerr
4 +
5 +import (
6 + "errors"
7 + "fmt"
8 +
9 + "github.com/facebookgo/stack"
10 +)
11 +
12 +// Error provides the wrapper that adds multiple Stacks to an error. Each Stack
13 +// represents a location in code thru which this error was wrapped.
14 +type Error struct {
15 + multiStack *stack.Multi
16 + underlying error
17 +}
18 +
19 +// Error provides a multi line error string that includes the stack trace.
20 +func (e *Error) Error() string {
21 + return fmt.Sprintf("%s\n%s", e.underlying, e.multiStack)
22 +}
23 +
24 +// MultiStack identifies the locations this error was wrapped at.
25 +func (e *Error) MultiStack() *stack.Multi {
26 + return e.multiStack
27 +}
28 +
29 +// Underlying returns the error that is being wrapped.
30 +func (e *Error) Underlying() error {
31 + return e.underlying
32 +}
33 +
34 +type hasMultiStack interface {
35 + MultiStack() *stack.Multi
36 +}
37 +
38 +// WrapSkip the error and add the current Stack. The argument skip is the
39 +// number of stack frames to ascend, with 0 identifying the caller of Wrap. If
40 +// the error to be wrapped has a MultiStack, the current stack will be added to
41 +// it. If the error to be wrapped is nil, a nil error is returned.
42 +func WrapSkip(err error, skip int) error {
43 + // nil errors are returned back as nil.
44 + if err == nil {
45 + return nil
46 + }
47 +
48 + // we're adding another Stack to an already wrapped error.
49 + if se, ok := err.(hasMultiStack); ok {
50 + se.MultiStack().AddCallers(skip + 1)
51 + return err
52 + }
53 +
54 + // we're create a freshly wrapped error.
55 + return &Error{
56 + multiStack: stack.CallersMulti(skip + 1),
57 + underlying: err,
58 + }
59 +}
60 +
61 +// Wrap provides a convenience function that calls WrapSkip with skip=0. That
62 +// is, the Stack starts with the caller of Wrap.
63 +func Wrap(err error) error {
64 + return WrapSkip(err, 1)
65 +}
66 +
67 +// New returns a new error that includes the Stack.
68 +func New(s string) error {
69 + return WrapSkip(errors.New(s), 1)
70 +}
71 +
72 +// Newf formats and returns a new error that includes the Stack.
73 +func Newf(format string, args ...interface{}) error {
74 + return WrapSkip(fmt.Errorf(format, args...), 1)
75 +}
76 +
77 +type hasUnderlying interface {
78 + Underlying() error
79 +}
80 +
81 +// Underlying returns all the underlying errors by iteratively checking if the
82 +// error has an Underlying error. If e is nil, the returned slice will be nil.
83 +func Underlying(e error) []error {
84 + var errs []error
85 + for {
86 + if e == nil {
87 + return errs
88 + }
89 + errs = append(errs, e)
90 +
91 + if eh, ok := e.(hasUnderlying); ok {
92 + e = eh.Underlying()
93 + } else {
94 + e = nil
95 + }
96 + }
97 +}
Godeps/_workspace/src/github.com/facebookgo/stackerr/stackerr_test.go new
+82
@@ -0,0 +1,82 @@
1 +package stackerr_test
2 +
3 +import (
4 + "errors"
5 + "fmt"
6 + "regexp"
7 + "strings"
8 + "testing"
9 +
10 + "github.com/facebookgo/stackerr"
11 +)
12 +
13 +func TestNew(t *testing.T) {
14 + const errStr = "foo bar baz"
15 + e := stackerr.New(errStr)
16 + matches := []string{
17 + errStr,
18 + "^github.com/facebookgo/stackerr/stackerr_test.go:15 +TestNew$",
19 + }
20 + match(t, e.Error(), matches)
21 +}
22 +
23 +func TestNewf(t *testing.T) {
24 + const fmtStr = "%s 42"
25 + const errStr = "foo bar baz"
26 + e := stackerr.Newf(fmtStr, errStr)
27 + matches := []string{
28 + fmt.Sprintf(fmtStr, errStr),
29 + "^github.com/facebookgo/stackerr/stackerr_test.go:26 +TestNewf$",
30 + }
31 + match(t, e.Error(), matches)
32 +}
33 +
34 +func TestWrap(t *testing.T) {
35 + const errStr = "foo bar baz"
36 + e := stackerr.Wrap(errors.New(errStr))
37 + matches := []string{
38 + errStr,
39 + "^github.com/facebookgo/stackerr/stackerr_test.go:36 +TestWrap$",
40 + }
41 + match(t, e.Error(), matches)
42 +}
43 +
44 +func TestNilWrap(t *testing.T) {
45 + if stackerr.WrapSkip(nil, 1) != nil {
46 + t.Fatal("did not get nil error")
47 + }
48 +}
49 +
50 +func TestDoubleWrap(t *testing.T) {
51 + e := stackerr.New("")
52 + if stackerr.WrapSkip(e, 1) != e {
53 + t.Fatal("double wrap failure")
54 + }
55 +}
56 +
57 +func TestLog(t *testing.T) {
58 + t.Log(stackerr.New("hello"))
59 +}
60 +
61 +func TestUnderlying(t *testing.T) {
62 + e1 := errors.New("")
63 + e2 := stackerr.Wrap(e1)
64 + errs := stackerr.Underlying(e2)
65 + if len(errs) != 2 || errs[0] != e2 || errs[1] != e1 {
66 + t.Fatal("failed Underlying")
67 + }
68 +}
69 +
70 +func match(t testing.TB, s string, matches []string) {
71 + lines := strings.Split(s, "\n")
72 + for i, m := range matches {
73 + if !regexp.MustCompile(m).MatchString(lines[i]) {
74 + t.Fatalf(
75 + "did not find expected match \"%s\" on line %d in:\n%s",
76 + m,
77 + i,
78 + s,
79 + )
80 + }
81 + }
82 +}
cmd/ipfs2/main.go
+1
@@ -169,6 +169,7 @@ func (i *cmdInvocation) Parse(args []string) error {
169 if err != nil {
170 return err
171 }
172 + log.Debugf("config path is %s", configPath)
173
174 // this sets up the function that will initialize the config lazily.
175 ctx := i.req.Context()
config/config.go
+2 -2
@@ -5,11 +5,11 @@ import (
5 "crypto"
6 "crypto/x509"
7 "encoding/base64"
8 - "errors"
8 "os"
9 "path/filepath"
10
11 u "github.com/jbenet/go-ipfs/util"
12 + "github.com/jbenet/go-ipfs/util/debugerror"
13 )
14
15 var log = u.Logger("config")
@@ -129,7 +129,7 @@ func (i *Identity) DecodePrivateKey(passphrase string) (crypto.PrivateKey, error
129 func Load(filename string) (*Config, error) {
130 // if nothing is there, fail. User must run 'ipfs init'
131 if _, err := os.Stat(filename); os.IsNotExist(err) {
132 - return nil, errors.New("ipfs not initialized, please run 'ipfs init'")
132 + return nil, debugerror.New("ipfs not initialized, please run 'ipfs init'")
133 }
134
135 var cfg Config
util/debugerror/debugerror.go new
+30
@@ -0,0 +1,30 @@
1 +// package debugerror provides a way to augment errors with additional
2 +// information to allow for easier debugging.
3 +package debugerror
4 +
5 +import (
6 + "errors"
7 + "fmt"
8 +
9 + "github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/facebookgo/stackerr"
10 + "github.com/jbenet/go-ipfs/util"
11 +)
12 +
13 +func Errorf(format string, a ...interface{}) error {
14 + return Wrap(fmt.Errorf(format, a...))
15 +}
16 +
17 +// New returns an error that contains a stack trace (in debug mode)
18 +func New(s string) error {
19 + if util.Debug {
20 + return stackerr.New(s)
21 + }
22 + return errors.New(s)
23 +}
24 +
25 +func Wrap(err error) error {
26 + if util.Debug {
27 + return stackerr.Wrap(err)
28 + }
29 + return err
30 +}