//go:build linux || freebsd // +build linux freebsd package core import ( "fmt" "net/url" ) // ErrorType defines the error type type ErrorType string const ( ErrNetwork ErrorType = "NETWORK" ErrProtocol ErrorType = "PROTOCOL" ErrFile ErrorType = "FILE" ErrTimeout ErrorType = "TIMEOUT" ErrAuth ErrorType = "AUTH" ErrChecksum ErrorType = "CHECKSUM" ErrUnsupported ErrorType = "UNSUPPORTED" ErrCancelled ErrorType = "CANCELLED" ) // GogetError is a structured error with context type GogetError struct { Type ErrorType Message string Cause error URL string Hint string // Actionable suggestion for the user Details map[string]string } func (e *GogetError) Error() string { var msg string if e.Cause != nil { msg = fmt.Sprintf("[%s] %s: %v", e.Type, e.Message, e.Cause) } else { msg = fmt.Sprintf("[%s] %s", e.Type, e.Message) } if e.Hint != "" { msg += fmt.Sprintf(" (hint: %s)", e.Hint) } return msg } func (e *GogetError) Unwrap() error { return e.Cause } // GetDetail returns a value from the Details map, or an empty string if the key is absent. func (e *GogetError) GetDetail(key string) string { if e.Details == nil { return "" } return e.Details[key] } // NewNetworkError creates a network error func NewNetworkError(msg string, cause error, url string) *GogetError { return &GogetError{ Type: ErrNetwork, Message: msg, Cause: cause, URL: url, } } // NewProtocolError creates a protocol error func NewProtocolError(msg string, cause error, url string) *GogetError { return &GogetError{ Type: ErrProtocol, Message: msg, Cause: cause, URL: url, } } // NewFileError creates a file error func NewFileError(msg string, cause error) *GogetError { return &GogetError{ Type: ErrFile, Message: msg, Cause: cause, } } // NewTimeoutError creates a timeout error func NewTimeoutError(msg string, url string) *GogetError { return &GogetError{ Type: ErrTimeout, Message: msg, URL: url, Hint: "increase --max-time or --connect-timeout, or check network connectivity", } } // NewChecksumError creates a checksum error func NewChecksumError(expected, actual string) *GogetError { return &GogetError{ Type: ErrChecksum, Message: fmt.Sprintf("checksum mismatch: expected %s, got %s", expected, actual), Hint: "verify the file integrity with an external checksum tool or re-download", Details: map[string]string{ "expected": expected, "actual": actual, }, } } // NewUnsupportedError creates an unsupported operation error func NewUnsupportedError(msg string) *GogetError { return &GogetError{ Type: ErrUnsupported, Message: msg, } } // WithHint returns the error with the hint set. Use for adding contextual, // actionable suggestions to an existing error without creating a new one. func (e *GogetError) WithHint(hint string) *GogetError { e.Hint = hint return e } // SafeURL returns the URL string with credentials removed for safe error logging. func SafeURL(u *url.URL) string { if u == nil { return "" } clean := *u clean.User = nil return clean.String() }