AdGuardHome/internal/aghrenameio/renameio.go
Ainar Garipov 698b963e11 Pull request 1937: imp-filter-upd
Squashed commit of the following:

commit 6ce649c06398cf8a6f8e1a90f560fa8205f6500e
Merge: 1c6327e5d 996c6b3ee
Author: Ainar Garipov <A.Garipov@AdGuard.COM>
Date:   Tue Jul 25 17:42:01 2023 +0300

    Merge branch 'master' into imp-filter-upd

commit 1c6327e5d4c04393abc5d4d3e4b8568d4c6eca23
Author: Ainar Garipov <A.Garipov@AdGuard.COM>
Date:   Fri Jul 21 17:32:47 2023 +0300

    all: imp code; use renameio/v2 consistently

commit 1669288c9b662d1310f83a4e0d3f1f60731188cd
Author: Ainar Garipov <A.Garipov@AdGuard.COM>
Date:   Fri Jul 21 16:26:17 2023 +0300

    all: add renameioutil; imp flt upd
2023-07-25 17:47:24 +03:00

52 lines
1.9 KiB
Go

// Package aghrenameio is a wrapper around package github.com/google/renameio/v2
// that provides a similar stream-based API for both Unix and Windows systems.
// While the Windows API is not technically atomic, it still provides a
// consistent stream-based interface, and atomic renames of files do not seem to
// be possible in all cases anyway.
//
// See https://github.com/google/renameio/issues/1.
//
// TODO(a.garipov): Consider moving to golibs/renameioutil once tried and
// tested.
package aghrenameio
import (
"io/fs"
"github.com/AdguardTeam/golibs/errors"
)
// PendingFile is the interface for pending temporary files.
type PendingFile interface {
// Cleanup closes the file, and removes it without performing the renaming.
// To close and rename the file, use CloseReplace.
Cleanup() (err error)
// CloseReplace closes the temporary file and replaces the destination file
// with it, possibly atomically.
//
// This method is not safe for concurrent use by multiple goroutines.
CloseReplace() (err error)
// Write writes len(b) bytes from b to the File. It returns the number of
// bytes written and an error, if any. Write returns a non-nil error when n
// != len(b).
Write(b []byte) (n int, err error)
}
// NewPendingFile is a wrapper around [renameio.NewPendingFile] on Unix systems
// and [os.CreateTemp] on Windows.
func NewPendingFile(filePath string, mode fs.FileMode) (f PendingFile, err error) {
return newPendingFile(filePath, mode)
}
// WithDeferredCleanup is a helper that performs the necessary cleanups and
// finalizations of the temporary files based on the returned error.
func WithDeferredCleanup(returned error, file PendingFile) (err error) {
// Make sure that any error returned from here is marked as a deferred one.
if returned != nil {
return errors.WithDeferred(returned, file.Cleanup())
}
return errors.WithDeferred(nil, file.CloseReplace())
}