2021-08-17 12:46:50 +00:00
|
|
|
//go:build windows
|
2019-10-29 11:26:39 +00:00
|
|
|
// +build windows
|
|
|
|
|
|
|
|
package tools
|
|
|
|
|
|
|
|
import (
|
|
|
|
"os"
|
|
|
|
|
|
|
|
"github.com/avast/retry-go"
|
2020-10-25 23:01:36 +00:00
|
|
|
"golang.org/x/sys/windows"
|
2019-10-29 11:26:39 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
func underlyingError(err error) error {
|
|
|
|
switch err := err.(type) {
|
|
|
|
case *os.PathError:
|
|
|
|
return err.Err
|
|
|
|
case *os.LinkError:
|
|
|
|
return err.Err
|
|
|
|
case *os.SyscallError:
|
|
|
|
return err.Err
|
|
|
|
}
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
// isEphemeralError returns true if err may be resolved by waiting.
|
|
|
|
func isEphemeralError(err error) bool {
|
|
|
|
// TODO: Use this instead for Go >= 1.13
|
2020-10-25 23:01:36 +00:00
|
|
|
// return errors.Is(err, windows.ERROR_SHARING_VIOLATION)
|
2019-10-29 11:26:39 +00:00
|
|
|
|
|
|
|
err = underlyingError(err)
|
2020-10-25 23:01:36 +00:00
|
|
|
return err == windows.ERROR_SHARING_VIOLATION
|
2019-10-29 11:26:39 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func RobustRename(oldpath, newpath string) error {
|
|
|
|
return retry.Do(
|
|
|
|
func() error {
|
|
|
|
return os.Rename(oldpath, newpath)
|
|
|
|
},
|
|
|
|
retry.RetryIf(isEphemeralError),
|
|
|
|
retry.LastErrorOnly(true),
|
|
|
|
)
|
|
|
|
}
|
|
|
|
|
|
|
|
func RobustOpen(name string) (*os.File, error) {
|
|
|
|
var result *os.File
|
|
|
|
return result, retry.Do(
|
|
|
|
func() error {
|
|
|
|
f, err := os.Open(name)
|
|
|
|
result = f
|
|
|
|
return err
|
|
|
|
},
|
|
|
|
retry.RetryIf(isEphemeralError),
|
|
|
|
retry.LastErrorOnly(true),
|
|
|
|
)
|
|
|
|
}
|