Skip to content

Commit

Permalink
feat: Add the ability to wrap and unwrap errors with exit codes (#21)
Browse files Browse the repository at this point in the history
  • Loading branch information
boblail authored Jun 13, 2023
1 parent a7718c8 commit 142116e
Show file tree
Hide file tree
Showing 2 changed files with 52 additions and 5 deletions.
48 changes: 48 additions & 0 deletions exit.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,11 @@ of some sort. Exit Codes 100-119 indicate software or system error of some sort.
*/
package exit

import (
"errors"
"fmt"
)

// Code is the exit code that is passed to the system call `exit`
// when the program terminates. Conventionally, the value zero indicates
// success and all other values (1-255) indicate failure.
Expand Down Expand Up @@ -95,3 +100,46 @@ func IsSignal(code Code) bool {
// https://pkg.go.dev/os#ProcessState.ExitCode
return code == -1 || code > 128 && code < 255
}

var (
ErrNotOK = Error{Code: NotOK}
ErrUsageError = Error{Code: UsageError}
ErrUnknownSubcommand = Error{Code: UnknownSubcommand}
ErrRequirementNotMet = Error{Code: RequirementNotMet}
ErrForbidden = Error{Code: Forbidden}
ErrMovedPermanently = Error{Code: MovedPermanently}
ErrInternalError = Error{Code: InternalError}
ErrUnavailable = Error{Code: Unavailable}
)

func FromError(err error) Code {
var e Error
if errors.As(err, &e) {
return e.Code
} else if err == nil {
return OK
} else {
return NotOK
}
}

func Wrap(err error, code Code) error {
return Error{Code: code, Cause: err}
}

type Error struct {
Code Code
Cause error
}

func (e Error) Error() string {
if e.Cause != nil {
return fmt.Sprintf("exit %d: %s", e.Code, e.Cause)
} else {
return fmt.Sprintf("exit %d", e.Code)
}
}

func (e Error) Unwrap() error {
return e.Cause
}
9 changes: 4 additions & 5 deletions readme_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package exit
import (
_ "embed"
"go/ast"
"go/importer"
"go/parser"
"go/token"
"go/types"
Expand All @@ -17,11 +18,8 @@ var readme string
var src string

func TestExitCodesMatchReadme(t *testing.T) {
var (
f *ast.File
conf types.Config
err error
)
var f *ast.File
var err error

re := regexp.MustCompile("\\| (\\d+) \\| `(\\w+)` \\| .* \\|\n")
expectedConstants := make(map[string]string)
Expand All @@ -38,6 +36,7 @@ func TestExitCodesMatchReadme(t *testing.T) {
// We create an empty map for each kind of input
// we're interested in, and Check populates them.
info := types.Info{Defs: make(map[*ast.Ident]types.Object)}
conf := types.Config{Importer: importer.Default()}
if _, err = conf.Check("", fset, []*ast.File{f}, &info); err != nil {
t.Error(err)
}
Expand Down

0 comments on commit 142116e

Please sign in to comment.