func ErrorFilePath(err error) string { v, ok := errors.GetData(err, filePathErrorKey).(string) if !ok { return "" } return v }
func ErrorLineNumber(err error) int { v, ok := errors.GetData(err, lineNumberErrorKey).(int) if !ok { return -1 } return v }
// GetStatusCode will return the status code associated with an error, and // default_code if none is found. func GetStatusCode(err error, default_code int) int { rv := errors.GetData(err, statusCode) sc, ok := rv.(int) if ok { return sc } return default_code }
// GetErrorBody will return the user-visible error message given an error. // The message will be determined by errors.GetMessage() unless the error class // has an error body overridden by OverrideErrorBody. func GetErrorBody(err error) string { rv := errors.GetData(err, errorBody) message, ok := rv.(string) if !ok { return errors.GetMessage(err) } class := errors.GetClass(err) if class == nil { return message } return fmt.Sprintf("%s: %s", class.String(), message) }
func main() { try.Do(func() { cli.Main(os.Args, os.Stderr, os.Stdout) }).Catch(cli.Exit, func(err *errors.Error) { // Errors marked as valid user-facing issues get a nice // pretty-printed route out, and may include specified exit codes. fmt.Fprintf(os.Stderr, "%s\n", err.Message()) // exit, taking the specified code if any. code := errors.GetData(err, cli.ExitCodeKey) if code == nil { os.Exit(int(0)) } os.Exit(int(code.(cli.ExitCode))) }).Catch(cli.Error, func(err *errors.Error) { // Errors marked as valid user-facing issues get a nice // pretty-printed route out, and may include specified exit codes. if isDebugMode() { // in debug-mode, repanic all the way to death so that we get all of golang's built in log features. panic(err) } else { // print nicely. fmt.Fprintf(os.Stderr, "Repeatr was unable to complete your request!\n"+ "%s\n", err.Message()) // exit, taking the specified code if any. code := errors.GetData(err, cli.ExitCodeKey) if code == nil { os.Exit(int(cli.EXIT_USER)) } os.Exit(int(code.(cli.ExitCode))) } }).CatchAll(func(err error) { // Errors that aren't marked as valid user-facing issues should be // logged in preparation for a bug report. if isDebugMode() { // in debug-mode, repanic all the way to death so that we get all of golang's built in log features. panic(err) } else { // save the error to a file. we want to keep the stacks, but not scare away the user. logPath, saveErr := saveErrorReport(err) var saveMsg string if saveErr == nil { saveMsg = fmt.Sprintf("We've logged the full error to a file: %q. Please include this in the report.", logPath) } else { saveMsg = fmt.Sprintf("Additionally, we were unable to save a full log of the problem (\"%s\").", saveErr) } fmt.Fprintf(os.Stderr, "Repeatr encountered a serious issue and was unable to complete your request!\n"+ "Please file an issue to help us fix it.\n"+ "%s\n"+ "\n"+ "This is the short version of the problem:\n"+ "%s\n", saveMsg, errors.GetMessage(err), ) os.Exit(int(cli.EXIT_UNKNOWNPANIC)) } }).Done() }