diff --git a/cmd/mutagen/daemon/connect.go b/cmd/mutagen/daemon/connect.go index 3d195ac1c..26bd4f4c3 100644 --- a/cmd/mutagen/daemon/connect.go +++ b/cmd/mutagen/daemon/connect.go @@ -78,7 +78,7 @@ func Connect(autostart, enforceVersionMatch bool) (*grpc.ClientConn, error) { // Check for errors. if err != nil { // Handle failure due to timeouts. - if err == context.DeadlineExceeded { + if errors.Is(err, context.DeadlineExceeded) { // If autostart is enabled, and we have attempts remaining, then // try autostarting, waiting, and retrying. if autostart && remainingPostAutostatAttempts > 0 { diff --git a/pkg/agent/bundle.go b/pkg/agent/bundle.go index f5ffe4bb9..ce5b5b260 100644 --- a/pkg/agent/bundle.go +++ b/pkg/agent/bundle.go @@ -117,7 +117,7 @@ func ExecutableForPlatform(goos, goarch, outputPath string) (string, error) { var header *tar.Header for { if h, err := bundleArchive.Next(); err != nil { - if err == io.EOF { + if errors.Is(err, io.EOF) { break } return "", fmt.Errorf("unable to read archive header: %w", err) diff --git a/pkg/filesystem/behavior/internal/format/format_statfs.go b/pkg/filesystem/behavior/internal/format/format_statfs.go index fb0c4dd58..978eb578d 100644 --- a/pkg/filesystem/behavior/internal/format/format_statfs.go +++ b/pkg/filesystem/behavior/internal/format/format_statfs.go @@ -3,6 +3,7 @@ package format import ( + "errors" "fmt" "golang.org/x/sys/unix" @@ -15,7 +16,7 @@ import ( func statfsRetryingOnEINTR(path string, metadata *unix.Statfs_t) error { for { err := unix.Statfs(path, metadata) - if err == unix.EINTR { + if errors.Is(err, unix.EINTR) { continue } return err @@ -28,7 +29,7 @@ func statfsRetryingOnEINTR(path string, metadata *unix.Statfs_t) error { func fstatfsRetryingOnEINTR(fd int, metadata *unix.Statfs_t) error { for { err := unix.Fstatfs(fd, metadata) - if err == unix.EINTR { + if errors.Is(err, unix.EINTR) { continue } return err diff --git a/pkg/filesystem/directory_posix.go b/pkg/filesystem/directory_posix.go index 369e2cfa3..13f814b88 100644 --- a/pkg/filesystem/directory_posix.go +++ b/pkg/filesystem/directory_posix.go @@ -448,7 +448,7 @@ func (d *Directory) ReadSymbolicLink(name string) (string, error) { // Handle errors. If we see ERANGE on AIX systems, it's an indication // that the buffer size is too small. - if runtime.GOOS == "aix" && err == unix.ERANGE { + if runtime.GOOS == "aix" && errors.Is(err, unix.ERANGE) { continue } else if err != nil { return "", err @@ -554,7 +554,7 @@ func Rename( ) if err == nil || (err != unix.ENOTSUP && err != unix.ENOSYS) { return err - } else if err == unix.ENOTSUP && targetDirectory != nil { + } else if errors.Is(err, unix.ENOTSUP) && targetDirectory != nil { targetDirectory.renameatNoReplaceUnsupported.Mark() } } @@ -588,5 +588,5 @@ func Rename( // IsCrossDeviceError checks whether or not an error returned from rename // represents a cross-device error. func IsCrossDeviceError(err error) bool { - return err == unix.EXDEV + return errors.Is(err, unix.EXDEV) } diff --git a/pkg/filesystem/directory_rename_darwin.go b/pkg/filesystem/directory_rename_darwin.go index 0a4b0f935..4b2712698 100644 --- a/pkg/filesystem/directory_rename_darwin.go +++ b/pkg/filesystem/directory_rename_darwin.go @@ -1,6 +1,8 @@ package filesystem import ( + "errors" + "golang.org/x/sys/unix" "github.com/mutagen-io/mutagen/pkg/filesystem/internal/syscall" @@ -15,7 +17,7 @@ import ( func renameatNoReplaceRetryingOnEINTR(oldDirectory int, oldPath string, newDirectory int, newPath string) error { for { err := syscall.Renameatx_np(oldDirectory, oldPath, newDirectory, newPath, syscall.RENAME_EXCL) - if err == unix.EINTR { + if errors.Is(err, unix.EINTR) { continue } return err diff --git a/pkg/filesystem/directory_rename_linux.go b/pkg/filesystem/directory_rename_linux.go index 07181dc40..1ae19534f 100644 --- a/pkg/filesystem/directory_rename_linux.go +++ b/pkg/filesystem/directory_rename_linux.go @@ -1,6 +1,8 @@ package filesystem import ( + "errors" + "golang.org/x/sys/unix" "github.com/mutagen-io/mutagen/pkg/state" @@ -24,9 +26,9 @@ func renameatNoReplaceRetryingOnEINTR(oldDirectory int, oldPath string, newDirec // Loop until renameat2 completes with a return value other that EINTR. for { err := unix.Renameat2(oldDirectory, oldPath, newDirectory, newPath, unix.RENAME_NOREPLACE) - if err == unix.EINTR { + if errors.Is(err, unix.EINTR) { continue - } else if err == unix.EINVAL { + } else if errors.Is(err, unix.EINVAL) { // HACK: On Linux, using RENAME_NOREPLACE with a target filesystem // that doesn't support it will yield EINVAL. To keep consistency // with other renameatNoReplaceRetryingOnEINTR implementations, we @@ -38,7 +40,7 @@ func renameatNoReplaceRetryingOnEINTR(oldDirectory int, oldPath string, newDirec // invocation of renameat2. The only other error we'd need to // consider would be ENOSYS, but that we don't need to alias. return unix.ENOTSUP - } else if err == unix.ENOSYS { + } else if errors.Is(err, unix.ENOSYS) { renameat2FailedWithENOSYS.Mark() } return err diff --git a/pkg/filesystem/interrupt_posix.go b/pkg/filesystem/interrupt_posix.go index c8272e2a6..da46e0c25 100644 --- a/pkg/filesystem/interrupt_posix.go +++ b/pkg/filesystem/interrupt_posix.go @@ -3,6 +3,7 @@ package filesystem import ( + "errors" "io" "golang.org/x/sys/unix" @@ -15,7 +16,7 @@ import ( func openatRetryingOnEINTR(directory int, path string, flags int, mode uint32) (int, error) { for { result, err := unix.Openat(directory, path, flags, mode) - if err == unix.EINTR { + if errors.Is(err, unix.EINTR) { continue } return result, err @@ -27,7 +28,7 @@ func openatRetryingOnEINTR(directory int, path string, flags int, mode uint32) ( func readRetryingOnEINTR(file int, buffer []byte) (int, error) { for { result, err := unix.Read(file, buffer) - if err == unix.EINTR { + if errors.Is(err, unix.EINTR) { continue } else if err == nil && result == 0 { return 0, io.EOF @@ -64,7 +65,7 @@ func closeConsideringEINTR(file int) error { func mkdiratRetryingOnEINTR(directory int, path string, mode uint32) error { for { err := unix.Mkdirat(directory, path, mode) - if err == unix.EINTR { + if errors.Is(err, unix.EINTR) { continue } return err @@ -77,7 +78,7 @@ func mkdiratRetryingOnEINTR(directory int, path string, mode uint32) error { func renameatRetryingOnEINTR(oldDirectory int, oldPath string, newDirectory int, newPath string) error { for { err := unix.Renameat(oldDirectory, oldPath, newDirectory, newPath) - if err == unix.EINTR { + if errors.Is(err, unix.EINTR) { continue } return err @@ -90,7 +91,7 @@ func renameatRetryingOnEINTR(oldDirectory int, oldPath string, newDirectory int, func unlinkatRetryingOnEINTR(directory int, path string, flags int) error { for { err := unix.Unlinkat(directory, path, flags) - if err == unix.EINTR { + if errors.Is(err, unix.EINTR) { continue } return err @@ -102,7 +103,7 @@ func unlinkatRetryingOnEINTR(directory int, path string, flags int) error { func fstatRetryingOnEINTR(file int, metadata *unix.Stat_t) error { for { err := unix.Fstat(file, metadata) - if err == unix.EINTR { + if errors.Is(err, unix.EINTR) { continue } return err @@ -114,7 +115,7 @@ func fstatRetryingOnEINTR(file int, metadata *unix.Stat_t) error { func fchmodRetryingOnEINTR(file int, mode uint32) error { for { err := unix.Fchmod(file, mode) - if err == unix.EINTR { + if errors.Is(err, unix.EINTR) { continue } return err @@ -127,7 +128,7 @@ func fchmodRetryingOnEINTR(file int, mode uint32) error { func fstatatRetryingOnEINTR(directory int, path string, metadata *unix.Stat_t, flags int) error { for { err := unix.Fstatat(directory, path, metadata, flags) - if err == unix.EINTR { + if errors.Is(err, unix.EINTR) { continue } return err @@ -140,7 +141,7 @@ func fstatatRetryingOnEINTR(directory int, path string, metadata *unix.Stat_t, f func fchmodatRetryingOnEINTR(directory int, path string, mode uint32, flags int) error { for { err := unix.Fchmodat(directory, path, mode, flags) - if err == unix.EINTR { + if errors.Is(err, unix.EINTR) { continue } return err @@ -153,7 +154,7 @@ func fchmodatRetryingOnEINTR(directory int, path string, mode uint32, flags int) func fchownatRetryingOnEINTR(directory int, path string, uid int, gid int, flags int) error { for { err := unix.Fchownat(directory, path, uid, gid, flags) - if err == unix.EINTR { + if errors.Is(err, unix.EINTR) { continue } return err @@ -166,7 +167,7 @@ func fchownatRetryingOnEINTR(directory int, path string, uid int, gid int, flags func symlinkatRetryingOnEINTR(target string, directory int, path string) error { for { err := syscall.Symlinkat(target, directory, path) - if err == unix.EINTR { + if errors.Is(err, unix.EINTR) { continue } return err @@ -179,7 +180,7 @@ func symlinkatRetryingOnEINTR(target string, directory int, path string) error { func readlinkatRetryingOnEINTR(directory int, path string, buffer []byte) (int, error) { for { result, err := syscall.Readlinkat(directory, path, buffer) - if err == unix.EINTR { + if errors.Is(err, unix.EINTR) { continue } return result, err diff --git a/pkg/filesystem/locking/locker_posix.go b/pkg/filesystem/locking/locker_posix.go index 82e25d5c1..e6ff4874f 100644 --- a/pkg/filesystem/locking/locker_posix.go +++ b/pkg/filesystem/locking/locker_posix.go @@ -19,7 +19,7 @@ import ( func fcntlFlockRetryingOnEINTR(file uintptr, command int, specification *unix.Flock_t) error { for { err := unix.FcntlFlock(file, command, specification) - if err == unix.EINTR { + if errors.Is(err, unix.EINTR) { continue } return err diff --git a/pkg/multiplexing/multiplexer.go b/pkg/multiplexing/multiplexer.go index 038009c18..4a0c4b0c8 100644 --- a/pkg/multiplexing/multiplexer.go +++ b/pkg/multiplexing/multiplexer.go @@ -381,7 +381,7 @@ func (m *Multiplexer) read(reader Carrier, heartbeats chan<- struct{}) error { stream.receiveBufferLock.Lock() if _, err := stream.receiveBuffer.ReadNFrom(reader, length); err != nil { stream.receiveBufferLock.Unlock() - if err == ring.ErrBufferFull { + if errors.Is(err, ring.ErrBufferFull) { return errors.New("remote violated stream receive window") } return fmt.Errorf("unable to read stream data into buffer: %w", err) @@ -694,13 +694,13 @@ func (m *Multiplexer) acceptOneStream(ctx context.Context) (*Stream, error) { return stream, nil } -// AcceptContext accepts an incoming stream. +// AcceptStream accepts an incoming stream. func (m *Multiplexer) AcceptStream(ctx context.Context) (*Stream, error) { // Loop until we find a pending stream that's not stale or encounter some // other error. for { stream, err := m.acceptOneStream(ctx) - if err == errStaleInboundStream { + if errors.Is(err, errStaleInboundStream) { continue } return stream, err diff --git a/pkg/multiplexing/multiplexer_test.go b/pkg/multiplexing/multiplexer_test.go index 2a61e962d..4d284cc80 100644 --- a/pkg/multiplexing/multiplexer_test.go +++ b/pkg/multiplexing/multiplexer_test.go @@ -2,6 +2,7 @@ package multiplexing import ( "context" + "errors" "fmt" "net" "sync" @@ -20,7 +21,7 @@ func makeNetTestMakePipe(opener, acceptor *Multiplexer) nettest.MakePipe { var openErr, acceptErr error go func() { opened, openErr = opener.OpenStream(context.Background()) - if openErr == ErrMultiplexerClosed { + if errors.Is(openErr, ErrMultiplexerClosed) { if internalErr := opener.InternalError(); internalErr != nil { openErr = fmt.Errorf("multiplexer closed due to internal error: %w", internalErr) } @@ -29,7 +30,7 @@ func makeNetTestMakePipe(opener, acceptor *Multiplexer) nettest.MakePipe { }() go func() { accepted, acceptErr = acceptor.AcceptStream(context.Background()) - if acceptErr == ErrMultiplexerClosed { + if errors.Is(acceptErr, ErrMultiplexerClosed) { if internalErr := acceptor.InternalError(); internalErr != nil { acceptErr = fmt.Errorf("multiplexer closed due to internal error: %w", internalErr) } diff --git a/pkg/multiplexing/ring/buffer.go b/pkg/multiplexing/ring/buffer.go index 03e6307d2..1b0818932 100644 --- a/pkg/multiplexing/ring/buffer.go +++ b/pkg/multiplexing/ring/buffer.go @@ -177,7 +177,7 @@ func (b *Buffer) ReadNFrom(reader io.Reader, n int) (int, error) { // If we encountered io.EOF simultaneously with completing the read, then we // can clear the error. - if err == io.EOF && n == 0 { + if errors.Is(err, io.EOF) && n == 0 { err = nil } diff --git a/pkg/state/lock_test.go b/pkg/state/lock_test.go index c15c0f7cb..87170abb1 100644 --- a/pkg/state/lock_test.go +++ b/pkg/state/lock_test.go @@ -2,6 +2,7 @@ package state import ( "context" + "errors" "testing" "time" ) @@ -28,7 +29,7 @@ func TestTrackingLock(t *testing.T) { // Wait for termination and ensure that the state doesn't change. finalState, err := tracker.WaitForChange(context.Background(), firstState) - handoff <- (finalState == firstState && err == ErrTrackingTerminated) + handoff <- (finalState == firstState && errors.Is(err, ErrTrackingTerminated)) }() // Acquire and release the lock in a way that will change the state, and diff --git a/pkg/state/tracker_test.go b/pkg/state/tracker_test.go index d999c5876..1c58e449a 100644 --- a/pkg/state/tracker_test.go +++ b/pkg/state/tracker_test.go @@ -2,6 +2,7 @@ package state import ( "context" + "errors" "testing" "time" ) @@ -45,7 +46,7 @@ func TestTracker(t *testing.T) { // Wait for termination and ensure that the state doesn't change. finalState, err := tracker.WaitForChange(context.Background(), secondState) - handoff <- (finalState == firstState && err == ErrTrackingTerminated) + handoff <- (finalState == firstState && errors.Is(err, ErrTrackingTerminated)) }() // Notify of a change and wait for a response. diff --git a/pkg/synchronization/controller.go b/pkg/synchronization/controller.go index d0986c559..393ed710f 100644 --- a/pkg/synchronization/controller.go +++ b/pkg/synchronization/controller.go @@ -808,7 +808,7 @@ func (c *controller) run(ctx context.Context, alpha, beta Endpoint) { // If synchronization failed due a halting error, then wait for the // synchronization loop to be manually resumed. - if err == errHaltedForSafety { + if errors.Is(err, errHaltedForSafety) { <-ctx.Done() return } diff --git a/pkg/synchronization/core/scan.go b/pkg/synchronization/core/scan.go index a93b4a14f..5bfcbb999 100644 --- a/pkg/synchronization/core/scan.go +++ b/pkg/synchronization/core/scan.go @@ -208,7 +208,7 @@ func (s *scanner) file( // timely cancellation. preemptableHasher := stream.NewPreemptableWriter(s.hasher, s.cancelled, scannerCopyPreemptionInterval) if copied, err := io.CopyBuffer(preemptableHasher, file, s.copyBuffer); err != nil { - if err == stream.ErrWritePreempted { + if errors.Is(err, stream.ErrWritePreempted) { return nil, ErrScanCancelled } return &Entry{ diff --git a/pkg/synchronization/core/transition.go b/pkg/synchronization/core/transition.go index bb52039c4..9c83d441f 100644 --- a/pkg/synchronization/core/transition.go +++ b/pkg/synchronization/core/transition.go @@ -662,7 +662,7 @@ func (t *transitioner) findAndMoveStagedFileIntoPlace( // If there was a copy error, then remove the temporary and abort. if copyErr != nil { parent.RemoveFile(temporaryName) - if copyErr == stream.ErrWritePreempted { + if errors.Is(copyErr, stream.ErrWritePreempted) { return errTransitionCancelled } return fmt.Errorf("unable to copy file contents: %w", copyErr) diff --git a/pkg/synchronization/endpoint/local/endpoint.go b/pkg/synchronization/endpoint/local/endpoint.go index 1bf31506b..75f536751 100644 --- a/pkg/synchronization/endpoint/local/endpoint.go +++ b/pkg/synchronization/endpoint/local/endpoint.go @@ -937,7 +937,7 @@ WatchEstablishment: // events are likely happening on disk faster than we can // process them. In that case, wait one polling interval before // attempting to re-establish the watch. - if err == watching.ErrWatchInternalOverflow { + if errors.Is(err, watching.ErrWatchInternalOverflow) { logger.Debug("Waiting before watch re-establishment") timer.Reset(pollingDuration) select { diff --git a/pkg/synchronization/rsync/engine.go b/pkg/synchronization/rsync/engine.go index dc9b47338..f29b241a8 100644 --- a/pkg/synchronization/rsync/engine.go +++ b/pkg/synchronization/rsync/engine.go @@ -347,10 +347,10 @@ func (e *Engine) Signature(base io.Reader, blockSize uint64) (*Signature, error) // at the end of the file, so we should hash this block but not go // through the loop again. All other errors are terminal. n, err := io.ReadFull(base, buffer) - if err == io.EOF { + if errors.Is(err, io.EOF) { result.LastBlockSize = blockSize break - } else if err == io.ErrUnexpectedEOF { + } else if errors.Is(err, io.ErrUnexpectedEOF) { result.LastBlockSize = uint64(n) eof = true } else if err != nil { @@ -450,9 +450,9 @@ func (e *Engine) chunkAndTransmitAll(target io.Reader, maxDataOpSize uint64, tra // Loop until the entire target has been transmitted as data operations. for { - if n, err := io.ReadFull(target, buffer); err == io.EOF { + if n, err := io.ReadFull(target, buffer); errors.Is(err, io.EOF) { return nil - } else if err == io.ErrUnexpectedEOF { + } else if errors.Is(err, io.ErrUnexpectedEOF) { if err = e.transmitData(buffer[:n], transmit); err != nil { return fmt.Errorf("unable to transmit data operation: %w", err) } @@ -559,11 +559,9 @@ func (e *Engine) Deltify(target io.Reader, base *Signature, maxDataOpSize uint64 // each insertion would require a linear search to find the insertion // location within the array. hashes := base.Hashes - haveShortLastBlock := false var lastBlockIndex uint64 var shortLastBlock *BlockHash if base.LastBlockSize != base.BlockSize { - haveShortLastBlock = true lastBlockIndex = uint64(len(hashes) - 1) shortLastBlock = hashes[lastBlockIndex] hashes = hashes[:lastBlockIndex] @@ -610,7 +608,8 @@ func (e *Engine) Deltify(target io.Reader, base *Signature, maxDataOpSize uint64 // we've broken an invariant in our code. Otherwise, we need to move the // search block one byte forward and roll the hash. if occupancy == 0 { - if n, err := io.ReadFull(bufferedTarget, buffer[:base.BlockSize]); err == io.EOF || err == io.ErrUnexpectedEOF { + n, err := io.ReadFull(bufferedTarget, buffer[:base.BlockSize]) + if errors.Is(err, io.EOF) || errors.Is(err, io.ErrUnexpectedEOF) { occupancy = uint64(n) break } else if err != nil { @@ -622,7 +621,7 @@ func (e *Engine) Deltify(target io.Reader, base *Signature, maxDataOpSize uint64 } else if occupancy < base.BlockSize { panic("buffer contains less than a block worth of data") } else { - if b, err := bufferedTarget.ReadByte(); err == io.EOF { + if b, err := bufferedTarget.ReadByte(); errors.Is(err, io.EOF) { break } else if err != nil { return fmt.Errorf("unable to read target byte: %w", err) @@ -669,7 +668,7 @@ func (e *Engine) Deltify(target io.Reader, base *Signature, maxDataOpSize uint64 // If we have a short last block and the occupancy of the buffer is large // enough that it could match, then check for a match. - if haveShortLastBlock && occupancy >= base.LastBlockSize { + if shortLastBlock != nil && occupancy >= base.LastBlockSize { potentialLastBlockMatch := buffer[occupancy-base.LastBlockSize : occupancy] // For short blocks, we still use the full block size when computing the // weak hash. We could alternatively use the short block length, but it diff --git a/scripts/build.go b/scripts/build.go index 13fec6161..387a94c0b 100644 --- a/scripts/build.go +++ b/scripts/build.go @@ -539,7 +539,7 @@ func build() error { flagSet.StringVar(&macosCodesignIdentity, "macos-codesign-identity", "", "specify the macOS code signing identity") flagSet.BoolVar(&enableSSPLEnhancements, "sspl", false, "enable SSPL-licensed enhancements") if err := flagSet.Parse(os.Args[1:]); err != nil { - if err == pflag.ErrHelp { + if errors.Is(err, pflag.ErrHelp) { fmt.Fprint(os.Stdout, usage) return nil } else { diff --git a/sspl/pkg/filesystem/watching/fanotify/fanotify.go b/sspl/pkg/filesystem/watching/fanotify/fanotify.go index d93c54dd9..3ba748f6d 100644 --- a/sspl/pkg/filesystem/watching/fanotify/fanotify.go +++ b/sspl/pkg/filesystem/watching/fanotify/fanotify.go @@ -210,7 +210,7 @@ func processEvent(mountFD int, buffer []byte) ([]byte, string, error) { mountFD, fileHandle, unix.O_PATH|unix.O_CLOEXEC, ) if err != nil { - if err == unix.ESTALE { + if errors.Is(err, unix.ESTALE) { return buffer, pathStale, nil } return nil, "", fmt.Errorf("unable to open event file: %w", err) diff --git a/sspl/pkg/filesystem/watching/fanotify/watch.go b/sspl/pkg/filesystem/watching/fanotify/watch.go index a0bc06b19..1021f70e1 100644 --- a/sspl/pkg/filesystem/watching/fanotify/watch.go +++ b/sspl/pkg/filesystem/watching/fanotify/watch.go @@ -199,7 +199,7 @@ func (w *RecursiveWatcher) run(ctx context.Context, watch io.Reader, mountDescri // Process a single event. remaining, path, err := processEvent(mountDescriptor, populated) if err != nil { - if err == ErrWatchInternalOverflow { + if errors.Is(err, ErrWatchInternalOverflow) { return err } return fmt.Errorf("unable to extract event path: %w", err) diff --git a/tools/scan_bench/main.go b/tools/scan_bench/main.go index 5e90fda97..aeb16943c 100644 --- a/tools/scan_bench/main.go +++ b/tools/scan_bench/main.go @@ -71,7 +71,7 @@ func main() { flagSet.StringVar(&ignoreSyntaxName, "ignore-syntax", "mutagen", "specify ignore syntax") flagSet.StringSliceVarP(&ignores, "ignore", "i", nil, "specify ignore paths") if err := flagSet.Parse(os.Args[1:]); err != nil { - if err == pflag.ErrHelp { + if errors.Is(err, pflag.ErrHelp) { fmt.Fprint(os.Stdout, usage) return } else {