Refactor error system (#33771)

It should not expose `util.SilentWrap` or construct it manually.
This commit is contained in:
wxiaoguang
2025-03-03 13:36:10 +08:00
committed by GitHub
parent dbed39d632
commit 216243eee2
12 changed files with 41 additions and 58 deletions

View File

@ -25,7 +25,7 @@ func (err ErrKeyUnableVerify) Error() string {
} }
// ErrKeyIsPrivate is returned when the provided key is a private key not a public key // ErrKeyIsPrivate is returned when the provided key is a private key not a public key
var ErrKeyIsPrivate = util.NewSilentWrapErrorf(util.ErrInvalidArgument, "the provided key is a private key") var ErrKeyIsPrivate = util.ErrorWrap(util.ErrInvalidArgument, "the provided key is a private key")
// ErrKeyNotExist represents a "KeyNotExist" kind of error. // ErrKeyNotExist represents a "KeyNotExist" kind of error.
type ErrKeyNotExist struct { type ErrKeyNotExist struct {

View File

@ -77,7 +77,7 @@ func (err ErrNameCharsNotAllowed) Unwrap() error {
func IsUsableName(reservedNames, reservedPatterns []string, name string) error { func IsUsableName(reservedNames, reservedPatterns []string, name string) error {
name = strings.TrimSpace(strings.ToLower(name)) name = strings.TrimSpace(strings.ToLower(name))
if utf8.RuneCountInString(name) == 0 { if utf8.RuneCountInString(name) == 0 {
return util.SilentWrap{Message: "name is empty", Err: util.ErrInvalidArgument} return util.NewInvalidArgumentErrorf("name is empty")
} }
for i := range reservedNames { for i := range reservedNames {

View File

@ -50,15 +50,15 @@ func (archiver *RepoArchiver) RelativePath() string {
func repoArchiverForRelativePath(relativePath string) (*RepoArchiver, error) { func repoArchiverForRelativePath(relativePath string) (*RepoArchiver, error) {
parts := strings.SplitN(relativePath, "/", 3) parts := strings.SplitN(relativePath, "/", 3)
if len(parts) != 3 { if len(parts) != 3 {
return nil, util.SilentWrap{Message: fmt.Sprintf("invalid storage path: %s", relativePath), Err: util.ErrInvalidArgument} return nil, util.NewInvalidArgumentErrorf("invalid storage path: must have 3 parts")
} }
repoID, err := strconv.ParseInt(parts[0], 10, 64) repoID, err := strconv.ParseInt(parts[0], 10, 64)
if err != nil { if err != nil {
return nil, util.SilentWrap{Message: fmt.Sprintf("invalid storage path: %s", relativePath), Err: util.ErrInvalidArgument} return nil, util.NewInvalidArgumentErrorf("invalid storage path: invalid repo id")
} }
commitID, archiveType := git.SplitArchiveNameType(parts[2]) commitID, archiveType := git.SplitArchiveNameType(parts[2])
if archiveType == git.ArchiveUnknown { if archiveType == git.ArchiveUnknown {
return nil, util.SilentWrap{Message: fmt.Sprintf("invalid storage path: %s", relativePath), Err: util.ErrInvalidArgument} return nil, util.NewInvalidArgumentErrorf("invalid storage path: invalid archive type")
} }
return &RepoArchiver{RepoID: repoID, CommitID: commitID, Type: archiveType}, nil return &RepoArchiver{RepoID: repoID, CommitID: commitID, Type: archiveType}, nil
} }

View File

@ -34,7 +34,7 @@ func SetMustChangePassword(ctx context.Context, all, mustChangePassword bool, in
if !all { if !all {
include = sliceTrimSpaceDropEmpty(include) include = sliceTrimSpaceDropEmpty(include)
if len(include) == 0 { if len(include) == 0 {
return 0, util.NewSilentWrapErrorf(util.ErrInvalidArgument, "no users to include provided") return 0, util.ErrorWrap(util.ErrInvalidArgument, "no users to include provided")
} }
cond = cond.And(builder.In("lower_name", include)) cond = cond.And(builder.In("lower_name", include))

View File

@ -17,9 +17,9 @@ import (
) )
var ( var (
ErrInvalidStructure = util.SilentWrap{Message: "package structure is invalid", Err: util.ErrInvalidArgument} ErrInvalidStructure = util.NewInvalidArgumentErrorf("package structure is invalid")
ErrInvalidName = util.SilentWrap{Message: "package name is invalid", Err: util.ErrInvalidArgument} ErrInvalidName = util.NewInvalidArgumentErrorf("package name is invalid")
ErrInvalidVersion = util.SilentWrap{Message: "package version is invalid", Err: util.ErrInvalidArgument} ErrInvalidVersion = util.NewInvalidArgumentErrorf("package version is invalid")
) )
const ( const (

View File

@ -1,13 +0,0 @@
// Copyright 2022 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT
package i18n
import (
"code.gitea.io/gitea/modules/util"
)
var (
ErrLocaleAlreadyExist = util.SilentWrap{Message: "lang already exists", Err: util.ErrAlreadyExist}
ErrUncertainArguments = util.SilentWrap{Message: "arguments to i18n should not contain uncertain slices", Err: util.ErrInvalidArgument}
)

View File

@ -4,6 +4,7 @@
package i18n package i18n
import ( import (
"errors"
"fmt" "fmt"
"reflect" "reflect"
) )
@ -30,7 +31,7 @@ func Format(format string, args ...any) (msg string, err error) {
fmtArgs = append(fmtArgs, val.Index(i).Interface()) fmtArgs = append(fmtArgs, val.Index(i).Interface())
} }
} else { } else {
err = ErrUncertainArguments err = errors.New("arguments to i18n should not contain uncertain slices")
break break
} }
} else { } else {

View File

@ -4,6 +4,7 @@
package i18n package i18n
import ( import (
"errors"
"fmt" "fmt"
"html/template" "html/template"
"slices" "slices"
@ -41,7 +42,7 @@ func NewLocaleStore() LocaleStore {
// AddLocaleByIni adds locale by ini into the store // AddLocaleByIni adds locale by ini into the store
func (store *localeStore) AddLocaleByIni(langName, langDesc string, source, moreSource []byte) error { func (store *localeStore) AddLocaleByIni(langName, langDesc string, source, moreSource []byte) error {
if _, ok := store.localeMap[langName]; ok { if _, ok := store.localeMap[langName]; ok {
return ErrLocaleAlreadyExist return errors.New("lang has already been added")
} }
store.langNames = append(store.langNames, langName) store.langNames = append(store.langNames, langName)

View File

@ -22,74 +22,74 @@ var (
ErrUnprocessableContent = errors.New("unprocessable content") ErrUnprocessableContent = errors.New("unprocessable content")
) )
// SilentWrap provides a simple wrapper for a wrapped error where the wrapped error message plays no part in the error message // errorWrapper provides a simple wrapper for a wrapped error where the wrapped error message plays no part in the error message
// Especially useful for "untyped" errors created with "errors.New(…)" that can be classified as 'invalid argument', 'permission denied', 'exists already', or 'does not exist' // Especially useful for "untyped" errors created with "errors.New(…)" that can be classified as 'invalid argument', 'permission denied', 'exists already', or 'does not exist'
type SilentWrap struct { type errorWrapper struct {
Message string Message string
Err error Err error
} }
// Error returns the message // Error returns the message
func (w SilentWrap) Error() string { func (w errorWrapper) Error() string {
return w.Message return w.Message
} }
// Unwrap returns the underlying error // Unwrap returns the underlying error
func (w SilentWrap) Unwrap() error { func (w errorWrapper) Unwrap() error {
return w.Err return w.Err
} }
type LocaleWrap struct { type LocaleWrapper struct {
err error err error
TrKey string TrKey string
TrArgs []any TrArgs []any
} }
// Error returns the message // Error returns the message
func (w LocaleWrap) Error() string { func (w LocaleWrapper) Error() string {
return w.err.Error() return w.err.Error()
} }
// Unwrap returns the underlying error // Unwrap returns the underlying error
func (w LocaleWrap) Unwrap() error { func (w LocaleWrapper) Unwrap() error {
return w.err return w.err
} }
// NewSilentWrapErrorf returns an error that formats as the given text but unwraps as the provided error // ErrorWrap returns an error that formats as the given text but unwraps as the provided error
func NewSilentWrapErrorf(unwrap error, message string, args ...any) error { func ErrorWrap(unwrap error, message string, args ...any) error {
if len(args) == 0 { if len(args) == 0 {
return SilentWrap{Message: message, Err: unwrap} return errorWrapper{Message: message, Err: unwrap}
} }
return SilentWrap{Message: fmt.Sprintf(message, args...), Err: unwrap} return errorWrapper{Message: fmt.Sprintf(message, args...), Err: unwrap}
} }
// NewInvalidArgumentErrorf returns an error that formats as the given text but unwraps as an ErrInvalidArgument // NewInvalidArgumentErrorf returns an error that formats as the given text but unwraps as an ErrInvalidArgument
func NewInvalidArgumentErrorf(message string, args ...any) error { func NewInvalidArgumentErrorf(message string, args ...any) error {
return NewSilentWrapErrorf(ErrInvalidArgument, message, args...) return ErrorWrap(ErrInvalidArgument, message, args...)
} }
// NewPermissionDeniedErrorf returns an error that formats as the given text but unwraps as an ErrPermissionDenied // NewPermissionDeniedErrorf returns an error that formats as the given text but unwraps as an ErrPermissionDenied
func NewPermissionDeniedErrorf(message string, args ...any) error { func NewPermissionDeniedErrorf(message string, args ...any) error {
return NewSilentWrapErrorf(ErrPermissionDenied, message, args...) return ErrorWrap(ErrPermissionDenied, message, args...)
} }
// NewAlreadyExistErrorf returns an error that formats as the given text but unwraps as an ErrAlreadyExist // NewAlreadyExistErrorf returns an error that formats as the given text but unwraps as an ErrAlreadyExist
func NewAlreadyExistErrorf(message string, args ...any) error { func NewAlreadyExistErrorf(message string, args ...any) error {
return NewSilentWrapErrorf(ErrAlreadyExist, message, args...) return ErrorWrap(ErrAlreadyExist, message, args...)
} }
// NewNotExistErrorf returns an error that formats as the given text but unwraps as an ErrNotExist // NewNotExistErrorf returns an error that formats as the given text but unwraps as an ErrNotExist
func NewNotExistErrorf(message string, args ...any) error { func NewNotExistErrorf(message string, args ...any) error {
return NewSilentWrapErrorf(ErrNotExist, message, args...) return ErrorWrap(ErrNotExist, message, args...)
} }
// ErrWrapLocale wraps an err with a translation key and arguments // ErrorWrapLocale wraps an err with a translation key and arguments
func ErrWrapLocale(err error, trKey string, trArgs ...any) error { func ErrorWrapLocale(err error, trKey string, trArgs ...any) error {
return LocaleWrap{err: err, TrKey: trKey, TrArgs: trArgs} return LocaleWrapper{err: err, TrKey: trKey, TrArgs: trArgs}
} }
func ErrAsLocale(err error) *LocaleWrap { func ErrorAsLocale(err error) *LocaleWrapper {
var e LocaleWrap var e LocaleWrapper
if errors.As(err, &e) { if errors.As(err, &e) {
return &e return &e
} }

View File

@ -789,7 +789,7 @@ func Run(ctx *context_module.Context) {
return nil return nil
}) })
if err != nil { if err != nil {
if errLocale := util.ErrAsLocale(err); errLocale != nil { if errLocale := util.ErrorAsLocale(err); errLocale != nil {
ctx.Flash.Error(ctx.Tr(errLocale.TrKey, errLocale.TrArgs...)) ctx.Flash.Error(ctx.Tr(errLocale.TrKey, errLocale.TrArgs...))
ctx.Redirect(redirectURL) ctx.Redirect(redirectURL)
} else { } else {

View File

@ -141,14 +141,14 @@ func GetActionWorkflow(ctx *context.APIContext, workflowID string) (*api.ActionW
func DispatchActionWorkflow(ctx reqctx.RequestContext, doer *user_model.User, repo *repo_model.Repository, gitRepo *git.Repository, workflowID, ref string, processInputs func(model *model.WorkflowDispatch, inputs map[string]any) error) error { func DispatchActionWorkflow(ctx reqctx.RequestContext, doer *user_model.User, repo *repo_model.Repository, gitRepo *git.Repository, workflowID, ref string, processInputs func(model *model.WorkflowDispatch, inputs map[string]any) error) error {
if workflowID == "" { if workflowID == "" {
return util.ErrWrapLocale( return util.ErrorWrapLocale(
util.NewNotExistErrorf("workflowID is empty"), util.NewNotExistErrorf("workflowID is empty"),
"actions.workflow.not_found", workflowID, "actions.workflow.not_found", workflowID,
) )
} }
if ref == "" { if ref == "" {
return util.ErrWrapLocale( return util.ErrorWrapLocale(
util.NewNotExistErrorf("ref is empty"), util.NewNotExistErrorf("ref is empty"),
"form.target_ref_not_exist", ref, "form.target_ref_not_exist", ref,
) )
@ -158,7 +158,7 @@ func DispatchActionWorkflow(ctx reqctx.RequestContext, doer *user_model.User, re
cfgUnit := repo.MustGetUnit(ctx, unit.TypeActions) cfgUnit := repo.MustGetUnit(ctx, unit.TypeActions)
cfg := cfgUnit.ActionsConfig() cfg := cfgUnit.ActionsConfig()
if cfg.IsWorkflowDisabled(workflowID) { if cfg.IsWorkflowDisabled(workflowID) {
return util.ErrWrapLocale( return util.ErrorWrapLocale(
util.NewPermissionDeniedErrorf("workflow is disabled"), util.NewPermissionDeniedErrorf("workflow is disabled"),
"actions.workflow.disabled", "actions.workflow.disabled",
) )
@ -177,7 +177,7 @@ func DispatchActionWorkflow(ctx reqctx.RequestContext, doer *user_model.User, re
runTargetCommit, err = gitRepo.GetBranchCommit(ref) runTargetCommit, err = gitRepo.GetBranchCommit(ref)
} }
if err != nil { if err != nil {
return util.ErrWrapLocale( return util.ErrorWrapLocale(
util.NewNotExistErrorf("ref %q doesn't exist", ref), util.NewNotExistErrorf("ref %q doesn't exist", ref),
"form.target_ref_not_exist", ref, "form.target_ref_not_exist", ref,
) )
@ -208,7 +208,7 @@ func DispatchActionWorkflow(ctx reqctx.RequestContext, doer *user_model.User, re
} }
if len(workflows) == 0 { if len(workflows) == 0 {
return util.ErrWrapLocale( return util.ErrorWrapLocale(
util.NewNotExistErrorf("workflow %q doesn't exist", workflowID), util.NewNotExistErrorf("workflow %q doesn't exist", workflowID),
"actions.workflow.not_found", workflowID, "actions.workflow.not_found", workflowID,
) )

View File

@ -296,10 +296,7 @@ func UpdateRelease(ctx context.Context, doer *user_model.User, gitRepo *git.Repo
} }
for _, attach := range attachments { for _, attach := range attachments {
if attach.ReleaseID != rel.ID { if attach.ReleaseID != rel.ID {
return util.SilentWrap{ return util.NewPermissionDeniedErrorf("delete attachment of release permission denied")
Message: "delete attachment of release permission denied",
Err: util.ErrPermissionDenied,
}
} }
deletedUUIDs.Add(attach.UUID) deletedUUIDs.Add(attach.UUID)
} }
@ -321,10 +318,7 @@ func UpdateRelease(ctx context.Context, doer *user_model.User, gitRepo *git.Repo
} }
for _, attach := range attachments { for _, attach := range attachments {
if attach.ReleaseID != rel.ID { if attach.ReleaseID != rel.ID {
return util.SilentWrap{ return util.NewPermissionDeniedErrorf("update attachment of release permission denied")
Message: "update attachment of release permission denied",
Err: util.ErrPermissionDenied,
}
} }
} }