Example #1
0
func TestUnderlying(t *testing.T) {
	e1 := errors.New("")
	e2 := stackerr.Wrap(e1)
	errs := stackerr.Underlying(e2)
	if len(errs) != 2 || errs[0] != e2 || errs[1] != e1 {
		t.Fatal("failed Underlying")
	}
}
Example #2
0
// errorString returns the error string with our without the stack trace
// depending on the environment variable. this exists because we want plain
// messages for end users, but when we're working on the CLI we want the stack
// trace for debugging.
func errorString(e *env, err error) string {
	type hasUnderlying interface {
		HasUnderlying() error
	}

	parseErr := func(err error) error {
		if apiErr, ok := err.(*parse.Error); ok {
			return errors.New(apiErr.Message)
		}
		return err
	}

	lastErr := func(err error) error {
		if serr, ok := err.(*stackerr.Error); ok {
			if errs := stackerr.Underlying(serr); len(errs) != 0 {
				err = errs[len(errs)-1]
			}
		} else {
			if eu, ok := err.(hasUnderlying); ok {
				err = eu.HasUnderlying()
			}
		}

		return parseErr(err)
	}

	if !e.ErrorStack {
		if merr, ok := err.(errgroup.MultiError); ok {
			var multiError []error
			for _, ierr := range []error(merr) {
				multiError = append(multiError, lastErr(ierr))
			}
			err = errgroup.MultiError(multiError)
		} else {
			err = lastErr(err)
		}
		return parseErr(err).Error()
	}

	return err.Error()
}