From ce428377024188ae8ce8aae411881b7e993f9553 Mon Sep 17 00:00:00 2001 From: HIROSE Masaaki Date: Fri, 30 Sep 2016 19:23:44 +0900 Subject: [PATCH 1/5] Call HandleExitCoder for all members of MultiError.Errors --- errors.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/errors.go b/errors.go index c7d8c2f..fd67b96 100644 --- a/errors.go +++ b/errors.go @@ -86,8 +86,9 @@ func HandleExitCoder(err error) { if multiErr, ok := err.(MultiError); ok { for _, merr := range multiErr.Errors { - HandleExitCoder(merr) + fmt.Fprintln(ErrWriter, merr) } + OsExiter(1) return } From 6c50b15a273d29dc3820b5e4d50d78eeb113d335 Mon Sep 17 00:00:00 2001 From: HIROSE Masaaki Date: Fri, 11 Nov 2016 13:11:50 +0900 Subject: [PATCH 2/5] Exit with the code of ExitCoder if exists --- errors.go | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/errors.go b/errors.go index fd67b96..583f89f 100644 --- a/errors.go +++ b/errors.go @@ -85,10 +85,8 @@ func HandleExitCoder(err error) { } if multiErr, ok := err.(MultiError); ok { - for _, merr := range multiErr.Errors { - fmt.Fprintln(ErrWriter, merr) - } - OsExiter(1) + code := handleMultiError(multiErr) + OsExiter(code) return } @@ -97,3 +95,18 @@ func HandleExitCoder(err error) { } OsExiter(1) } + +func handleMultiError(multiErr MultiError) int { + code := 1 + for _, merr := range multiErr.Errors { + if multiErr2, ok := merr.(MultiError); ok { + code = handleMultiError(multiErr2) + } else { + fmt.Fprintln(ErrWriter, merr) + if exitErr, ok := merr.(ExitCoder); ok { + code = exitErr.ExitCode() + } + } + } + return code +} From 71ced406af64ee9961533d518dab28d455a66666 Mon Sep 17 00:00:00 2001 From: HIROSE Masaaki Date: Thu, 12 Jan 2017 18:59:38 +0900 Subject: [PATCH 3/5] Treat `rc` first called as exit code Because default OsExiter is os.Exit. --- errors_test.go | 38 ++++++++++++++++++++++++++------------ 1 file changed, 26 insertions(+), 12 deletions(-) diff --git a/errors_test.go b/errors_test.go index 131bd38..d3764b7 100644 --- a/errors_test.go +++ b/errors_test.go @@ -12,8 +12,10 @@ func TestHandleExitCoder_nil(t *testing.T) { called := false OsExiter = func(rc int) { - exitCode = rc - called = true + if !called { + exitCode = rc + called = true + } } defer func() { OsExiter = fakeOsExiter }() @@ -29,8 +31,10 @@ func TestHandleExitCoder_ExitCoder(t *testing.T) { called := false OsExiter = func(rc int) { - exitCode = rc - called = true + if !called { + exitCode = rc + called = true + } } defer func() { OsExiter = fakeOsExiter }() @@ -46,8 +50,10 @@ func TestHandleExitCoder_MultiErrorWithExitCoder(t *testing.T) { called := false OsExiter = func(rc int) { - exitCode = rc - called = true + if !called { + exitCode = rc + called = true + } } defer func() { OsExiter = fakeOsExiter }() @@ -65,8 +71,10 @@ func TestHandleExitCoder_ErrorWithMessage(t *testing.T) { called := false OsExiter = func(rc int) { - exitCode = rc - called = true + if !called { + exitCode = rc + called = true + } } ErrWriter = &bytes.Buffer{} @@ -88,8 +96,10 @@ func TestHandleExitCoder_ErrorWithoutMessage(t *testing.T) { called := false OsExiter = func(rc int) { - exitCode = rc - called = true + if !called { + exitCode = rc + called = true + } } ErrWriter = &bytes.Buffer{} @@ -123,7 +133,9 @@ func TestHandleExitCoder_ErrorWithFormat(t *testing.T) { called := false OsExiter = func(rc int) { - called = true + if !called { + called = true + } } ErrWriter = &bytes.Buffer{} @@ -143,7 +155,9 @@ func TestHandleExitCoder_MultiErrorWithFormat(t *testing.T) { called := false OsExiter = func(rc int) { - called = true + if !called { + called = true + } } ErrWriter = &bytes.Buffer{} From 286b4b56d988e0ac6da075615f1da496db94da87 Mon Sep 17 00:00:00 2001 From: HIROSE Masaaki Date: Thu, 12 Jan 2017 19:12:17 +0900 Subject: [PATCH 4/5] Document on exit code in case of MultiError is given --- errors.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/errors.go b/errors.go index 8aa8d9e..f9d648e 100644 --- a/errors.go +++ b/errors.go @@ -74,7 +74,7 @@ func (ee *ExitError) ExitCode() int { // HandleExitCoder checks if the error fulfills the ExitCoder interface, and if // so prints the error to stderr (if it is non-empty) and calls OsExiter with the // given exit code. If the given error is a MultiError, then this func is -// called on all members of the Errors slice. +// called on all members of the Errors slice and calls OsExiter with the last exit code. func HandleExitCoder(err error) { if err == nil { return From adec15acf537c7b696c299223a16c60cb3eeeed8 Mon Sep 17 00:00:00 2001 From: HIROSE Masaaki Date: Fri, 13 Jan 2017 15:37:09 +0900 Subject: [PATCH 5/5] Add another ExitCoder to assert that it uses last one --- errors_test.go | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/errors_test.go b/errors_test.go index d3764b7..d9e0da6 100644 --- a/errors_test.go +++ b/errors_test.go @@ -59,10 +59,11 @@ func TestHandleExitCoder_MultiErrorWithExitCoder(t *testing.T) { defer func() { OsExiter = fakeOsExiter }() exitErr := NewExitError("galactic perimeter breach", 9) - err := NewMultiError(errors.New("wowsa"), errors.New("egad"), exitErr) + exitErr2 := NewExitError("last ExitCoder", 11) + err := NewMultiError(errors.New("wowsa"), errors.New("egad"), exitErr, exitErr2) HandleExitCoder(err) - expect(t, exitCode, 9) + expect(t, exitCode, 11) expect(t, called, true) }