Modernize error handling in local backend
* Stop prepending the operation name: it's already part of os.PathError, leading to repetitive errors like "Chmod: chmod /foo/bar: operation not permitted". * Use errors.Is to check for specific errors.
This commit is contained in:
parent
d7322a5f36
commit
e5f0f67ba0
2 changed files with 13 additions and 11 deletions
|
@ -64,7 +64,7 @@ func Create(ctx context.Context, cfg Config) (*Local, error) {
|
||||||
for _, d := range be.Paths() {
|
for _, d := range be.Paths() {
|
||||||
err := fs.MkdirAll(d, backend.Modes.Dir)
|
err := fs.MkdirAll(d, backend.Modes.Dir)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrap(err, "MkdirAll")
|
return nil, errors.WithStack(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -78,7 +78,7 @@ func (b *Local) Location() string {
|
||||||
|
|
||||||
// IsNotExist returns true if the error is caused by a non existing file.
|
// IsNotExist returns true if the error is caused by a non existing file.
|
||||||
func (b *Local) IsNotExist(err error) bool {
|
func (b *Local) IsNotExist(err error) bool {
|
||||||
return os.IsNotExist(errors.Cause(err))
|
return errors.Is(err, os.ErrNotExist)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Save stores data in the backend at the handle.
|
// Save stores data in the backend at the handle.
|
||||||
|
@ -114,14 +114,14 @@ func (b *Local) Save(ctx context.Context, h restic.Handle, rd restic.RewindReade
|
||||||
}
|
}
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrap(err, "OpenFile")
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// save data, then sync
|
// save data, then sync
|
||||||
wbytes, err := io.Copy(f, rd)
|
wbytes, err := io.Copy(f, rd)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
_ = f.Close()
|
_ = f.Close()
|
||||||
return errors.Wrap(err, "Write")
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
// sanity check
|
// sanity check
|
||||||
if wbytes != rd.Length() {
|
if wbytes != rd.Length() {
|
||||||
|
@ -135,13 +135,13 @@ func (b *Local) Save(ctx context.Context, h restic.Handle, rd restic.RewindReade
|
||||||
// ignore error if filesystem does not support the sync operation
|
// ignore error if filesystem does not support the sync operation
|
||||||
if !isNotSupported {
|
if !isNotSupported {
|
||||||
_ = f.Close()
|
_ = f.Close()
|
||||||
return errors.Wrap(err, "Sync")
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
err = f.Close()
|
err = f.Close()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrap(err, "Close")
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// try to mark file as read-only to avoid accidential modifications
|
// try to mark file as read-only to avoid accidential modifications
|
||||||
|
@ -149,7 +149,7 @@ func (b *Local) Save(ctx context.Context, h restic.Handle, rd restic.RewindReade
|
||||||
// e.g. exfat and network file systems with certain mount options
|
// e.g. exfat and network file systems with certain mount options
|
||||||
err = setFileReadonly(filename, backend.Modes.File)
|
err = setFileReadonly(filename, backend.Modes.File)
|
||||||
if err != nil && !os.IsPermission(err) {
|
if err != nil && !os.IsPermission(err) {
|
||||||
return errors.Wrap(err, "Chmod")
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
@ -202,7 +202,7 @@ func (b *Local) Stat(ctx context.Context, h restic.Handle) (restic.FileInfo, err
|
||||||
|
|
||||||
fi, err := fs.Stat(b.Filename(h))
|
fi, err := fs.Stat(b.Filename(h))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return restic.FileInfo{}, errors.Wrap(err, "Stat")
|
return restic.FileInfo{}, errors.WithStack(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return restic.FileInfo{Size: fi.Size(), Name: h.Name}, nil
|
return restic.FileInfo{Size: fi.Size(), Name: h.Name}, nil
|
||||||
|
@ -213,10 +213,10 @@ func (b *Local) Test(ctx context.Context, h restic.Handle) (bool, error) {
|
||||||
debug.Log("Test %v", h)
|
debug.Log("Test %v", h)
|
||||||
_, err := fs.Stat(b.Filename(h))
|
_, err := fs.Stat(b.Filename(h))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if os.IsNotExist(errors.Cause(err)) {
|
if b.IsNotExist(err) {
|
||||||
return false, nil
|
return false, nil
|
||||||
}
|
}
|
||||||
return false, errors.Wrap(err, "Stat")
|
return false, errors.WithStack(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return true, nil
|
return true, nil
|
||||||
|
@ -230,7 +230,7 @@ func (b *Local) Remove(ctx context.Context, h restic.Handle) error {
|
||||||
// reset read-only flag
|
// reset read-only flag
|
||||||
err := fs.Chmod(fn, 0666)
|
err := fs.Chmod(fn, 0666)
|
||||||
if err != nil && !os.IsPermission(err) {
|
if err != nil && !os.IsPermission(err) {
|
||||||
return errors.Wrap(err, "Chmod")
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return fs.Remove(fn)
|
return fs.Remove(fn)
|
||||||
|
|
|
@ -27,6 +27,8 @@ var Wrapf = errors.Wrapf
|
||||||
// returns nil.
|
// returns nil.
|
||||||
var WithMessage = errors.WithMessage
|
var WithMessage = errors.WithMessage
|
||||||
|
|
||||||
|
var WithStack = errors.WithStack
|
||||||
|
|
||||||
// Cause returns the cause of an error. It will also unwrap certain errors,
|
// Cause returns the cause of an error. It will also unwrap certain errors,
|
||||||
// e.g. *url.Error returned by the net/http client.
|
// e.g. *url.Error returned by the net/http client.
|
||||||
func Cause(err error) error {
|
func Cause(err error) error {
|
||||||
|
|
Loading…
Reference in a new issue