Skip to content

Commit a86d070

Browse files
committed
Make every not exist error unwrappable to a fs.ErrNotExist
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>
1 parent 6d31814 commit a86d070

Some content is hidden

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

41 files changed

+527
-16
lines changed

models/asymkey/error.go

+52-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,10 @@
44

55
package asymkey
66

7-
import "fmt"
7+
import (
8+
"fmt"
9+
"io/fs"
10+
)
811

912
// ErrKeyUnableVerify represents a "KeyUnableVerify" kind of error.
1013
type ErrKeyUnableVerify struct {
@@ -36,6 +39,10 @@ func (err ErrKeyNotExist) Error() string {
3639
return fmt.Sprintf("public key does not exist [id: %d]", err.ID)
3740
}
3841

42+
func (err ErrKeyNotExist) Unwrap() error {
43+
return fs.ErrNotExist
44+
}
45+
3946
// ErrKeyAlreadyExist represents a "KeyAlreadyExist" kind of error.
4047
type ErrKeyAlreadyExist struct {
4148
OwnerID int64
@@ -54,6 +61,10 @@ func (err ErrKeyAlreadyExist) Error() string {
5461
err.OwnerID, err.Fingerprint, err.Content)
5562
}
5663

64+
func (err ErrKeyAlreadyExist) Unwrap() error {
65+
return fs.ErrExist
66+
}
67+
5768
// ErrKeyNameAlreadyUsed represents a "KeyNameAlreadyUsed" kind of error.
5869
type ErrKeyNameAlreadyUsed struct {
5970
OwnerID int64
@@ -70,6 +81,10 @@ func (err ErrKeyNameAlreadyUsed) Error() string {
7081
return fmt.Sprintf("public key already exists [owner_id: %d, name: %s]", err.OwnerID, err.Name)
7182
}
7283

84+
func (err ErrKeyNameAlreadyUsed) Unwrap() error {
85+
return fs.ErrExist
86+
}
87+
7388
// ErrGPGNoEmailFound represents a "ErrGPGNoEmailFound" kind of error.
7489
type ErrGPGNoEmailFound struct {
7590
FailedEmails []string
@@ -132,6 +147,10 @@ func (err ErrGPGKeyNotExist) Error() string {
132147
return fmt.Sprintf("public gpg key does not exist [id: %d]", err.ID)
133148
}
134149

150+
func (err ErrGPGKeyNotExist) Unwrap() error {
151+
return fs.ErrNotExist
152+
}
153+
135154
// ErrGPGKeyImportNotExist represents a "GPGKeyImportNotExist" kind of error.
136155
type ErrGPGKeyImportNotExist struct {
137156
ID string
@@ -147,6 +166,10 @@ func (err ErrGPGKeyImportNotExist) Error() string {
147166
return fmt.Sprintf("public gpg key import does not exist [id: %s]", err.ID)
148167
}
149168

169+
func (err ErrGPGKeyImportNotExist) Unwrap() error {
170+
return fs.ErrNotExist
171+
}
172+
150173
// ErrGPGKeyIDAlreadyUsed represents a "GPGKeyIDAlreadyUsed" kind of error.
151174
type ErrGPGKeyIDAlreadyUsed struct {
152175
KeyID string
@@ -162,6 +185,10 @@ func (err ErrGPGKeyIDAlreadyUsed) Error() string {
162185
return fmt.Sprintf("public key already exists [key_id: %s]", err.KeyID)
163186
}
164187

188+
func (err ErrGPGKeyIDAlreadyUsed) Unwrap() error {
189+
return fs.ErrExist
190+
}
191+
165192
// ErrGPGKeyAccessDenied represents a "GPGKeyAccessDenied" kind of Error.
166193
type ErrGPGKeyAccessDenied struct {
167194
UserID int64
@@ -180,6 +207,10 @@ func (err ErrGPGKeyAccessDenied) Error() string {
180207
err.UserID, err.KeyID)
181208
}
182209

210+
func (err ErrGPGKeyAccessDenied) Unwrap() error {
211+
return fs.ErrPermission
212+
}
213+
183214
// ErrKeyAccessDenied represents a "KeyAccessDenied" kind of error.
184215
type ErrKeyAccessDenied struct {
185216
UserID int64
@@ -198,6 +229,10 @@ func (err ErrKeyAccessDenied) Error() string {
198229
err.UserID, err.KeyID, err.Note)
199230
}
200231

232+
func (err ErrKeyAccessDenied) Unwrap() error {
233+
return fs.ErrPermission
234+
}
235+
201236
// ErrDeployKeyNotExist represents a "DeployKeyNotExist" kind of error.
202237
type ErrDeployKeyNotExist struct {
203238
ID int64
@@ -215,6 +250,10 @@ func (err ErrDeployKeyNotExist) Error() string {
215250
return fmt.Sprintf("Deploy key does not exist [id: %d, key_id: %d, repo_id: %d]", err.ID, err.KeyID, err.RepoID)
216251
}
217252

253+
func (err ErrDeployKeyNotExist) Unwrap() error {
254+
return fs.ErrNotExist
255+
}
256+
218257
// ErrDeployKeyAlreadyExist represents a "DeployKeyAlreadyExist" kind of error.
219258
type ErrDeployKeyAlreadyExist struct {
220259
KeyID int64
@@ -231,6 +270,10 @@ func (err ErrDeployKeyAlreadyExist) Error() string {
231270
return fmt.Sprintf("public key already exists [key_id: %d, repo_id: %d]", err.KeyID, err.RepoID)
232271
}
233272

273+
func (err ErrDeployKeyAlreadyExist) Unwrap() error {
274+
return fs.ErrExist
275+
}
276+
234277
// ErrDeployKeyNameAlreadyUsed represents a "DeployKeyNameAlreadyUsed" kind of error.
235278
type ErrDeployKeyNameAlreadyUsed struct {
236279
RepoID int64
@@ -247,6 +290,10 @@ func (err ErrDeployKeyNameAlreadyUsed) Error() string {
247290
return fmt.Sprintf("public key with name already exists [repo_id: %d, name: %s]", err.RepoID, err.Name)
248291
}
249292

293+
func (err ErrDeployKeyNameAlreadyUsed) Unwrap() error {
294+
return fs.ErrNotExist
295+
}
296+
250297
// ErrSSHInvalidTokenSignature represents a "ErrSSHInvalidTokenSignature" kind of error.
251298
type ErrSSHInvalidTokenSignature struct {
252299
Wrapped error
@@ -262,3 +309,7 @@ func IsErrSSHInvalidTokenSignature(err error) bool {
262309
func (err ErrSSHInvalidTokenSignature) Error() string {
263310
return "the provided signature does not sign the token with the provided key"
264311
}
312+
313+
func (err ErrSSHInvalidTokenSignature) Unwrap() error {
314+
return fs.ErrInvalid
315+
}

models/auth/oauth2.go

+11
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import (
1010
"encoding/base32"
1111
"encoding/base64"
1212
"fmt"
13+
"io/fs"
1314
"net/url"
1415
"strings"
1516

@@ -483,6 +484,11 @@ func (err ErrOAuthClientIDInvalid) Error() string {
483484
return fmt.Sprintf("Client ID invalid [Client ID: %s]", err.ClientID)
484485
}
485486

487+
// Unwrap unwraps this as a ErrNotExist err
488+
func (err ErrOAuthClientIDInvalid) Unwrap() error {
489+
return fs.ErrNotExist
490+
}
491+
486492
// ErrOAuthApplicationNotFound will be thrown if id cannot be found
487493
type ErrOAuthApplicationNotFound struct {
488494
ID int64
@@ -499,6 +505,11 @@ func (err ErrOAuthApplicationNotFound) Error() string {
499505
return fmt.Sprintf("OAuth application not found [ID: %d]", err.ID)
500506
}
501507

508+
// Unwrap unwraps this as a ErrNotExist err
509+
func (err ErrOAuthApplicationNotFound) Unwrap() error {
510+
return fs.ErrNotExist
511+
}
512+
502513
// GetActiveOAuth2ProviderSources returns all actived LoginOAuth2 sources
503514
func GetActiveOAuth2ProviderSources() ([]*Source, error) {
504515
sources := make([]*Source, 0, 1)

models/auth/source.go

+11
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ package auth
77

88
import (
99
"fmt"
10+
"io/fs"
1011
"reflect"
1112

1213
"code.gitea.io/gitea/models/db"
@@ -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 fs.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 fs.ErrExist
393+
}
394+
384395
// ErrSourceInUse represents a "SourceInUse" kind of error.
385396
type ErrSourceInUse struct {
386397
ID int64

models/auth/twofactor.go

+6
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import (
1111
"encoding/base32"
1212
"encoding/base64"
1313
"fmt"
14+
"io/fs"
1415

1516
"code.gitea.io/gitea/models/db"
1617
"code.gitea.io/gitea/modules/secret"
@@ -41,6 +42,11 @@ func (err ErrTwoFactorNotEnrolled) Error() string {
4142
return fmt.Sprintf("user not enrolled in 2FA [uid: %d]", err.UID)
4243
}
4344

45+
// Unwrap unwraps this as a ErrNotExist err
46+
func (err ErrTwoFactorNotEnrolled) Unwrap() error {
47+
return fs.ErrNotExist
48+
}
49+
4450
// TwoFactor represents a two-factor authentication token.
4551
type TwoFactor struct {
4652
ID int64 `xorm:"pk autoincr"`

models/auth/webauthn.go

+6
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ package auth
77
import (
88
"context"
99
"fmt"
10+
"io/fs"
1011
"strings"
1112

1213
"code.gitea.io/gitea/models/db"
@@ -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 fs.ErrNotExist
36+
}
37+
3238
// IsErrWebAuthnCredentialNotExist checks if an error is a ErrWebAuthnCredentialNotExist.
3339
func IsErrWebAuthnCredentialNotExist(err error) bool {
3440
_, ok := err.(ErrWebAuthnCredentialNotExist)

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)

models/db/error.go

+17-2
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ package db
66

77
import (
88
"fmt"
9+
"io/fs"
910
)
1011

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

4647
// ErrNotExist represents a non-exist error.
4748
type ErrNotExist struct {
48-
ID int64
49+
Resource string
50+
ID int64
4951
}
5052

5153
// IsErrNotExist checks if an error is an ErrNotExist
@@ -55,5 +57,18 @@ func IsErrNotExist(err error) bool {
5557
}
5658

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

models/db/name.go

+28-3
Original file line numberDiff line numberDiff line change
@@ -5,21 +5,31 @@
55
package db
66

77
import (
8-
"errors"
98
"fmt"
9+
"io/fs"
1010
"regexp"
1111
"strings"
1212
"unicode/utf8"
1313
)
1414

1515
var (
1616
// ErrNameEmpty name is empty error
17-
ErrNameEmpty = errors.New("Name is empty")
17+
ErrNameEmpty = errNameEmpty{}
1818

1919
// AlphaDashDotPattern characters prohibited in a user name (anything except A-Za-z0-9_.-)
2020
AlphaDashDotPattern = regexp.MustCompile(`[^\w-\.]`)
2121
)
2222

23+
type errNameEmpty struct{}
24+
25+
func (err errNameEmpty) Error() string {
26+
return "name is empty"
27+
}
28+
29+
func (err errNameEmpty) Unwrap() error {
30+
return fs.ErrInvalid
31+
}
32+
2333
// ErrNameReserved represents a "reserved name" error.
2434
type ErrNameReserved struct {
2535
Name string
@@ -35,6 +45,11 @@ func (err ErrNameReserved) Error() string {
3545
return fmt.Sprintf("name is reserved [name: %s]", err.Name)
3646
}
3747

48+
// Unwrap unwraps this as a ErrInvalid err
49+
func (err ErrNameReserved) Unwrap() error {
50+
return fs.ErrInvalid
51+
}
52+
3853
// ErrNamePatternNotAllowed represents a "pattern not allowed" error.
3954
type ErrNamePatternNotAllowed struct {
4055
Pattern string
@@ -50,6 +65,11 @@ func (err ErrNamePatternNotAllowed) Error() string {
5065
return fmt.Sprintf("name pattern is not allowed [pattern: %s]", err.Pattern)
5166
}
5267

68+
// Unwrap unwraps this as a ErrInvalid err
69+
func (err ErrNamePatternNotAllowed) Unwrap() error {
70+
return fs.ErrInvalid
71+
}
72+
5373
// ErrNameCharsNotAllowed represents a "character not allowed in name" error.
5474
type ErrNameCharsNotAllowed struct {
5575
Name string
@@ -62,7 +82,12 @@ func IsErrNameCharsNotAllowed(err error) bool {
6282
}
6383

6484
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)
85+
return fmt.Sprintf("name is invalid [%s]: must be valid alpha or numeric or dash(-_) or dot characters", err.Name)
86+
}
87+
88+
// Unwrap unwraps this as a ErrInvalid err
89+
func (err ErrNameCharsNotAllowed) Unwrap() error {
90+
return fs.ErrInvalid
6691
}
6792

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

0 commit comments

Comments
 (0)