diff options
author | Patrick Steinhardt <psteinhardt@gitlab.com> | 2023-12-05 11:00:01 +0300 |
---|---|---|
committer | Patrick Steinhardt <psteinhardt@gitlab.com> | 2023-12-05 11:00:01 +0300 |
commit | 9171724863b73d3e98c1b2021a6095a58ac128e1 (patch) | |
tree | 9d61ab2a1def1d9a13a0d9da9cc6738c69fe0df0 | |
parent | 14d9f1ae93d635a8b5759e915d0e3c2915e7dd7f (diff) | |
parent | ecb44d3134504c1be057de89585db1c1e199bad1 (diff) |
Merge branch 'kn-error-lint' into 'master'
errors: ensure errors work correctly with wrapped errors
See merge request https://gitlab.com/gitlab-org/gitaly/-/merge_requests/6555
Merged-by: Patrick Steinhardt <psteinhardt@gitlab.com>
Approved-by: Patrick Steinhardt <psteinhardt@gitlab.com>
Approved-by: Justin Tobler <jtobler@gitlab.com>
Reviewed-by: Patrick Steinhardt <psteinhardt@gitlab.com>
Reviewed-by: karthik nayak <knayak@gitlab.com>
Co-authored-by: Karthik Nayak <knayak@gitlab.com>
104 files changed, 274 insertions, 184 deletions
diff --git a/.golangci.yml b/.golangci.yml index 825be0e44..23ed7f966 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -12,6 +12,7 @@ linters: - depguard - errcheck - errname + - errorlint - exportloopref - forbidigo - gci @@ -32,9 +33,9 @@ linters: - paralleltest - revive - rowserrcheck + - sqlclosecheck - staticcheck - stylecheck - - sqlclosecheck - tenv - thelper - unconvert diff --git a/cmd/gitaly/main_test.go b/cmd/gitaly/main_test.go index b649c10aa..339d7cbd6 100644 --- a/cmd/gitaly/main_test.go +++ b/cmd/gitaly/main_test.go @@ -2,6 +2,7 @@ package main import ( "bytes" + "errors" "os/exec" "testing" @@ -63,8 +64,9 @@ func TestGitalyCLI(t *testing.T) { err := cmd.Run() exitCode := 0 - if err != nil { - exitCode = err.(*exec.ExitError).ExitCode() + var exitErr *exec.ExitError + if errors.As(err, &exitErr) { + exitCode = exitErr.ExitCode() } assert.Equal(t, tc.exitCode, exitCode) diff --git a/internal/backup/backup.go b/internal/backup/backup.go index 4b05c9aba..5eed0724a 100644 --- a/internal/backup/backup.go +++ b/internal/backup/backup.go @@ -445,7 +445,7 @@ func (mgr *Manager) negatedKnownRefs(ctx context.Context, step *Step) (io.ReadCl for { var ref git.Reference - if err := d.Decode(&ref); err == io.EOF { + if err := d.Decode(&ref); errors.Is(err, io.EOF) { break } else if err != nil { _ = w.CloseWithError(err) @@ -475,7 +475,7 @@ func (mgr *Manager) readRefs(ctx context.Context, path string) ([]git.Reference, for { var ref git.Reference - if err := d.Decode(&ref); err == io.EOF { + if err := d.Decode(&ref); errors.Is(err, io.EOF) { break } else if err != nil { return refs, fmt.Errorf("read refs: %w", err) diff --git a/internal/backup/sink_test.go b/internal/backup/sink_test.go index 9ff6f3f8a..5eb337147 100644 --- a/internal/backup/sink_test.go +++ b/internal/backup/sink_test.go @@ -2,6 +2,7 @@ package backup import ( "bytes" + "errors" "fmt" "io" "os" @@ -24,8 +25,8 @@ func TestResolveSink(t *testing.T) { sssink, ok := sink.(*StorageServiceSink) require.True(t, ok) _, err := sssink.bucket.List(nil).Next(ctx) - ierr, ok := err.(interface{ Unwrap() error }) - require.True(t, ok) + var ierr interface{ Unwrap() error } + require.True(t, errors.As(err, &ierr)) terr := ierr.Unwrap() require.Contains(t, terr.Error(), expErrMsg) } diff --git a/internal/cache/diskcache.go b/internal/cache/diskcache.go index 8046ae3c5..b442b75df 100644 --- a/internal/cache/diskcache.go +++ b/internal/cache/diskcache.go @@ -209,10 +209,10 @@ func (c *DiskCache) Collect(metrics chan<- prometheus.Metric) { } func (c *DiskCache) countErr(err error) error { - switch err { - case ErrMissingLeaseFile: + switch { + case errors.Is(err, ErrMissingLeaseFile): c.errTotal.WithLabelValues("ErrMissingLeaseFile").Inc() - case ErrPendingExists: + case errors.Is(err, ErrPendingExists): c.errTotal.WithLabelValues("ErrPendingExists").Inc() } return err diff --git a/internal/cli/gitalybackup/create.go b/internal/cli/gitalybackup/create.go index a67cc75da..e1a6ec823 100644 --- a/internal/cli/gitalybackup/create.go +++ b/internal/cli/gitalybackup/create.go @@ -3,6 +3,7 @@ package gitalybackup import ( "context" "encoding/json" + "errors" "fmt" "io" "runtime" @@ -151,7 +152,7 @@ func (cmd *createSubcommand) run(ctx context.Context, logger log.Logger, stdin i decoder := json.NewDecoder(stdin) for { var sr serverRepository - if err := decoder.Decode(&sr); err == io.EOF { + if err := decoder.Decode(&sr); errors.Is(err, io.EOF) { break } else if err != nil { return fmt.Errorf("create: %w", err) diff --git a/internal/cli/praefect/subcmd_dataloss.go b/internal/cli/praefect/subcmd_dataloss.go index 8554b10e3..03ece2ade 100644 --- a/internal/cli/praefect/subcmd_dataloss.go +++ b/internal/cli/praefect/subcmd_dataloss.go @@ -1,6 +1,7 @@ package praefect import ( + "errors" "fmt" "io" "sort" @@ -107,7 +108,7 @@ func datalossAction(ctx *cli.Context) error { for { resp, err := stream.Recv() if err != nil { - if err != io.EOF { + if !errors.Is(err, io.EOF) { return fmt.Errorf("getting response: %w", err) } diff --git a/internal/cli/praefect/subcmd_track_repositories.go b/internal/cli/praefect/subcmd_track_repositories.go index 9de4ddfbf..bde162108 100644 --- a/internal/cli/praefect/subcmd_track_repositories.go +++ b/internal/cli/praefect/subcmd_track_repositories.go @@ -4,6 +4,7 @@ import ( "bufio" "context" "encoding/json" + "errors" "fmt" "io" "os" @@ -215,10 +216,11 @@ func printInvalidRequests(w io.Writer, repoErrs []invalidRequest, pathLines map[ for _, l := range repoErrs { fmt.Fprintf(w, " line %v, relative_path: %q, replica_path: %q\n", l.line, l.relativePath, l.replicaPath) for _, err := range l.errs { - if dup, ok := err.(*dupPathError); ok { + var dupPathErr *dupPathError + if errors.As(err, &dupPathErr) { // The complete set of duplicate reqNums won't be known until input is // fully processed, fetch them now. - err = &dupPathError{path: dup.path, reqNums: pathLines[dup.path]} + err = &dupPathError{path: dupPathErr.path, reqNums: pathLines[dupPathErr.path]} } fmt.Fprintf(w, " %v\n", err) } diff --git a/internal/command/command.go b/internal/command/command.go index 0067f9836..4d9524028 100644 --- a/internal/command/command.go +++ b/internal/command/command.go @@ -410,8 +410,8 @@ func (c *Command) wait() { // The standard library sets exit status -1 if the process was terminated by a signal, // such as the SIGTERM sent when context is done. if exitCode, ok := ExitStatus(c.waitError); ok && exitCode == -1 { - //nolint:gitaly-linters // We can only wrap one - c.waitError = fmt.Errorf("%s: %w", c.waitError, c.context.Err()) + // TODO: use errors.Join() to combine errors instead + c.waitError = fmt.Errorf("%s: %w", c.waitError.Error(), c.context.Err()) } } diff --git a/internal/errors/cfgerror/validate.go b/internal/errors/cfgerror/validate.go index dfbc61e80..f4dfd378a 100644 --- a/internal/errors/cfgerror/validate.go +++ b/internal/errors/cfgerror/validate.go @@ -72,22 +72,26 @@ type ValidationErrors []ValidationError // provided keys or if provided err is not an instance of the ValidationError it will be wrapped // into it. In case the nil is provided nothing happens. func (vs ValidationErrors) Append(err error, keys ...string) ValidationErrors { - switch terr := err.(type) { - case nil: + if err == nil { return vs - case ValidationErrors: - for _, err := range terr { + } + + var validationErrs ValidationErrors + var validationErr ValidationError + + if errors.As(err, &validationErrs) { + for _, err := range validationErrs { vs = append(vs, ValidationError{ Key: append(keys, err.Key...), Cause: err.Cause, }) } - case ValidationError: + } else if errors.As(err, &validationErr) { vs = append(vs, ValidationError{ - Key: append(keys, terr.Key...), - Cause: terr.Cause, + Key: append(keys, validationErr.Key...), + Cause: validationErr.Cause, }) - default: + } else { vs = append(vs, ValidationError{ Key: keys, Cause: err, diff --git a/internal/git/catfile/parser.go b/internal/git/catfile/parser.go index dc437732f..5df14954d 100644 --- a/internal/git/catfile/parser.go +++ b/internal/git/catfile/parser.go @@ -3,6 +3,7 @@ package catfile import ( "bufio" "bytes" + "errors" "fmt" "io" "strconv" @@ -46,7 +47,7 @@ func (p *parser) ParseCommit(object git.Object) (*gitalypb.GitCommit, error) { bytesRemaining := object.ObjectSize() for !lastLine { line, err := p.bufferedReader.ReadString('\n') - if err == io.EOF { + if errors.Is(err, io.EOF) { lastLine = true } else if err != nil { return nil, fmt.Errorf("parse raw commit: header: %w", err) @@ -214,7 +215,7 @@ func (p *parser) parseTag(object git.Object, name []byte) (*gitalypb.Tag, tagged for !lastLine { line, err := p.bufferedReader.ReadString('\n') - if err == io.EOF { + if errors.Is(err, io.EOF) { lastLine = true } else if err != nil { return nil, taggedObject{}, fmt.Errorf("reading tag header: %w", err) diff --git a/internal/git/catfile/tree_entries.go b/internal/git/catfile/tree_entries.go index 4ddbabacf..6274e0395 100644 --- a/internal/git/catfile/tree_entries.go +++ b/internal/git/catfile/tree_entries.go @@ -82,7 +82,7 @@ func extractEntryInfoFromTreeData( for { modeBytes, err := bufReader.ReadBytes(' ') - if err == io.EOF { + if errors.Is(err, io.EOF) { break } if err != nil || len(modeBytes) <= 1 { diff --git a/internal/git/decoder_test.go b/internal/git/decoder_test.go index 39dff5f6e..359bf6f04 100644 --- a/internal/git/decoder_test.go +++ b/internal/git/decoder_test.go @@ -2,6 +2,7 @@ package git_test import ( "bytes" + "errors" "io" "testing" @@ -38,7 +39,7 @@ func TestShowRefDecoder(t *testing.T) { var ref git.Reference err := d.Decode(&ref) - if err == io.EOF { + if errors.Is(err, io.EOF) { break } require.NoError(t, err) diff --git a/internal/git/gitio/hashfile.go b/internal/git/gitio/hashfile.go index fc090b76b..cfa46a73c 100644 --- a/internal/git/gitio/hashfile.go +++ b/internal/git/gitio/hashfile.go @@ -3,6 +3,7 @@ package gitio import ( "bytes" "crypto/sha1" + "errors" "fmt" "hash" "io" @@ -32,7 +33,7 @@ func NewHashfileReader(r io.Reader) *HashfileReader { func (hr *HashfileReader) Read(p []byte) (int, error) { n, err := hr.tee.Read(p) - if err == io.EOF { + if errors.Is(err, io.EOF) { return n, hr.validateChecksum() } diff --git a/internal/git/gitio/trailer.go b/internal/git/gitio/trailer.go index fd60ca8df..17e71122a 100644 --- a/internal/git/gitio/trailer.go +++ b/internal/git/gitio/trailer.go @@ -1,6 +1,7 @@ package gitio import ( + "errors" "fmt" "io" ) @@ -59,7 +60,7 @@ func (tr *TrailerReader) Read(p []byte) (int, error) { n, err := tr.r.Read(tr.buf[tr.end:]) if err != nil { - if err != io.EOF { + if !errors.Is(err, io.EOF) { return 0, err } tr.atEOF = true diff --git a/internal/git/gittest/command.go b/internal/git/gittest/command.go index 30d276961..c5eef143c 100644 --- a/internal/git/gittest/command.go +++ b/internal/git/gittest/command.go @@ -2,6 +2,7 @@ package gittest import ( "context" + "errors" "io" "os" "os/exec" @@ -67,11 +68,12 @@ func ExecOpts(tb testing.TB, cfg config.Cfg, execCfg ExecConfig, args ...string) func handleExecErr(tb testing.TB, cfg config.Cfg, execCfg ExecConfig, args []string, err error) { var stderr []byte - if ee, ok := err.(*exec.ExitError); ok { - if execCfg.ExpectedExitCode == ee.ExitCode() { + var exitErr *exec.ExitError + if errors.As(err, &exitErr) { + if execCfg.ExpectedExitCode == exitErr.ExitCode() { return } - stderr = ee.Stderr + stderr = exitErr.Stderr } tb.Log(cfg.Git.BinPath, args) if len(stderr) > 0 { diff --git a/internal/git/localrepo/bundle.go b/internal/git/localrepo/bundle.go index 53a02a9b9..cef05fa5e 100644 --- a/internal/git/localrepo/bundle.go +++ b/internal/git/localrepo/bundle.go @@ -231,7 +231,7 @@ func (repo *Repo) findBundleHead(ctx context.Context, bundlePath string) (*git.R for { var ref git.Reference err := decoder.Decode(&ref) - if err == io.EOF { + if errors.Is(err, io.EOF) { break } else if err != nil { return nil, fmt.Errorf("find bundle HEAD: %w", err) diff --git a/internal/git/localrepo/parser_test.go b/internal/git/localrepo/parser_test.go index c6fb19211..8edbea8a8 100644 --- a/internal/git/localrepo/parser_test.go +++ b/internal/git/localrepo/parser_test.go @@ -2,6 +2,7 @@ package localrepo import ( "bytes" + "errors" "io" "testing" @@ -75,7 +76,7 @@ func TestParser(t *testing.T) { parsedEntries := Entries{} for { entry, err := parser.NextEntry() - if err == io.EOF { + if errors.Is(err, io.EOF) { break } @@ -132,7 +133,7 @@ func TestParserReadEntryPath(t *testing.T) { parsedPaths := [][]byte{} for { path, err := parser.NextEntryPath() - if err == io.EOF { + if errors.Is(err, io.EOF) { break } diff --git a/internal/git/localrepo/tree_test.go b/internal/git/localrepo/tree_test.go index 6f48ac326..3e7398f18 100644 --- a/internal/git/localrepo/tree_test.go +++ b/internal/git/localrepo/tree_test.go @@ -3,6 +3,7 @@ package localrepo import ( "bytes" "context" + "errors" "os" "path/filepath" "sort" @@ -194,11 +195,11 @@ func TestTreeEntry_Write(t *testing.T) { err := tree.Write(ctx, repo) oid := tree.OID if tc.expectedErrString != "" { - switch e := err.(type) { - case structerr.Error: - stderr := e.Metadata()["stderr"].(string) + var structErr structerr.Error + if errors.As(err, &structErr) { + stderr := structErr.Metadata()["stderr"].(string) strings.Contains(stderr, tc.expectedErrString) - default: + } else { strings.Contains(err.Error(), tc.expectedErrString) } return diff --git a/internal/git/objectpool/disconnect_test.go b/internal/git/objectpool/disconnect_test.go index ff1b0f0d0..6774c9dfc 100644 --- a/internal/git/objectpool/disconnect_test.go +++ b/internal/git/objectpool/disconnect_test.go @@ -431,9 +431,11 @@ func TestRemoveAlternatesIfOk(t *testing.T) { altBackup := altPath + ".backup" err = removeAlternatesIfOk(ctx, repo, altPath, altBackup, logger, nil) require.Error(t, err, "removeAlternatesIfOk should fail") - require.IsType(t, &connectivityError{}, err, "error must be because of connectivity check") - connectivityErr := err.(*connectivityError) - require.IsType(t, &exec.ExitError{}, connectivityErr.error, "error must be because of fsck") + + var connectivityErr *connectivityError + require.True(t, errors.As(err, &connectivityErr), "error must be because of connectivity check") + var exitError *exec.ExitError + require.True(t, errors.As(connectivityErr.error, &exitError), "error must be because of fsck") // We expect objects/info/alternates to have been restored when // removeAlternatesIfOk returned. diff --git a/internal/git/objectpool/pool.go b/internal/git/objectpool/pool.go index 5749d727d..452c6b5db 100644 --- a/internal/git/objectpool/pool.go +++ b/internal/git/objectpool/pool.go @@ -214,7 +214,7 @@ func getAlternateObjectDir(repo *localrepo.Repo) (string, error) { r := bufio.NewReader(altFile) b, err := r.ReadBytes('\n') - if err != nil && err != io.EOF { + if err != nil && !errors.Is(err, io.EOF) { return "", fmt.Errorf("reading alternates file: %w", err) } diff --git a/internal/git/packfile/bitmap.go b/internal/git/packfile/bitmap.go index f5149ce03..5be97e327 100644 --- a/internal/git/packfile/bitmap.go +++ b/internal/git/packfile/bitmap.go @@ -5,6 +5,7 @@ import ( "bytes" "encoding/binary" "encoding/hex" + "errors" "fmt" "io" "math" @@ -93,7 +94,7 @@ func (idx *Index) LoadBitmap() error { } } - if _, err := r.Peek(1); err != io.EOF { + if _, err := r.Peek(1); !errors.Is(err, io.EOF) { return fmt.Errorf("expected EOF, got %w", err) } diff --git a/internal/git/trace2/parser.go b/internal/git/trace2/parser.go index c95427f42..58248cf13 100644 --- a/internal/git/trace2/parser.go +++ b/internal/git/trace2/parser.go @@ -3,6 +3,7 @@ package trace2 import ( "context" "encoding/json" + "errors" "fmt" "io" "strings" @@ -100,7 +101,7 @@ func (p *parser) parse() (*Trace, error) { func (p *parser) readEvent() (*jsonEvent, error) { var event jsonEvent if err := p.decoder.Decode(&event); err != nil { - if err == io.EOF { + if errors.Is(err, io.EOF) { return nil, nil } return nil, fmt.Errorf("decoding event: %w", err) diff --git a/internal/gitaly/archive/tar_entries.go b/internal/gitaly/archive/tar_entries.go index f43ee4080..3d05afa5c 100644 --- a/internal/gitaly/archive/tar_entries.go +++ b/internal/gitaly/archive/tar_entries.go @@ -2,6 +2,7 @@ package archive import ( "archive/tar" + "errors" "io" ) @@ -13,7 +14,7 @@ func TarEntries(r io.Reader) ([]string, error) { for { hdr, err := tr.Next() - if err == io.EOF { + if errors.Is(err, io.EOF) { break } if err != nil { diff --git a/internal/gitaly/diff/diff.go b/internal/gitaly/diff/diff.go index 66075e5ed..b5a535a70 100644 --- a/internal/gitaly/diff/diff.go +++ b/internal/gitaly/diff/diff.go @@ -3,6 +3,7 @@ package diff import ( "bufio" "bytes" + "errors" "fmt" "io" "path/filepath" @@ -165,7 +166,7 @@ func (parser *Parser) Parse() bool { for currentPatchDone := false; !currentPatchDone || parser.patchReader.Buffered() > 0; { // We cannot use bufio.Scanner because the line may be very long. line, err := parser.patchReader.Peek(10) - if err == io.EOF { + if errors.Is(err, io.EOF) { // If the last diff has an empty patch (e.g. --ignore-space-change), // patchReader will read EOF, but Parser not finished. currentPatchDone = true @@ -304,7 +305,7 @@ func (parser *Parser) cacheRawLines(reader *bufio.Reader) { for { line, err := reader.ReadBytes('\n') if err != nil { - if err != io.EOF { + if !errors.Is(err, io.EOF) { parser.err = err parser.finished = true } @@ -361,10 +362,10 @@ func (parser *Parser) findNextPatchFromPath() error { } line, err := parser.patchReader.ReadBytes('\n') - if err != nil && err != io.EOF { + if err != nil && !errors.Is(err, io.EOF) { parser.err = fmt.Errorf("read diff header line: %w", err) return parser.err - } else if err == io.EOF { + } else if errors.Is(err, io.EOF) { return nil } @@ -452,10 +453,10 @@ func (parser *Parser) consumeChunkLine(updateLineStats bool) { line, err = parser.patchReader.ReadSlice('\n') n += len(line) - switch err { - case io.EOF, nil: + switch { + case err == nil || errors.Is(err, io.EOF): done = true - case bufio.ErrBufferFull: + case errors.Is(err, bufio.ErrBufferFull): // long line: keep reading default: parser.err = fmt.Errorf("read chunk line: %w", err) @@ -475,7 +476,7 @@ func (parser *Parser) consumeChunkLine(updateLineStats bool) { func (parser *Parser) consumeLine(updateStats bool) { line, err := parser.patchReader.ReadBytes('\n') - if err != nil && err != io.EOF { + if err != nil && !errors.Is(err, io.EOF) { parser.err = fmt.Errorf("read line: %w", err) return } diff --git a/internal/gitaly/diff/numstat_test.go b/internal/gitaly/diff/numstat_test.go index 5f35a234a..3956a46a3 100644 --- a/internal/gitaly/diff/numstat_test.go +++ b/internal/gitaly/diff/numstat_test.go @@ -1,6 +1,7 @@ package diff import ( + "errors" "io" "os" "testing" @@ -20,7 +21,7 @@ func TestNumStatParser(t *testing.T) { for { stat, err := parser.NextNumStat() - if err == io.EOF { + if errors.Is(err, io.EOF) { break } diff --git a/internal/gitaly/maintenance/optimize.go b/internal/gitaly/maintenance/optimize.go index 84e7da602..029e48822 100644 --- a/internal/gitaly/maintenance/optimize.go +++ b/internal/gitaly/maintenance/optimize.go @@ -50,7 +50,7 @@ func StartWorkers( case <-time.After(timeout): err = fmt.Errorf("timed out after %s", timeout) } - if err != nil && err != context.Canceled { + if err != nil && !errors.Is(err, context.Canceled) { l.WithError(err).Error("maintenance worker shutdown") } } diff --git a/internal/gitaly/maintenance/randomwalker_test.go b/internal/gitaly/maintenance/randomwalker_test.go index 6bdb42980..4fd93ced3 100644 --- a/internal/gitaly/maintenance/randomwalker_test.go +++ b/internal/gitaly/maintenance/randomwalker_test.go @@ -1,6 +1,7 @@ package maintenance import ( + "errors" "math/rand" "os" "path/filepath" @@ -167,7 +168,7 @@ func TestRandomWalk(t *testing.T) { actualPaths := []string{} for { fi, path, err := walker.next() - if err == errIterOver { + if errors.Is(err, errIterOver) { break } require.NoError(t, err) diff --git a/internal/gitaly/repoutil/custom_hooks.go b/internal/gitaly/repoutil/custom_hooks.go index f81d827e8..7d7b4dd70 100644 --- a/internal/gitaly/repoutil/custom_hooks.go +++ b/internal/gitaly/repoutil/custom_hooks.go @@ -57,7 +57,7 @@ func ExtractHooks(ctx context.Context, logger log.Logger, reader io.Reader, path // an error. Since an empty hooks tar is symbolic of a repository having no // hooks, the reader is peeked to check if there is any data present. buf := bufio.NewReader(reader) - if _, err := buf.Peek(1); err == io.EOF { + if _, err := buf.Peek(1); errors.Is(err, io.EOF) { return nil } diff --git a/internal/gitaly/repoutil/custom_hooks_test.go b/internal/gitaly/repoutil/custom_hooks_test.go index 34089e38d..2e7658e8a 100644 --- a/internal/gitaly/repoutil/custom_hooks_test.go +++ b/internal/gitaly/repoutil/custom_hooks_test.go @@ -4,6 +4,7 @@ import ( "archive/tar" "bytes" "context" + "errors" "fmt" "io" "io/fs" @@ -54,7 +55,7 @@ func TestGetCustomHooks_successful(t *testing.T) { fileLength := 0 for { file, err := reader.Next() - if err == io.EOF { + if errors.Is(err, io.EOF) { break } require.NoError(t, err) diff --git a/internal/gitaly/service/blob/blobs_test.go b/internal/gitaly/service/blob/blobs_test.go index f1ccd5e5e..e0345c9a3 100644 --- a/internal/gitaly/service/blob/blobs_test.go +++ b/internal/gitaly/service/blob/blobs_test.go @@ -492,7 +492,7 @@ func BenchmarkListAllBlobs(b *testing.B) { for { _, err := stream.Recv() - if err == io.EOF { + if errors.Is(err, io.EOF) { break } require.NoError(b, err) @@ -539,7 +539,7 @@ func BenchmarkListBlobs(b *testing.B) { for { _, err := stream.Recv() - if err == io.EOF { + if errors.Is(err, io.EOF) { break } require.NoError(b, err) diff --git a/internal/gitaly/service/blob/lfs_pointers_test.go b/internal/gitaly/service/blob/lfs_pointers_test.go index a61336005..74ea55948 100644 --- a/internal/gitaly/service/blob/lfs_pointers_test.go +++ b/internal/gitaly/service/blob/lfs_pointers_test.go @@ -3,6 +3,7 @@ package blob import ( "bytes" "context" + "errors" "io" "sort" "strings" @@ -123,7 +124,7 @@ func TestListLFSPointers(t *testing.T) { var actualLFSPointers []*gitalypb.LFSPointer for { resp, err := stream.Recv() - if err == io.EOF { + if errors.Is(err, io.EOF) { break } testhelper.RequireGrpcError(t, tc.expectedErr, err) @@ -290,7 +291,7 @@ size 12345` var pointers []*gitalypb.LFSPointer for { resp, err := stream.Recv() - if err == io.EOF { + if errors.Is(err, io.EOF) { break } @@ -381,7 +382,7 @@ func TestGetLFSPointers(t *testing.T) { var receivedPointers []*gitalypb.LFSPointer for { resp, err := stream.Recv() - if err == io.EOF { + if errors.Is(err, io.EOF) { break } diff --git a/internal/gitaly/service/cleanup/apply_bfg_object_map_stream.go b/internal/gitaly/service/cleanup/apply_bfg_object_map_stream.go index 5ecf4967f..0c13d57eb 100644 --- a/internal/gitaly/service/cleanup/apply_bfg_object_map_stream.go +++ b/internal/gitaly/service/cleanup/apply_bfg_object_map_stream.go @@ -1,6 +1,7 @@ package cleanup import ( + "errors" "io" "gitlab.com/gitlab-org/gitaly/v16/internal/gitaly/storage" @@ -52,7 +53,8 @@ func (s *server) ApplyBfgObjectMapStream(server gitalypb.CleanupService_ApplyBfg } if err := cleaner.applyObjectMap(ctx, reader.streamReader()); err != nil { - if invalidErr, ok := err.(errInvalidObjectMap); ok { + var invalidErr errInvalidObjectMap + if errors.As(err, &invalidErr) { return structerr.NewInvalidArgument("%w", invalidErr) } diff --git a/internal/gitaly/service/cleanup/apply_bfg_object_map_stream_test.go b/internal/gitaly/service/cleanup/apply_bfg_object_map_stream_test.go index 21ed96b6d..2c37cadfd 100644 --- a/internal/gitaly/service/cleanup/apply_bfg_object_map_stream_test.go +++ b/internal/gitaly/service/cleanup/apply_bfg_object_map_stream_test.go @@ -2,6 +2,7 @@ package cleanup import ( "context" + "errors" "fmt" "io" "strings" @@ -155,7 +156,7 @@ func doStreamingRequest( if rsp != nil { entries = append(entries, rsp.GetEntries()...) } - if err == io.EOF { + if errors.Is(err, io.EOF) { break } if err != nil { diff --git a/internal/gitaly/service/commit/check_objects_exist.go b/internal/gitaly/service/commit/check_objects_exist.go index 4f28e8720..cbddf9222 100644 --- a/internal/gitaly/service/commit/check_objects_exist.go +++ b/internal/gitaly/service/commit/check_objects_exist.go @@ -20,7 +20,7 @@ func (s *server) CheckObjectsExist( request, err := stream.Recv() if err != nil { - if err == io.EOF { + if errors.Is(err, io.EOF) { // Ideally, we'd return an invalid-argument error in case there aren't any // requests. We can't do this though as this would diverge from Praefect's // behaviour, which always returns `io.EOF`. @@ -60,7 +60,7 @@ func (s *server) CheckObjectsExist( request, err = stream.Recv() if err != nil { - if err == io.EOF { + if errors.Is(err, io.EOF) { break } diff --git a/internal/gitaly/service/commit/commit_messages_test.go b/internal/gitaly/service/commit/commit_messages_test.go index efd786f41..f24fa74b8 100644 --- a/internal/gitaly/service/commit/commit_messages_test.go +++ b/internal/gitaly/service/commit/commit_messages_test.go @@ -1,6 +1,7 @@ package commit import ( + "errors" "io" "strings" "testing" @@ -101,7 +102,7 @@ func readAllMessagesFromClient(t *testing.T, c gitalypb.CommitService_GetCommitM for { resp, err := c.Recv() - if err == io.EOF { + if errors.Is(err, io.EOF) { break } require.NoError(t, err) diff --git a/internal/gitaly/service/commit/commit_signatures.go b/internal/gitaly/service/commit/commit_signatures.go index 079d954e4..9dc5a9819 100644 --- a/internal/gitaly/service/commit/commit_signatures.go +++ b/internal/gitaly/service/commit/commit_signatures.go @@ -88,7 +88,7 @@ func extractSignature(reader io.Reader) ([]byte, []byte, error) { for { line, err := bufferedReader.ReadBytes('\n') - if err == io.EOF { + if errors.Is(err, io.EOF) { commitText = append(commitText, line...) break } diff --git a/internal/gitaly/service/commit/commits_by_message_test.go b/internal/gitaly/service/commit/commits_by_message_test.go index 2ef840600..4dbaa8ba7 100644 --- a/internal/gitaly/service/commit/commits_by_message_test.go +++ b/internal/gitaly/service/commit/commits_by_message_test.go @@ -1,6 +1,7 @@ package commit import ( + "errors" "io" "testing" @@ -159,7 +160,7 @@ Commit #1`), gittest.WithBranch("few-commits"), gittest.WithParents(commit10ID)) receivedCommits := getAllCommits(t, func() (gitCommitsGetter, error) { resp, err := c.Recv() - if err != nil && err != io.EOF { + if err != nil && !errors.Is(err, io.EOF) { testhelper.RequireGrpcError(t, tc.expectedErr, err) err = io.EOF } diff --git a/internal/gitaly/service/commit/filter_shas_with_signatures.go b/internal/gitaly/service/commit/filter_shas_with_signatures.go index 237cc0319..4cc924340 100644 --- a/internal/gitaly/service/commit/filter_shas_with_signatures.go +++ b/internal/gitaly/service/commit/filter_shas_with_signatures.go @@ -54,7 +54,7 @@ func (s *server) filterShasWithSignatures(bidi gitalypb.CommitService_FilterShas } request, err = bidi.Recv() - if err == io.EOF { + if errors.Is(err, io.EOF) { return nil } diff --git a/internal/gitaly/service/commit/find_commits_test.go b/internal/gitaly/service/commit/find_commits_test.go index 50648526c..8f7b5492c 100644 --- a/internal/gitaly/service/commit/find_commits_test.go +++ b/internal/gitaly/service/commit/find_commits_test.go @@ -2,6 +2,7 @@ package commit import ( "context" + "errors" "fmt" "io" "path/filepath" @@ -764,7 +765,7 @@ func benchmarkCommitStatsN(b *testing.B, ctx context.Context, request *gitalypb. for { response, err := stream.Recv() - if err == io.EOF { + if errors.Is(err, io.EOF) { break } require.NoError(b, err) @@ -791,7 +792,7 @@ func benchmarkFindCommitsWithStat(b *testing.B, ctx context.Context, request *gi for { _, err := stream.Recv() - if err == io.EOF { + if errors.Is(err, io.EOF) { break } require.NoError(b, err) diff --git a/internal/gitaly/service/commit/get_tree_entries_test.go b/internal/gitaly/service/commit/get_tree_entries_test.go index 203704947..02b27bcaa 100644 --- a/internal/gitaly/service/commit/get_tree_entries_test.go +++ b/internal/gitaly/service/commit/get_tree_entries_test.go @@ -1,6 +1,7 @@ package commit import ( + "errors" "fmt" "io" "strconv" @@ -1487,7 +1488,7 @@ func getTreeEntriesFromTreeEntryClient(t *testing.T, client gitalypb.CommitServi resp, err := client.Recv() if expectedError == nil { - if err == io.EOF { + if errors.Is(err, io.EOF) { break } require.NoError(t, err) diff --git a/internal/gitaly/service/commit/languages.go b/internal/gitaly/service/commit/languages.go index 4248d44ea..5e0944981 100644 --- a/internal/gitaly/service/commit/languages.go +++ b/internal/gitaly/service/commit/languages.go @@ -92,8 +92,7 @@ func (ls languageSorter) Less(i, j int) bool { return ls[i].Share > ls[j].Share func (s *server) lookupRevision(ctx context.Context, repo git.RepositoryExecutor, revision string) (string, error) { rev, err := s.checkRevision(ctx, repo, revision) if err != nil { - switch err { - case errAmbigRef: + if errors.Is(err, errAmbigRef) { fullRev, err := s.disambiguateRevision(ctx, repo, revision) if err != nil { return "", err @@ -103,7 +102,7 @@ func (s *server) lookupRevision(ctx context.Context, repo git.RepositoryExecutor if err != nil { return "", err } - default: + } else { return "", err } } diff --git a/internal/gitaly/service/commit/list_all_commits_test.go b/internal/gitaly/service/commit/list_all_commits_test.go index 952d83cad..d95b74568 100644 --- a/internal/gitaly/service/commit/list_all_commits_test.go +++ b/internal/gitaly/service/commit/list_all_commits_test.go @@ -1,6 +1,7 @@ package commit import ( + "errors" "io" "os" "path/filepath" @@ -213,7 +214,7 @@ func BenchmarkListAllCommits(b *testing.B) { for { _, err := stream.Recv() - if err == io.EOF { + if errors.Is(err, io.EOF) { break } require.NoError(b, err) diff --git a/internal/gitaly/service/commit/list_commits_by_oid_test.go b/internal/gitaly/service/commit/list_commits_by_oid_test.go index 4c8e7e635..1a8148d85 100644 --- a/internal/gitaly/service/commit/list_commits_by_oid_test.go +++ b/internal/gitaly/service/commit/list_commits_by_oid_test.go @@ -1,6 +1,7 @@ package commit import ( + "errors" "fmt" "io" "testing" @@ -102,7 +103,7 @@ func TestListCommitsByOid(t *testing.T) { receivedCommits := getAllCommits(t, func() (gitCommitsGetter, error) { getter, err := c.Recv() - if tc.expectedErr != nil || err != nil && err != io.EOF { + if tc.expectedErr != nil || err != nil && !errors.Is(err, io.EOF) { testhelper.RequireGrpcError(t, tc.expectedErr, err) return getter, io.EOF } diff --git a/internal/gitaly/service/commit/list_commits_by_ref_name_test.go b/internal/gitaly/service/commit/list_commits_by_ref_name_test.go index e4c426eac..fa0d8ccc4 100644 --- a/internal/gitaly/service/commit/list_commits_by_ref_name_test.go +++ b/internal/gitaly/service/commit/list_commits_by_ref_name_test.go @@ -2,6 +2,7 @@ package commit import ( "context" + "errors" "fmt" "io" "testing" @@ -422,7 +423,7 @@ func consumeGetByRefNameResponse(t *testing.T, c gitalypb.CommitService_ListComm var receivedCommitRefs []*gitalypb.ListCommitsByRefNameResponse_CommitForRef for { resp, err := c.Recv() - if err == io.EOF { + if errors.Is(err, io.EOF) { break } else if err != nil { testhelper.RequireGrpcError(t, expectedErr, err) diff --git a/internal/gitaly/service/commit/list_files.go b/internal/gitaly/service/commit/list_files.go index 8379462f1..ffe3f568b 100644 --- a/internal/gitaly/service/commit/list_files.go +++ b/internal/gitaly/service/commit/list_files.go @@ -1,6 +1,7 @@ package commit import ( + "errors" "fmt" "io" @@ -96,7 +97,7 @@ func (s *server) listFiles(repo git.RepositoryExecutor, revision string, stream for parser := localrepo.NewParser(cmd, objectHash); ; { entry, err := parser.NextEntry() - if err == io.EOF { + if errors.Is(err, io.EOF) { break } if err != nil { diff --git a/internal/gitaly/service/commit/list_last_commits_for_tree.go b/internal/gitaly/service/commit/list_last_commits_for_tree.go index 0514a8e1e..fa7e7d0f7 100644 --- a/internal/gitaly/service/commit/list_last_commits_for_tree.go +++ b/internal/gitaly/service/commit/list_last_commits_for_tree.go @@ -2,6 +2,7 @@ package commit import ( "context" + "errors" "fmt" "io" "sort" @@ -99,7 +100,7 @@ func getLSTreeEntries(parser *localrepo.Parser) (localrepo.Entries, error) { for { entry, err := parser.NextEntry() if err != nil { - if err == io.EOF { + if errors.Is(err, io.EOF) { break } diff --git a/internal/gitaly/service/commit/testhelper_test.go b/internal/gitaly/service/commit/testhelper_test.go index 654861279..8eaea6fb0 100644 --- a/internal/gitaly/service/commit/testhelper_test.go +++ b/internal/gitaly/service/commit/testhelper_test.go @@ -2,6 +2,7 @@ package commit import ( "context" + "errors" "fmt" "io" "testing" @@ -85,7 +86,7 @@ func getAllCommits(tb testing.TB, getter func() (gitCommitsGetter, error)) []*gi var commits []*gitalypb.GitCommit for { resp, err := getter() - if err == io.EOF { + if errors.Is(err, io.EOF) { return commits } require.NoError(tb, err) diff --git a/internal/gitaly/service/conflicts/list_conflict_files.go b/internal/gitaly/service/conflicts/list_conflict_files.go index d5f62a810..02ba3e290 100644 --- a/internal/gitaly/service/conflicts/list_conflict_files.go +++ b/internal/gitaly/service/conflicts/list_conflict_files.go @@ -149,7 +149,7 @@ func (s *server) conflictFilesWithGitMergeTree( var content bytes.Buffer _, err = content.ReadFrom(object) - if err != nil && err != io.EOF { + if err != nil && !errors.Is(err, io.EOF) { return structerr.NewInternal("reading conflict object: %w", err) } diff --git a/internal/gitaly/service/conflicts/list_conflict_files_test.go b/internal/gitaly/service/conflicts/list_conflict_files_test.go index bfe2018d5..6eb59a95a 100644 --- a/internal/gitaly/service/conflicts/list_conflict_files_test.go +++ b/internal/gitaly/service/conflicts/list_conflict_files_test.go @@ -2,6 +2,7 @@ package conflicts import ( "context" + "errors" "fmt" "io" "strings" @@ -645,7 +646,7 @@ func getConflictFiles(t *testing.T, c gitalypb.ConflictsService_ListConflictFile for { var r *gitalypb.ListConflictFilesResponse r, err = c.Recv() - if err == io.EOF { + if errors.Is(err, io.EOF) { break } else if err != nil { return files, err diff --git a/internal/gitaly/service/conflicts/resolve_conflicts.go b/internal/gitaly/service/conflicts/resolve_conflicts.go index 43a60ba7b..ba91e4d49 100644 --- a/internal/gitaly/service/conflicts/resolve_conflicts.go +++ b/internal/gitaly/service/conflicts/resolve_conflicts.go @@ -107,7 +107,7 @@ func (s *server) resolveConflicts(header *gitalypb.ResolveConflictsRequestHeader b := bytes.NewBuffer(nil) for { req, err := stream.Recv() - if err == io.EOF { + if errors.Is(err, io.EOF) { break } if err != nil { diff --git a/internal/gitaly/service/diff/commit_delta_test.go b/internal/gitaly/service/diff/commit_delta_test.go index 68f3a313d..64b8ffce0 100644 --- a/internal/gitaly/service/diff/commit_delta_test.go +++ b/internal/gitaly/service/diff/commit_delta_test.go @@ -1,6 +1,7 @@ package diff import ( + "errors" "io" "testing" @@ -282,7 +283,7 @@ func assertExactReceivedDeltas(t *testing.T, client gitalypb.DiffService_CommitD var actualDeltas []*gitalypb.CommitDelta for { fetchedDeltas, err := client.Recv() - if err == io.EOF { + if errors.Is(err, io.EOF) { break } require.NoError(t, err) diff --git a/internal/gitaly/service/diff/commit_diff_test.go b/internal/gitaly/service/diff/commit_diff_test.go index 938137629..8f9634269 100644 --- a/internal/gitaly/service/diff/commit_diff_test.go +++ b/internal/gitaly/service/diff/commit_diff_test.go @@ -1,6 +1,7 @@ package diff import ( + "errors" "io" "strings" "testing" @@ -1146,7 +1147,7 @@ func getDiffsFromCommitDiffClient(t *testing.T, client gitalypb.DiffService_Comm for { fetchedDiff, err := client.Recv() - if err == io.EOF { + if errors.Is(err, io.EOF) { break } require.NoError(t, err) diff --git a/internal/gitaly/service/diff/find_changed_paths.go b/internal/gitaly/service/diff/find_changed_paths.go index 849073252..4d377e1f0 100644 --- a/internal/gitaly/service/diff/find_changed_paths.go +++ b/internal/gitaly/service/diff/find_changed_paths.go @@ -101,7 +101,7 @@ func parsePaths(reader *bufio.Reader, chunker *chunk.Chunker) error { for { paths, err := nextPath(reader) if err != nil { - if err == io.EOF { + if errors.Is(err, io.EOF) { break } diff --git a/internal/gitaly/service/diff/find_changed_paths_test.go b/internal/gitaly/service/diff/find_changed_paths_test.go index 2d182b352..52e5ce17a 100644 --- a/internal/gitaly/service/diff/find_changed_paths_test.go +++ b/internal/gitaly/service/diff/find_changed_paths_test.go @@ -1,6 +1,7 @@ package diff import ( + "errors" "io" "testing" @@ -718,7 +719,7 @@ func TestFindChangedPathsRequest_success(t *testing.T) { var paths []*gitalypb.ChangedPaths for { fetchedPaths, err := stream.Recv() - if err == io.EOF { + if errors.Is(err, io.EOF) { break } @@ -911,7 +912,7 @@ func TestFindChangedPathsRequest_deprecated(t *testing.T) { var paths []*gitalypb.ChangedPaths for { fetchedPaths, err := stream.Recv() - if err == io.EOF { + if errors.Is(err, io.EOF) { break } diff --git a/internal/gitaly/service/diff/numstat.go b/internal/gitaly/service/diff/numstat.go index 07ff5e237..3b0117d0f 100644 --- a/internal/gitaly/service/diff/numstat.go +++ b/internal/gitaly/service/diff/numstat.go @@ -1,6 +1,7 @@ package diff import ( + "errors" "io" "gitlab.com/gitlab-org/gitaly/v16/internal/git" @@ -31,7 +32,7 @@ func (s *server) DiffStats(in *gitalypb.DiffStatsRequest, stream gitalypb.DiffSe for { stat, err := parser.NextNumStat() if err != nil { - if err == io.EOF { + if errors.Is(err, io.EOF) { break } diff --git a/internal/gitaly/service/diff/numstat_test.go b/internal/gitaly/service/diff/numstat_test.go index 6cfe58d49..449b316e1 100644 --- a/internal/gitaly/service/diff/numstat_test.go +++ b/internal/gitaly/service/diff/numstat_test.go @@ -1,6 +1,7 @@ package diff import ( + "errors" "io" "testing" @@ -44,7 +45,7 @@ func TestDiffStats_successful(t *testing.T) { var actualStats []*gitalypb.DiffStats for { response, err := stream.Recv() - if err == io.EOF { + if errors.Is(err, io.EOF) { break } require.NoError(t, err) diff --git a/internal/gitaly/service/hook/post_receive_test.go b/internal/gitaly/service/hook/post_receive_test.go index 5d2af9eba..5174ff5ba 100644 --- a/internal/gitaly/service/hook/post_receive_test.go +++ b/internal/gitaly/service/hook/post_receive_test.go @@ -2,6 +2,7 @@ package hook import ( "bytes" + "errors" "io" "path/filepath" "testing" @@ -150,7 +151,7 @@ func TestHooksMissingStdin(t *testing.T) { var status int32 for { resp, err := stream.Recv() - if err == io.EOF { + if errors.Is(err, io.EOF) { break } @@ -286,7 +287,7 @@ To create a merge request for okay, visit: var stdout, stderr bytes.Buffer for { resp, err := stream.Recv() - if err == io.EOF { + if errors.Is(err, io.EOF) { break } diff --git a/internal/gitaly/service/hook/pre_receive_test.go b/internal/gitaly/service/hook/pre_receive_test.go index 921e19c50..82017dee2 100644 --- a/internal/gitaly/service/hook/pre_receive_test.go +++ b/internal/gitaly/service/hook/pre_receive_test.go @@ -2,6 +2,7 @@ package hook import ( "bytes" + "errors" "fmt" "io" "net/http" @@ -55,7 +56,7 @@ func sendPreReceiveHookRequest(t *testing.T, stream gitalypb.HookService_PreRece var stdout, stderr bytes.Buffer for { resp, err := stream.Recv() - if err == io.EOF { + if errors.Is(err, io.EOF) { break } if err != nil { diff --git a/internal/gitaly/service/hook/update_test.go b/internal/gitaly/service/hook/update_test.go index 2eb7bfb3e..d6424b65a 100644 --- a/internal/gitaly/service/hook/update_test.go +++ b/internal/gitaly/service/hook/update_test.go @@ -2,6 +2,7 @@ package hook import ( "bytes" + "errors" "fmt" "io" "strings" @@ -82,7 +83,7 @@ exit 1 var stderr, stdout bytes.Buffer for { resp, err := stream.Recv() - if err == io.EOF { + if errors.Is(err, io.EOF) { break } require.NoError(t, err, "when receiving stream") diff --git a/internal/gitaly/service/internalgitaly/walkrepos_test.go b/internal/gitaly/service/internalgitaly/walkrepos_test.go index 448d29784..f4a8d95f4 100644 --- a/internal/gitaly/service/internalgitaly/walkrepos_test.go +++ b/internal/gitaly/service/internalgitaly/walkrepos_test.go @@ -1,6 +1,7 @@ package internalgitaly import ( + "errors" "io" "os" "path/filepath" @@ -125,7 +126,7 @@ func consumeWalkReposStream(t *testing.T, stream gitalypb.InternalGitaly_WalkRep var repos []*gitalypb.WalkReposResponse for { resp, err := stream.Recv() - if err == io.EOF { + if errors.Is(err, io.EOF) { break } else { require.NoError(t, err) diff --git a/internal/gitaly/service/objectpool/util.go b/internal/gitaly/service/objectpool/util.go index 0de4bc753..49f91a033 100644 --- a/internal/gitaly/service/objectpool/util.go +++ b/internal/gitaly/service/objectpool/util.go @@ -34,7 +34,7 @@ func ExtractPool(req PoolRequest) (*gitalypb.Repository, error) { func (s *server) poolForRequest(req PoolRequest) (*objectpool.ObjectPool, error) { pool, err := objectpool.FromProto(s.logger, s.locator, s.gitCmdFactory, s.catfileCache, s.txManager, s.housekeepingManager, req.GetObjectPool()) if err != nil { - if err == objectpool.ErrInvalidPoolDir { + if errors.Is(err, objectpool.ErrInvalidPoolDir) { return nil, errInvalidPoolDir } diff --git a/internal/gitaly/service/operations/apply_patch_test.go b/internal/gitaly/service/operations/apply_patch_test.go index 281f27600..37f0dcd05 100644 --- a/internal/gitaly/service/operations/apply_patch_test.go +++ b/internal/gitaly/service/operations/apply_patch_test.go @@ -1,6 +1,7 @@ package operations import ( + "errors" "fmt" "io" "testing" @@ -541,7 +542,7 @@ To restore the original branch and stop patching, run "git am --abort". // // Abort the loop here so that we can observe the actual // error in `CloseAndRecv()`. - if err == io.EOF { + if errors.Is(err, io.EOF) { break outerLoop } diff --git a/internal/gitaly/service/operations/commit_files.go b/internal/gitaly/service/operations/commit_files.go index 3e8389ea7..ce2fd9bfb 100644 --- a/internal/gitaly/service/operations/commit_files.go +++ b/internal/gitaly/service/operations/commit_files.go @@ -372,28 +372,29 @@ func applyAction( // translateLocalrepoError converts errors returned by the `localrepo` package into nice errors that we can return to the caller. // Most importantly, these errors will carry metadata that helps to figure out what exactly has gone wrong. func translateError(err error, path string) error { - switch err { - case localrepo.ErrEntryNotFound, localrepo.ErrObjectNotFound: + switch { + case errors.Is(err, localrepo.ErrEntryNotFound) || + errors.Is(err, localrepo.ErrObjectNotFound): return indexError{ path: path, errorType: errFileNotFound, } - case localrepo.ErrEmptyPath, - localrepo.ErrPathTraversal, - localrepo.ErrAbsolutePath, - localrepo.ErrDisallowedPath: + case errors.Is(err, localrepo.ErrEmptyPath) || + errors.Is(err, localrepo.ErrPathTraversal) || + errors.Is(err, localrepo.ErrAbsolutePath) || + errors.Is(err, localrepo.ErrDisallowedPath): //The error coming back from git2go has the path in single //quotes. This is to match the git2go error for now. //nolint:gitaly-linters return unknownIndexError( fmt.Sprintf("invalid path: '%s'", path), ) - case localrepo.ErrPathTraversal: + case errors.Is(err, localrepo.ErrPathTraversal): return indexError{ path: path, errorType: errDirectoryTraversal, } - case localrepo.ErrEntryExists: + case errors.Is(err, localrepo.ErrEntryExists): return indexError{ path: path, errorType: errFileExists, diff --git a/internal/gitaly/service/operations/submodules.go b/internal/gitaly/service/operations/submodules.go index bef9e5d62..f543d57dd 100644 --- a/internal/gitaly/service/operations/submodules.go +++ b/internal/gitaly/service/operations/submodules.go @@ -222,7 +222,7 @@ func (s *Server) updateSubmodule(ctx context.Context, quarantineRepo *localrepo. return nil }, ); err != nil { - if err == localrepo.ErrEntryNotFound { + if errors.Is(err, localrepo.ErrEntryNotFound) { return "", fmt.Errorf("submodule: %s", legacyErrPrefixInvalidSubmodulePath) } diff --git a/internal/gitaly/service/ref/find_all_tags_test.go b/internal/gitaly/service/ref/find_all_tags_test.go index 5f1e982ce..91288dca5 100644 --- a/internal/gitaly/service/ref/find_all_tags_test.go +++ b/internal/gitaly/service/ref/find_all_tags_test.go @@ -2,6 +2,7 @@ package ref import ( "context" + "errors" "fmt" "io" "strings" @@ -747,7 +748,7 @@ func BenchmarkFindAllTags(b *testing.B) { for { _, err := stream.Recv() - if err == io.EOF { + if errors.Is(err, io.EOF) { break } require.NoError(b, err) diff --git a/internal/gitaly/service/ref/list_refs_test.go b/internal/gitaly/service/ref/list_refs_test.go index b831f22e1..977bf2bd7 100644 --- a/internal/gitaly/service/ref/list_refs_test.go +++ b/internal/gitaly/service/ref/list_refs_test.go @@ -1,6 +1,7 @@ package ref import ( + "errors" "io" "testing" "time" @@ -228,7 +229,7 @@ func TestServer_ListRefs(t *testing.T) { var refs []*gitalypb.ListRefsResponse_Reference for { r, err := c.Recv() - if err == io.EOF { + if errors.Is(err, io.EOF) { break } if tc.expectedError == "" && tc.expectedGrpcError == 0 { diff --git a/internal/gitaly/service/ref/tag_messages_test.go b/internal/gitaly/service/ref/tag_messages_test.go index b090e8d13..007f877cc 100644 --- a/internal/gitaly/service/ref/tag_messages_test.go +++ b/internal/gitaly/service/ref/tag_messages_test.go @@ -1,6 +1,7 @@ package ref import ( + "errors" "io" "strings" "testing" @@ -88,7 +89,7 @@ func TestFailedGetTagMessagesRequest(t *testing.T) { func readAllMessagesFromClient(t *testing.T, c gitalypb.RefService_GetTagMessagesClient) (messages []*gitalypb.GetTagMessagesResponse) { for { resp, err := c.Recv() - if err == io.EOF { + if errors.Is(err, io.EOF) { break } require.NoError(t, err) diff --git a/internal/gitaly/service/repository/get_custom_hooks_test.go b/internal/gitaly/service/repository/get_custom_hooks_test.go index e9157c597..cbbb6a37b 100644 --- a/internal/gitaly/service/repository/get_custom_hooks_test.go +++ b/internal/gitaly/service/repository/get_custom_hooks_test.go @@ -3,6 +3,7 @@ package repository import ( "archive/tar" "context" + "errors" "fmt" "io" "os" @@ -74,7 +75,7 @@ func TestGetCustomHooks_successful(t *testing.T) { fileLength := 0 for { file, err := reader.Next() - if err == io.EOF { + if errors.Is(err, io.EOF) { break } require.NoError(t, err) diff --git a/internal/gitaly/service/repository/license.go b/internal/gitaly/service/repository/license.go index dcbf50aa9..62be93182 100644 --- a/internal/gitaly/service/repository/license.go +++ b/internal/gitaly/service/repository/license.go @@ -219,7 +219,7 @@ func (f *gitFiler) ReadDir(string) ([]filer.File, error) { for { entry, err := tree.NextEntry() if err != nil { - if err == io.EOF { + if errors.Is(err, io.EOF) { break } return nil, err diff --git a/internal/gitaly/service/repository/raw_changes.go b/internal/gitaly/service/repository/raw_changes.go index b864375d3..49f044d5d 100644 --- a/internal/gitaly/service/repository/raw_changes.go +++ b/internal/gitaly/service/repository/raw_changes.go @@ -2,6 +2,7 @@ package repository import ( "context" + "errors" "fmt" "io" "regexp" @@ -88,7 +89,7 @@ func (s *server) getRawChanges(stream gitalypb.RepositoryService_GetRawChangesSe for { d, err := p.NextDiff() - if err == io.EOF { + if errors.Is(err, io.EOF) { break // happy path } if err != nil { diff --git a/internal/gitaly/service/repository/search_files.go b/internal/gitaly/service/repository/search_files.go index 835732465..d4f1e12a4 100644 --- a/internal/gitaly/service/repository/search_files.go +++ b/internal/gitaly/service/repository/search_files.go @@ -194,7 +194,7 @@ func parseLsTree(objectHash git.ObjectHash, cmd *command.Command, filter *regexp for { path, err := parser.NextEntryPath() if err != nil { - if err == io.EOF { + if errors.Is(err, io.EOF) { break } return nil, err diff --git a/internal/gitaly/service/repository/search_files_test.go b/internal/gitaly/service/repository/search_files_test.go index 4a2b144d1..cf6b40c5c 100644 --- a/internal/gitaly/service/repository/search_files_test.go +++ b/internal/gitaly/service/repository/search_files_test.go @@ -1,6 +1,7 @@ package repository import ( + "errors" "fmt" "io" "strings" @@ -545,7 +546,7 @@ func consumeFilenameByContentChunked(stream gitalypb.RepositoryService_SearchFil for { resp, err := stream.Recv() - if err == io.EOF { + if errors.Is(err, io.EOF) { break } if err != nil { @@ -566,7 +567,7 @@ func consumeFilenameByName(stream gitalypb.RepositoryService_SearchFilesByNameCl var filenames []string for { resp, err := stream.Recv() - if err == io.EOF { + if errors.Is(err, io.EOF) { break } if err != nil { diff --git a/internal/gitaly/service/smarthttp/cache.go b/internal/gitaly/service/smarthttp/cache.go index df51f9a17..515029c0f 100644 --- a/internal/gitaly/service/smarthttp/cache.go +++ b/internal/gitaly/service/smarthttp/cache.go @@ -2,6 +2,7 @@ package smarthttp import ( "context" + "errors" "io" "sync" @@ -68,8 +69,8 @@ func (c infoRefCache) tryCache(ctx context.Context, in *gitalypb.InfoRefsRequest }) stream, err := c.streamer.GetStream(ctx, in.Repository, in) - switch err { - case nil: + switch { + case err == nil: defer stream.Close() countHit() @@ -81,7 +82,7 @@ func (c infoRefCache) tryCache(ctx context.Context, in *gitalypb.InfoRefsRequest return nil - case cache.ErrReqNotFound: + case errors.Is(err, cache.ErrReqNotFound): countMiss() c.logger.InfoContext(ctx, "cache miss for InfoRefsUploadPack response") diff --git a/internal/grpc/backchannel/backchannel_example_test.go b/internal/grpc/backchannel/backchannel_example_test.go index 791da3730..b28bb68cf 100644 --- a/internal/grpc/backchannel/backchannel_example_test.go +++ b/internal/grpc/backchannel/backchannel_example_test.go @@ -2,6 +2,7 @@ package backchannel_test import ( "context" + "errors" "fmt" "net" "os" @@ -47,7 +48,7 @@ func Example() { fmt.Println("Gitaly received a transactional mutator") backchannelID, err := backchannel.GetPeerID(stream.Context()) - if err == backchannel.ErrNonMultiplexedConnection { + if errors.Is(err, backchannel.ErrNonMultiplexedConnection) { // This call is from a client that is not multiplexing aware. Client is not // Praefect, so no need to perform voting. The client could be for example // GitLab calling Gitaly directly. diff --git a/internal/grpc/backchannel/backchannel_test.go b/internal/grpc/backchannel/backchannel_test.go index 6791f944a..d3233ed55 100644 --- a/internal/grpc/backchannel/backchannel_test.go +++ b/internal/grpc/backchannel/backchannel_test.go @@ -54,7 +54,7 @@ func TestBackchannel_concurrentRequestsFromMultipleClients(t *testing.T) { gitalypb.RegisterRefTransactionServer(srv, mockTransactionServer{ voteTransactionFunc: func(ctx context.Context, req *gitalypb.VoteTransactionRequest) (*gitalypb.VoteTransactionResponse, error) { peerID, err := GetPeerID(ctx) - if err == ErrNonMultiplexedConnection { + if errors.Is(err, ErrNonMultiplexedConnection) { return nil, errNonMultiplexed } assert.NoError(t, err) diff --git a/internal/grpc/client/dial_test.go b/internal/grpc/client/dial_test.go index 7036d2a90..39636f213 100644 --- a/internal/grpc/client/dial_test.go +++ b/internal/grpc/client/dial_test.go @@ -1,6 +1,7 @@ package client import ( + "errors" "net" "testing" @@ -29,7 +30,7 @@ func TestDial(t *testing.T) { grpc.Creds(lm), grpc.UnknownServiceHandler(func(srv interface{}, stream grpc.ServerStream) error { _, err := backchannel.GetPeerID(stream.Context()) - if err == backchannel.ErrNonMultiplexedConnection { + if errors.Is(err, backchannel.ErrNonMultiplexedConnection) { return errNonMuxed } diff --git a/internal/grpc/dnsresolver/resolver.go b/internal/grpc/dnsresolver/resolver.go index 28396582b..df21fb198 100644 --- a/internal/grpc/dnsresolver/resolver.go +++ b/internal/grpc/dnsresolver/resolver.go @@ -2,6 +2,7 @@ package dnsresolver import ( "context" + "errors" "net" "sync" "time" @@ -131,7 +132,8 @@ func (d *dnsResolver) resolve() (*resolver.State, error) { // Backoff). // - Other errors should be suppressed (they may represent the absence of a TXT record). func handleDNSError(err error) error { - if dnsErr, ok := err.(*net.DNSError); ok && !dnsErr.IsTimeout && !dnsErr.IsTemporary { + var dnsErr *net.DNSError + if errors.As(err, &dnsErr) && !dnsErr.IsTimeout && !dnsErr.IsTemporary { return nil } diff --git a/internal/grpc/grpcstats/stats_test.go b/internal/grpc/grpcstats/stats_test.go index b3bfa881c..07239cca3 100644 --- a/internal/grpc/grpcstats/stats_test.go +++ b/internal/grpc/grpcstats/stats_test.go @@ -2,6 +2,7 @@ package grpcstats import ( "context" + "errors" "io" "net" "os" @@ -35,7 +36,7 @@ func (ts testService) UnaryCall(context.Context, *grpc_testing.SimpleRequest) (* func (ts testService) HalfDuplexCall(stream grpc_testing.TestService_HalfDuplexCallServer) error { for { if _, err := stream.Recv(); err != nil { - if err == io.EOF { + if errors.Is(err, io.EOF) { break } return err @@ -127,7 +128,7 @@ func TestPayloadBytes(t *testing.T) { defer close(done) for { _, err := call.Recv() - if err == io.EOF { + if errors.Is(err, io.EOF) { return } assert.NoError(t, err) diff --git a/internal/grpc/middleware/customfieldshandler/customfields_handler_test.go b/internal/grpc/middleware/customfieldshandler/customfields_handler_test.go index e92a4ec3b..65874dae7 100644 --- a/internal/grpc/middleware/customfieldshandler/customfields_handler_test.go +++ b/internal/grpc/middleware/customfieldshandler/customfields_handler_test.go @@ -2,6 +2,7 @@ package customfieldshandler import ( "context" + "errors" "io" "net" "testing" @@ -121,7 +122,7 @@ func TestInterceptor(t *testing.T) { for { _, err := stream.Recv() - if err == io.EOF { + if errors.Is(err, io.EOF) { break } require.NoError(t, err) diff --git a/internal/grpc/middleware/limithandler/middleware_test.go b/internal/grpc/middleware/limithandler/middleware_test.go index 1d9c5cf34..a299a456f 100644 --- a/internal/grpc/middleware/limithandler/middleware_test.go +++ b/internal/grpc/middleware/limithandler/middleware_test.go @@ -3,6 +3,7 @@ package limithandler_test import ( "bytes" "context" + "errors" "io" "net" "sync" @@ -644,7 +645,7 @@ func (q *queueTestServer) FullDuplexCall(stream grpc_testing.TestService_FullDup // Read all the input for { if _, err := stream.Recv(); err != nil { - if err != io.EOF { + if !errors.Is(err, io.EOF) { return err } diff --git a/internal/grpc/middleware/limithandler/testhelper_test.go b/internal/grpc/middleware/limithandler/testhelper_test.go index c32e97579..941365862 100644 --- a/internal/grpc/middleware/limithandler/testhelper_test.go +++ b/internal/grpc/middleware/limithandler/testhelper_test.go @@ -2,6 +2,7 @@ package limithandler_test import ( "context" + "errors" "io" "sync/atomic" "testing" @@ -62,7 +63,7 @@ func (s *server) StreamingInputCall(stream grpc_testing.TestService_StreamingInp // Read all the input for { if _, err := stream.Recv(); err != nil { - if err != io.EOF { + if !errors.Is(err, io.EOF) { return err } break @@ -82,7 +83,7 @@ func (s *server) FullDuplexCall(stream grpc_testing.TestService_FullDuplexCallSe // Read all the input for { if _, err := stream.Recv(); err != nil { - if err != io.EOF { + if !errors.Is(err, io.EOF) { return err } break diff --git a/internal/grpc/middleware/statushandler/statushandler.go b/internal/grpc/middleware/statushandler/statushandler.go index 07b736d97..339d849e7 100644 --- a/internal/grpc/middleware/statushandler/statushandler.go +++ b/internal/grpc/middleware/statushandler/statushandler.go @@ -2,6 +2,7 @@ package statushandler import ( "context" + "errors" "gitlab.com/gitlab-org/gitaly/v16/internal/structerr" "google.golang.org/grpc" @@ -32,9 +33,9 @@ func wrapCtxErr(ctx context.Context, err error) error { switch { case err == nil: return nil - case ctx.Err() == context.DeadlineExceeded: + case errors.Is(ctx.Err(), context.DeadlineExceeded): return structerr.New("%w", err).WithGRPCCode(codes.DeadlineExceeded) - case ctx.Err() == context.Canceled: + case errors.Is(ctx.Err(), context.Canceled): return structerr.New("%w", err).WithGRPCCode(codes.Canceled) default: return structerr.NewInternal("%w", err) diff --git a/internal/grpc/proxy/handler.go b/internal/grpc/proxy/handler.go index e43e86292..94033eef5 100644 --- a/internal/grpc/proxy/handler.go +++ b/internal/grpc/proxy/handler.go @@ -187,7 +187,7 @@ func HandleStream(serverStream grpc.ServerStream, fullMethodName string, params // clientErr will contain RPC error from client code. If not io.EOF, return // the RPC error as server stream error after the loop. - if primaryErr != io.EOF { + if !errors.Is(primaryErr, io.EOF) { // If there is an error from the primary, we want to cancel all streams cancelStreams(allStreams) } @@ -200,7 +200,7 @@ func HandleStream(serverStream grpc.ServerStream, fullMethodName string, params return status.Errorf(codes.Internal, "failed proxying c2s: %v", clientErr) } - if primaryErr != nil && primaryErr != io.EOF { + if primaryErr != nil && !errors.Is(primaryErr, io.EOF) { // we must not propagate Gitaly errors into Sentry sentryhandler.MarkToSkip(serverStream.Context()) return primaryErr diff --git a/internal/grpc/proxy/handler_ext_test.go b/internal/grpc/proxy/handler_ext_test.go index e03945dc9..1cd9e1082 100644 --- a/internal/grpc/proxy/handler_ext_test.go +++ b/internal/grpc/proxy/handler_ext_test.go @@ -175,7 +175,7 @@ func testHandlerFullDuplex(t *testing.T) { for i := 0; ; i++ { request, err := stream.Recv() - if err == io.EOF { + if errors.Is(err, io.EOF) { break } require.NoError(t, err) diff --git a/internal/grpc/sidechannel/proxy.go b/internal/grpc/sidechannel/proxy.go index 69df54e76..06e0b38ff 100644 --- a/internal/grpc/sidechannel/proxy.go +++ b/internal/grpc/sidechannel/proxy.go @@ -2,6 +2,7 @@ package sidechannel import ( "context" + "errors" "fmt" "io" @@ -20,7 +21,7 @@ func NewUnaryProxy(registry *Registry, log log.Logger) grpc.UnaryClientIntercept ctx, waiter := RegisterSidechannel(ctx, registry, proxy(ctx)) defer func() { - if waiterErr := waiter.Close(); waiterErr != nil && waiterErr != ErrCallbackDidNotRun { + if waiterErr := waiter.Close(); waiterErr != nil && !errors.Is(waiterErr, ErrCallbackDidNotRun) { if err == nil { err = fmt.Errorf("sidechannel: proxy callback: %w", waiterErr) } else { @@ -72,7 +73,7 @@ func (sw *streamWrapper) RecvMsg(m interface{}) (err error) { // on. Otherwise, when upstream returns an error, there is a race between the gRPC handler and // Sidechannel connection. This race sometimes makes the error message not fully flushed. // For more information: https://gitlab.com/gitlab-org/gitaly/-/issues/5552 - if waiterErr := sw.waiter.Close(); waiterErr != nil && waiterErr != ErrCallbackDidNotRun { + if waiterErr := sw.waiter.Close(); waiterErr != nil && !errors.Is(waiterErr, ErrCallbackDidNotRun) { if err == nil { err = fmt.Errorf("sidechannel: proxy callback: %w", waiterErr) } else { diff --git a/internal/grpc/sidechannel/proxy_test.go b/internal/grpc/sidechannel/proxy_test.go index 833767c6c..2d2ccb6ba 100644 --- a/internal/grpc/sidechannel/proxy_test.go +++ b/internal/grpc/sidechannel/proxy_test.go @@ -2,6 +2,7 @@ package sidechannel import ( "context" + "errors" "fmt" "io" "net" @@ -237,7 +238,7 @@ func TestStreamProxy_upstreamError(t *testing.T) { if err != nil { return err } - if _, err := client.Recv(); err != io.EOF { + if _, err := client.Recv(); !errors.Is(err, io.EOF) { return err } @@ -304,7 +305,7 @@ func testStreamProxy(t *testing.T, closeWrite bool) { return err } - if _, err := client.Recv(); err != io.EOF { + if _, err := client.Recv(); !errors.Is(err, io.EOF) { return fmt.Errorf("grpc proxy recv: %w", err) } diff --git a/internal/helper/chunk/chunker_test.go b/internal/helper/chunk/chunker_test.go index 1eb1a1e36..f36074629 100644 --- a/internal/helper/chunk/chunker_test.go +++ b/internal/helper/chunk/chunker_test.go @@ -1,6 +1,7 @@ package chunk import ( + "errors" "io" "net" "strconv" @@ -50,7 +51,7 @@ func TestChunker(t *testing.T) { for { resp, err := stream.Recv() - if err == io.EOF { + if errors.Is(err, io.EOF) { break } require.Less(t, proto.Size(resp), maxMessageSize) diff --git a/internal/helper/lines/send.go b/internal/helper/lines/send.go index c39126a09..723ae7ffb 100644 --- a/internal/helper/lines/send.go +++ b/internal/helper/lines/send.go @@ -3,6 +3,7 @@ package lines import ( "bufio" "bytes" + "errors" "fmt" "io" "regexp" @@ -98,7 +99,7 @@ func (w *writer) consume(r io.Reader) error { for { // delim can be multiple bytes, so we read till the end byte of it ... chunk, err := buf.ReadBytes(w.delimiter()) - if err != nil && err != io.EOF { + if err != nil && !errors.Is(err, io.EOF) { return err } @@ -108,7 +109,7 @@ func (w *writer) consume(r io.Reader) error { break } - if err == io.EOF { + if errors.Is(err, io.EOF) { i = w.options.Limit // Implicit exit clause for the loop break } diff --git a/internal/limiter/adaptive_calculator.go b/internal/limiter/adaptive_calculator.go index 1c16d0081..38d3e0ba8 100644 --- a/internal/limiter/adaptive_calculator.go +++ b/internal/limiter/adaptive_calculator.go @@ -2,6 +2,7 @@ package limiter import ( "context" + "errors" "fmt" "math" "sync" @@ -211,7 +212,7 @@ func (c *AdaptiveCalculator) pollBackoffEvent(ctx context.Context) { logger := c.logger.WithField("watcher", w.Name()) event, err := w.Poll(ctx) if err != nil { - if err == context.DeadlineExceeded { + if errors.Is(err, context.DeadlineExceeded) { c.watcherTimeouts[w].Add(1) // If the watcher timeouts for a number of consecutive times, treat it as a // backoff event. @@ -227,7 +228,7 @@ func (c *AdaptiveCalculator) pollBackoffEvent(ctx context.Context) { } } - if err != context.Canceled { + if !errors.Is(err, context.Canceled) { c.watcherErrorsVec.WithLabelValues(w.Name()).Inc() logger.WithError(err).Error("poll from resource watcher failed") } diff --git a/internal/limiter/concurrency_limiter.go b/internal/limiter/concurrency_limiter.go index 6e0b80007..7f23eb3ad 100644 --- a/internal/limiter/concurrency_limiter.go +++ b/internal/limiter/concurrency_limiter.go @@ -258,14 +258,14 @@ func (c *ConcurrencyLimiter) Limit(ctx context.Context, limitingKey string, f Li if err := sem.acquire(ctx, limitingKey); err != nil { queueTime := time.Since(start) - switch err { - case ErrMaxQueueSize: + switch { + case errors.Is(err, ErrMaxQueueSize): c.monitor.Dropped(ctx, limitingKey, sem.queueLength(), sem.inProgress(), queueTime, "max_size") return nil, structerr.NewResourceExhausted("%w", ErrMaxQueueSize).WithDetail(&gitalypb.LimitError{ ErrorMessage: err.Error(), RetryAfter: durationpb.New(0), }) - case ErrMaxQueueTime: + case errors.Is(err, ErrMaxQueueTime): c.monitor.Dropped(ctx, limitingKey, sem.queueLength(), sem.inProgress(), queueTime, "max_time") return nil, structerr.NewResourceExhausted("%w", ErrMaxQueueTime).WithDetail(&gitalypb.LimitError{ ErrorMessage: err.Error(), diff --git a/internal/praefect/datastore/listener.go b/internal/praefect/datastore/listener.go index 54b9fa586..b6face6b9 100644 --- a/internal/praefect/datastore/listener.go +++ b/internal/praefect/datastore/listener.go @@ -139,16 +139,17 @@ func (rl *ResilientListener) Listen(ctx context.Context, handler glsql.ListenHan } handler := metricsHandlerMiddleware{ListenHandler: handler, counter: rl.reconnectTotal} - if err := lis.Listen(ctx, handler, channels...); err != nil { - if errors.Is(err, context.Canceled) || errors.Is(err, context.DeadlineExceeded) { - return err - } - - rl.logger.WithError(err). - WithField("channels", channels). - Error("listening was interrupted") + + // Listen always returns an error, so we don't need to check for nil. + err = lis.Listen(ctx, handler, channels...) + if errors.Is(err, context.Canceled) || errors.Is(err, context.DeadlineExceeded) { + return err } + rl.logger.WithError(err). + WithField("channels", channels). + Error("listening was interrupted") + rl.ticker.Reset() select { case <-ctx.Done(): diff --git a/internal/praefect/middleware/errorhandler.go b/internal/praefect/middleware/errorhandler.go index f475507f4..738f9c1ed 100644 --- a/internal/praefect/middleware/errorhandler.go +++ b/internal/praefect/middleware/errorhandler.go @@ -2,6 +2,7 @@ package middleware import ( "context" + "errors" "fmt" "io" @@ -17,8 +18,8 @@ func StreamErrorHandler(registry *protoregistry.Registry, errorTracker tracker.E mi, lookupErr := registry.LookupMethod(method) if err != nil { - //nolint:gitaly-linters - return nil, fmt.Errorf("error when looking up method: %w %v", err, lookupErr) + // TODO: use errors.Join() to combine errors instead + return nil, fmt.Errorf("error when looking up method: %w %s", err, lookupErr.Error()) } return newCatchErrorStreamer(stream, errorTracker, mi.Operation, nodeStorage), err @@ -60,7 +61,7 @@ func (c *catchErrorStreamer) SendMsg(m interface{}) error { // RecvMsg proxies the send but records any errors func (c *catchErrorStreamer) RecvMsg(m interface{}) error { err := c.ClientStream.RecvMsg(m) - if err != nil && err != io.EOF { + if err != nil && !errors.Is(err, io.EOF) { switch c.operation { case protoregistry.OpAccessor: c.errors.IncrReadErr(c.nodeStorage) diff --git a/internal/praefect/nodes/sql_elector_test.go b/internal/praefect/nodes/sql_elector_test.go index 6c42f8a97..135c03b84 100644 --- a/internal/praefect/nodes/sql_elector_test.go +++ b/internal/praefect/nodes/sql_elector_test.go @@ -2,6 +2,7 @@ package nodes import ( "context" + "errors" "net" "testing" "time" @@ -435,7 +436,7 @@ func TestConnectionMultiplexing(t *testing.T) { grpc.Creds(lm), grpc.UnknownServiceHandler(func(srv interface{}, stream grpc.ServerStream) error { _, err := backchannel.GetPeerID(stream.Context()) - if err == backchannel.ErrNonMultiplexedConnection { + if errors.Is(err, backchannel.ErrNonMultiplexedConnection) { return errNonMuxed } diff --git a/internal/praefect/server_test.go b/internal/praefect/server_test.go index 94cc2e35a..ded415211 100644 --- a/internal/praefect/server_test.go +++ b/internal/praefect/server_test.go @@ -777,7 +777,7 @@ func TestProxyWrites(t *testing.T) { for { resp, err := stream.Recv() if err != nil { - if err == io.EOF { + if errors.Is(err, io.EOF) { break } require.FailNowf(t, "unexpected non io.EOF error: %v", err.Error()) diff --git a/internal/praefect/testserver.go b/internal/praefect/testserver.go index 835b5377d..fc4eb083d 100644 --- a/internal/praefect/testserver.go +++ b/internal/praefect/testserver.go @@ -2,6 +2,7 @@ package praefect import ( "context" + "errors" "fmt" "net" "testing" @@ -153,7 +154,7 @@ func newMockDownstream(tb testing.TB, token string, registerService func(*grpc.S // If the server is shutdown before Serve() is called on it // the Serve() calls will return the ErrServerStopped - if err := <-errQ; err != nil && err != grpc.ErrServerStopped { + if err := <-errQ; err != nil && !errors.Is(err, grpc.ErrServerStopped) { require.NoError(tb, err) } } diff --git a/internal/stream/std_stream.go b/internal/stream/std_stream.go index bf5079193..8afa2c8d6 100644 --- a/internal/stream/std_stream.go +++ b/internal/stream/std_stream.go @@ -1,6 +1,7 @@ package stream import ( + "errors" "fmt" "io" @@ -50,7 +51,7 @@ func Handler(recv func() (StdoutStderrResponse, error), send func(chan error), s } } } - if err == io.EOF { + if errors.Is(err, io.EOF) { err = nil } diff --git a/internal/streamcache/cache_test.go b/internal/streamcache/cache_test.go index f3a1bd57b..c8fdc82a6 100644 --- a/internal/streamcache/cache_test.go +++ b/internal/streamcache/cache_test.go @@ -365,8 +365,10 @@ func TestCache_unWriteableFile(t *testing.T) { _, err := io.WriteString(w, "hello") return err }) - require.IsType(t, &os.PathError{}, err) - require.Equal(t, "write", err.(*os.PathError).Op) + + var pathErr *os.PathError + require.True(t, errors.As(err, &pathErr)) + require.Equal(t, "write", pathErr.Op) } func TestCache_unCloseableFile(t *testing.T) { @@ -385,8 +387,10 @@ func TestCache_unCloseableFile(t *testing.T) { } _, _, err := c.Fetch(ctx, "key", io.Discard, func(w io.Writer) error { return nil }) - require.IsType(t, &os.PathError{}, err) - require.Equal(t, "close", err.(*os.PathError).Op) + + var pathErr *os.PathError + require.True(t, errors.As(err, &pathErr)) + require.Equal(t, "close", pathErr.Op) } func TestCache_cannotOpenFileForReading(t *testing.T) { @@ -406,8 +410,9 @@ func TestCache_cannotOpenFileForReading(t *testing.T) { _, _, err := c.Fetch(ctx, "key", io.Discard, func(w io.Writer) error { return nil }) err = errors.Unwrap(err) - require.IsType(t, &os.PathError{}, err) - require.Equal(t, "open", err.(*os.PathError).Op) + var pathErr *os.PathError + require.True(t, errors.As(err, &pathErr)) + require.Equal(t, "open", pathErr.Op) } func TestWaiter(t *testing.T) { diff --git a/internal/streamcache/pipe_linux.go b/internal/streamcache/pipe_linux.go index 3be8a2764..0ce3798e7 100644 --- a/internal/streamcache/pipe_linux.go +++ b/internal/streamcache/pipe_linux.go @@ -58,7 +58,7 @@ func (pr *pipeReader) writeTo(w io.Writer) (int64, error) { // If errSendfile is EAGAIN, ask Go runtime to wait for dst to become // writeable again by returning false. - return errSendfile != syscall.EAGAIN + return !errors.Is(errSendfile, syscall.EAGAIN) }) return true @@ -109,7 +109,7 @@ func (pr *pipeReader) sendfile(dst int, src int) error { } // In case of EINTR, ignore the error and retry immediately - if err != nil && err != syscall.EINTR { + if err != nil && !errors.Is(err, syscall.EINTR) { return err } } diff --git a/internal/structerr/error.go b/internal/structerr/error.go index e0c5dd0c7..be03ba886 100644 --- a/internal/structerr/error.go +++ b/internal/structerr/error.go @@ -262,7 +262,8 @@ func (e Error) GRPCStatus() *status.Status { func (e Error) errorChain() []Error { var result []Error for err := error(e); err != nil; err = errors.Unwrap(err) { - if structErr, ok := err.(Error); ok { + var structErr Error + if errors.As(err, &structErr) { result = append(result, structErr) } } @@ -367,6 +368,7 @@ func ExtractMetadata(err error) map[string]any { return metadata } +//nolint:errorlint func combineMetadataItems(err error) []MetadataItem { var metadataItems []MetadataItem diff --git a/internal/testhelper/directory.go b/internal/testhelper/directory.go index b9b3e7d48..58d540d51 100644 --- a/internal/testhelper/directory.go +++ b/internal/testhelper/directory.go @@ -3,6 +3,7 @@ package testhelper import ( "archive/tar" "bytes" + "errors" "io" "io/fs" "os" @@ -94,7 +95,7 @@ func RequireTarState(tb testing.TB, tarball io.Reader, expected DirectoryState) tr := tar.NewReader(tarball) for { header, err := tr.Next() - if err == io.EOF { + if errors.Is(err, io.EOF) { break } require.NoError(tb, err) diff --git a/internal/testhelper/leakage.go b/internal/testhelper/leakage.go index 7a9c4006a..3e23c56b5 100644 --- a/internal/testhelper/leakage.go +++ b/internal/testhelper/leakage.go @@ -1,6 +1,7 @@ package testhelper import ( + "errors" "fmt" "os" "os/exec" @@ -81,13 +82,13 @@ func mustFindNoRunningChildProcess() error { return fmt.Errorf("found running child processes %s:\n%s", pidsComma, psOut) } - exitError, ok := err.(*exec.ExitError) - if !ok { - //nolint:gitaly-linters + var exitErr *exec.ExitError + if !errors.As(err, &exitErr) { + //nolint:gitaly-linters,errorlint return fmt.Errorf("expected ExitError, got %T", err) } - if exitError.ExitCode() == 1 { + if exitErr.ExitCode() == 1 { return nil } diff --git a/internal/testhelper/testhelper.go b/internal/testhelper/testhelper.go index 6de813fb6..67905f67e 100644 --- a/internal/testhelper/testhelper.go +++ b/internal/testhelper/testhelper.go @@ -129,9 +129,10 @@ func MustRunCommand(tb testing.TB, stdin io.Reader, name string, args ...string) } output, err := cmd.Output() - if err != nil { - stderr := err.(*exec.ExitError).Stderr - require.NoError(tb, err, "%s %s: %s", name, args, stderr) + + var exitErr *exec.ExitError + if errors.As(err, &exitErr) { + require.NoError(tb, err, "%s %s: %s", name, args, exitErr.Stderr) } return output diff --git a/internal/testhelper/testserver/praefect.go b/internal/testhelper/testserver/praefect.go index 59331264c..6f1be2851 100644 --- a/internal/testhelper/testserver/praefect.go +++ b/internal/testhelper/testserver/praefect.go @@ -3,6 +3,7 @@ package testserver import ( "bytes" "context" + "errors" "net" "os" "os/exec" @@ -113,8 +114,7 @@ func StartPraefect(tb testing.TB, cfg config.Config) PraefectServer { select { case <-ctx.Done(): - switch ctx.Err() { - case context.DeadlineExceeded: + if errors.Is(ctx.Err(), context.DeadlineExceeded) { // Capture Praefect logs when waitHealthy takes too long. require.FailNowf(tb, "Connecting to Praefect exceeded deadline", "%s", stderr.String()) } |