Skip to content

Commit 716fcfc

Browse files
zeripathdelvh
andauthored
Make every not exist error unwrappable to a fs.ErrNotExist (#20891)
A lot of our code is repeatedly testing if individual errors are specific types of Not Exist errors. This is repetitative and unnecesary. `Unwrap() error` provides a common way of labelling an error as a NotExist error and we can/should use this. This PR has chosen to use the common `io/fs` errors e.g. `fs.ErrNotExist` for our errors. This is in some ways not completely correct as these are not filesystem errors but it seems like a reasonable thing to do and would allow us to simplify a lot of our code to `errors.Is(err, fs.ErrNotExist)` instead of `package.IsErr...NotExist(err)` I am open to suggestions to use a different base error - perhaps `models/db.ErrNotExist` if that would be felt to be better. Signed-off-by: Andrew Thornton <art27@cantab.net> Co-authored-by: delvh <dev.lh@web.de>
1 parent 6af1a0c commit 716fcfc

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

48 files changed

+545
-20
lines changed

Diff for: models/activities/notification.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -806,7 +806,7 @@ func getNotificationByID(ctx context.Context, notificationID int64) (*Notificati
806806
}
807807

808808
if !ok {
809-
return nil, db.ErrNotExist{ID: notificationID}
809+
return nil, db.ErrNotExist{Resource: "notification", ID: notificationID}
810810
}
811811

812812
return notification, nil

Diff for: models/admin/task.go

+4
Original file line numberDiff line numberDiff line change
@@ -167,6 +167,10 @@ func (err ErrTaskDoesNotExist) Error() string {
167167
err.ID, err.RepoID, err.Type)
168168
}
169169

170+
func (err ErrTaskDoesNotExist) Unwrap() error {
171+
return util.ErrNotExist
172+
}
173+
170174
// GetMigratingTask returns the migrating task by repo's id
171175
func GetMigratingTask(repoID int64) (*Task, error) {
172176
task := Task{

Diff for: models/asymkey/error.go

+53-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,11 @@
44

55
package asymkey
66

7-
import "fmt"
7+
import (
8+
"fmt"
9+
10+
"code.gitea.io/gitea/modules/util"
11+
)
812

913
// ErrKeyUnableVerify represents a "KeyUnableVerify" kind of error.
1014
type ErrKeyUnableVerify struct {
@@ -36,6 +40,10 @@ func (err ErrKeyNotExist) Error() string {
3640
return fmt.Sprintf("public key does not exist [id: %d]", err.ID)
3741
}
3842

43+
func (err ErrKeyNotExist) Unwrap() error {
44+
return util.ErrNotExist
45+
}
46+
3947
// ErrKeyAlreadyExist represents a "KeyAlreadyExist" kind of error.
4048
type ErrKeyAlreadyExist struct {
4149
OwnerID int64
@@ -54,6 +62,10 @@ func (err ErrKeyAlreadyExist) Error() string {
5462
err.OwnerID, err.Fingerprint, err.Content)
5563
}
5664

65+
func (err ErrKeyAlreadyExist) Unwrap() error {
66+
return util.ErrAlreadyExist
67+
}
68+
5769
// ErrKeyNameAlreadyUsed represents a "KeyNameAlreadyUsed" kind of error.
5870
type ErrKeyNameAlreadyUsed struct {
5971
OwnerID int64
@@ -70,6 +82,10 @@ func (err ErrKeyNameAlreadyUsed) Error() string {
7082
return fmt.Sprintf("public key already exists [owner_id: %d, name: %s]", err.OwnerID, err.Name)
7183
}
7284

85+
func (err ErrKeyNameAlreadyUsed) Unwrap() error {
86+
return util.ErrAlreadyExist
87+
}
88+
7389
// ErrGPGNoEmailFound represents a "ErrGPGNoEmailFound" kind of error.
7490
type ErrGPGNoEmailFound struct {
7591
FailedEmails []string
@@ -132,6 +148,10 @@ func (err ErrGPGKeyNotExist) Error() string {
132148
return fmt.Sprintf("public gpg key does not exist [id: %d]", err.ID)
133149
}
134150

151+
func (err ErrGPGKeyNotExist) Unwrap() error {
152+
return util.ErrNotExist
153+
}
154+
135155
// ErrGPGKeyImportNotExist represents a "GPGKeyImportNotExist" kind of error.
136156
type ErrGPGKeyImportNotExist struct {
137157
ID string
@@ -147,6 +167,10 @@ func (err ErrGPGKeyImportNotExist) Error() string {
147167
return fmt.Sprintf("public gpg key import does not exist [id: %s]", err.ID)
148168
}
149169

170+
func (err ErrGPGKeyImportNotExist) Unwrap() error {
171+
return util.ErrNotExist
172+
}
173+
150174
// ErrGPGKeyIDAlreadyUsed represents a "GPGKeyIDAlreadyUsed" kind of error.
151175
type ErrGPGKeyIDAlreadyUsed struct {
152176
KeyID string
@@ -162,6 +186,10 @@ func (err ErrGPGKeyIDAlreadyUsed) Error() string {
162186
return fmt.Sprintf("public key already exists [key_id: %s]", err.KeyID)
163187
}
164188

189+
func (err ErrGPGKeyIDAlreadyUsed) Unwrap() error {
190+
return util.ErrAlreadyExist
191+
}
192+
165193
// ErrGPGKeyAccessDenied represents a "GPGKeyAccessDenied" kind of Error.
166194
type ErrGPGKeyAccessDenied struct {
167195
UserID int64
@@ -180,6 +208,10 @@ func (err ErrGPGKeyAccessDenied) Error() string {
180208
err.UserID, err.KeyID)
181209
}
182210

211+
func (err ErrGPGKeyAccessDenied) Unwrap() error {
212+
return util.ErrPermissionDenied
213+
}
214+
183215
// ErrKeyAccessDenied represents a "KeyAccessDenied" kind of error.
184216
type ErrKeyAccessDenied struct {
185217
UserID int64
@@ -198,6 +230,10 @@ func (err ErrKeyAccessDenied) Error() string {
198230
err.UserID, err.KeyID, err.Note)
199231
}
200232

233+
func (err ErrKeyAccessDenied) Unwrap() error {
234+
return util.ErrPermissionDenied
235+
}
236+
201237
// ErrDeployKeyNotExist represents a "DeployKeyNotExist" kind of error.
202238
type ErrDeployKeyNotExist struct {
203239
ID int64
@@ -215,6 +251,10 @@ func (err ErrDeployKeyNotExist) Error() string {
215251
return fmt.Sprintf("Deploy key does not exist [id: %d, key_id: %d, repo_id: %d]", err.ID, err.KeyID, err.RepoID)
216252
}
217253

254+
func (err ErrDeployKeyNotExist) Unwrap() error {
255+
return util.ErrNotExist
256+
}
257+
218258
// ErrDeployKeyAlreadyExist represents a "DeployKeyAlreadyExist" kind of error.
219259
type ErrDeployKeyAlreadyExist struct {
220260
KeyID int64
@@ -231,6 +271,10 @@ func (err ErrDeployKeyAlreadyExist) Error() string {
231271
return fmt.Sprintf("public key already exists [key_id: %d, repo_id: %d]", err.KeyID, err.RepoID)
232272
}
233273

274+
func (err ErrDeployKeyAlreadyExist) Unwrap() error {
275+
return util.ErrAlreadyExist
276+
}
277+
234278
// ErrDeployKeyNameAlreadyUsed represents a "DeployKeyNameAlreadyUsed" kind of error.
235279
type ErrDeployKeyNameAlreadyUsed struct {
236280
RepoID int64
@@ -247,6 +291,10 @@ func (err ErrDeployKeyNameAlreadyUsed) Error() string {
247291
return fmt.Sprintf("public key with name already exists [repo_id: %d, name: %s]", err.RepoID, err.Name)
248292
}
249293

294+
func (err ErrDeployKeyNameAlreadyUsed) Unwrap() error {
295+
return util.ErrNotExist
296+
}
297+
250298
// ErrSSHInvalidTokenSignature represents a "ErrSSHInvalidTokenSignature" kind of error.
251299
type ErrSSHInvalidTokenSignature struct {
252300
Wrapped error
@@ -262,3 +310,7 @@ func IsErrSSHInvalidTokenSignature(err error) bool {
262310
func (err ErrSSHInvalidTokenSignature) Error() string {
263311
return "the provided signature does not sign the token with the provided key"
264312
}
313+
314+
func (err ErrSSHInvalidTokenSignature) Unwrap() error {
315+
return util.ErrInvalidArgument
316+
}

Diff for: models/auth/oauth2.go

+11-1
Original file line numberDiff line numberDiff line change
@@ -486,7 +486,7 @@ type ErrOAuthClientIDInvalid struct {
486486
ClientID string
487487
}
488488

489-
// IsErrOauthClientIDInvalid checks if an error is a ErrReviewNotExist.
489+
// IsErrOauthClientIDInvalid checks if an error is a ErrOAuthClientIDInvalid.
490490
func IsErrOauthClientIDInvalid(err error) bool {
491491
_, ok := err.(ErrOAuthClientIDInvalid)
492492
return ok
@@ -497,6 +497,11 @@ func (err ErrOAuthClientIDInvalid) Error() string {
497497
return fmt.Sprintf("Client ID invalid [Client ID: %s]", err.ClientID)
498498
}
499499

500+
// Unwrap unwraps this as a ErrNotExist err
501+
func (err ErrOAuthClientIDInvalid) Unwrap() error {
502+
return util.ErrNotExist
503+
}
504+
500505
// ErrOAuthApplicationNotFound will be thrown if id cannot be found
501506
type ErrOAuthApplicationNotFound struct {
502507
ID int64
@@ -513,6 +518,11 @@ func (err ErrOAuthApplicationNotFound) Error() string {
513518
return fmt.Sprintf("OAuth application not found [ID: %d]", err.ID)
514519
}
515520

521+
// Unwrap unwraps this as a ErrNotExist err
522+
func (err ErrOAuthApplicationNotFound) Unwrap() error {
523+
return util.ErrNotExist
524+
}
525+
516526
// GetActiveOAuth2ProviderSources returns all actived LoginOAuth2 sources
517527
func GetActiveOAuth2ProviderSources() ([]*Source, error) {
518528
sources := make([]*Source, 0, 1)

Diff for: models/auth/source.go

+11
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import (
1212
"code.gitea.io/gitea/models/db"
1313
"code.gitea.io/gitea/modules/log"
1414
"code.gitea.io/gitea/modules/timeutil"
15+
"code.gitea.io/gitea/modules/util"
1516

1617
"xorm.io/xorm"
1718
"xorm.io/xorm/convert"
@@ -366,6 +367,11 @@ func (err ErrSourceNotExist) Error() string {
366367
return fmt.Sprintf("login source does not exist [id: %d]", err.ID)
367368
}
368369

370+
// Unwrap unwraps this as a ErrNotExist err
371+
func (err ErrSourceNotExist) Unwrap() error {
372+
return util.ErrNotExist
373+
}
374+
369375
// ErrSourceAlreadyExist represents a "SourceAlreadyExist" kind of error.
370376
type ErrSourceAlreadyExist struct {
371377
Name string
@@ -381,6 +387,11 @@ func (err ErrSourceAlreadyExist) Error() string {
381387
return fmt.Sprintf("login source already exists [name: %s]", err.Name)
382388
}
383389

390+
// Unwrap unwraps this as a ErrExist err
391+
func (err ErrSourceAlreadyExist) Unwrap() error {
392+
return util.ErrAlreadyExist
393+
}
394+
384395
// ErrSourceInUse represents a "SourceInUse" kind of error.
385396
type ErrSourceInUse struct {
386397
ID int64

Diff for: models/auth/token.go

+8
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,10 @@ func (err ErrAccessTokenNotExist) Error() string {
3535
return fmt.Sprintf("access token does not exist [sha: %s]", err.Token)
3636
}
3737

38+
func (err ErrAccessTokenNotExist) Unwrap() error {
39+
return util.ErrNotExist
40+
}
41+
3842
// ErrAccessTokenEmpty represents a "AccessTokenEmpty" kind of error.
3943
type ErrAccessTokenEmpty struct{}
4044

@@ -48,6 +52,10 @@ func (err ErrAccessTokenEmpty) Error() string {
4852
return "access token is empty"
4953
}
5054

55+
func (err ErrAccessTokenEmpty) Unwrap() error {
56+
return util.ErrInvalidArgument
57+
}
58+
5159
var successfulAccessTokenCache *lru.Cache
5260

5361
// AccessToken represents a personal access token.

Diff for: models/auth/twofactor.go

+5
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,11 @@ func (err ErrTwoFactorNotEnrolled) Error() string {
4141
return fmt.Sprintf("user not enrolled in 2FA [uid: %d]", err.UID)
4242
}
4343

44+
// Unwrap unwraps this as a ErrNotExist err
45+
func (err ErrTwoFactorNotEnrolled) Unwrap() error {
46+
return util.ErrNotExist
47+
}
48+
4449
// TwoFactor represents a two-factor authentication token.
4550
type TwoFactor struct {
4651
ID int64 `xorm:"pk autoincr"`

Diff for: models/auth/webauthn.go

+6
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import (
1111

1212
"code.gitea.io/gitea/models/db"
1313
"code.gitea.io/gitea/modules/timeutil"
14+
"code.gitea.io/gitea/modules/util"
1415

1516
"github.com/duo-labs/webauthn/webauthn"
1617
"xorm.io/xorm"
@@ -29,6 +30,11 @@ func (err ErrWebAuthnCredentialNotExist) Error() string {
2930
return fmt.Sprintf("WebAuthn credential does not exist [credential_id: %x]", err.CredentialID)
3031
}
3132

33+
// Unwrap unwraps this as a ErrNotExist err
34+
func (err ErrWebAuthnCredentialNotExist) Unwrap() error {
35+
return util.ErrNotExist
36+
}
37+
3238
// IsErrWebAuthnCredentialNotExist checks if an error is a ErrWebAuthnCredentialNotExist.
3339
func IsErrWebAuthnCredentialNotExist(err error) bool {
3440
_, ok := err.(ErrWebAuthnCredentialNotExist)

Diff for: models/db/engine.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -225,7 +225,7 @@ func NamesToBean(names ...string) ([]interface{}, error) {
225225
for _, name := range names {
226226
bean, ok := beanMap[strings.ToLower(strings.TrimSpace(name))]
227227
if !ok {
228-
return nil, fmt.Errorf("No table found that matches: %s", name)
228+
return nil, fmt.Errorf("no table found that matches: %s", name)
229229
}
230230
if !gotBean[bean] {
231231
beans = append(beans, bean)

Diff for: models/db/error.go

+18-2
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ package db
66

77
import (
88
"fmt"
9+
10+
"code.gitea.io/gitea/modules/util"
911
)
1012

1113
// ErrCancelled represents an error due to context cancellation
@@ -45,7 +47,8 @@ func (err ErrSSHDisabled) Error() string {
4547

4648
// ErrNotExist represents a non-exist error.
4749
type ErrNotExist struct {
48-
ID int64
50+
Resource string
51+
ID int64
4952
}
5053

5154
// IsErrNotExist checks if an error is an ErrNotExist
@@ -55,5 +58,18 @@ func IsErrNotExist(err error) bool {
5558
}
5659

5760
func (err ErrNotExist) Error() string {
58-
return fmt.Sprintf("record does not exist [id: %d]", err.ID)
61+
name := "record"
62+
if err.Resource != "" {
63+
name = err.Resource
64+
}
65+
66+
if err.ID != 0 {
67+
return fmt.Sprintf("%s does not exist [id: %d]", name, err.ID)
68+
}
69+
return fmt.Sprintf("%s does not exist", name)
70+
}
71+
72+
// Unwrap unwraps this as a ErrNotExist err
73+
func (err ErrNotExist) Unwrap() error {
74+
return util.ErrNotExist
5975
}

Diff for: models/db/name.go

+19-3
Original file line numberDiff line numberDiff line change
@@ -5,16 +5,17 @@
55
package db
66

77
import (
8-
"errors"
98
"fmt"
109
"regexp"
1110
"strings"
1211
"unicode/utf8"
12+
13+
"code.gitea.io/gitea/modules/util"
1314
)
1415

1516
var (
1617
// ErrNameEmpty name is empty error
17-
ErrNameEmpty = errors.New("Name is empty")
18+
ErrNameEmpty = util.SilentWrap{Message: "name is empty", Err: util.ErrInvalidArgument}
1819

1920
// AlphaDashDotPattern characters prohibited in a user name (anything except A-Za-z0-9_.-)
2021
AlphaDashDotPattern = regexp.MustCompile(`[^\w-\.]`)
@@ -35,6 +36,11 @@ func (err ErrNameReserved) Error() string {
3536
return fmt.Sprintf("name is reserved [name: %s]", err.Name)
3637
}
3738

39+
// Unwrap unwraps this as a ErrInvalid err
40+
func (err ErrNameReserved) Unwrap() error {
41+
return util.ErrInvalidArgument
42+
}
43+
3844
// ErrNamePatternNotAllowed represents a "pattern not allowed" error.
3945
type ErrNamePatternNotAllowed struct {
4046
Pattern string
@@ -50,6 +56,11 @@ func (err ErrNamePatternNotAllowed) Error() string {
5056
return fmt.Sprintf("name pattern is not allowed [pattern: %s]", err.Pattern)
5157
}
5258

59+
// Unwrap unwraps this as a ErrInvalid err
60+
func (err ErrNamePatternNotAllowed) Unwrap() error {
61+
return util.ErrInvalidArgument
62+
}
63+
5364
// ErrNameCharsNotAllowed represents a "character not allowed in name" error.
5465
type ErrNameCharsNotAllowed struct {
5566
Name string
@@ -62,7 +73,12 @@ func IsErrNameCharsNotAllowed(err error) bool {
6273
}
6374

6475
func (err ErrNameCharsNotAllowed) Error() string {
65-
return fmt.Sprintf("User name is invalid [%s]: must be valid alpha or numeric or dash(-_) or dot characters", err.Name)
76+
return fmt.Sprintf("name is invalid [%s]: must be valid alpha or numeric or dash(-_) or dot characters", err.Name)
77+
}
78+
79+
// Unwrap unwraps this as a ErrInvalid err
80+
func (err ErrNameCharsNotAllowed) Unwrap() error {
81+
return util.ErrInvalidArgument
6682
}
6783

6884
// IsUsableName checks if name is reserved or pattern of name is not allowed

0 commit comments

Comments
 (0)