Ensure 'not exist' errors wrap os.ErrNotExist (#3982)

* Ensure 'not exist' errors wrap os.ErrNotExist

* Update go.sum

* Use an error type to avoid changing the error's string
This commit is contained in:
Francesc Campoy
2021-06-11 09:44:59 -07:00
committed by GitHub
parent 065432e074
commit 199802a176
3 changed files with 57 additions and 6 deletions

View File

@@ -0,0 +1,40 @@
package filesys
import (
"os"
"testing"
"github.com/pkg/errors"
"github.com/stretchr/testify/assert"
)
var filesysBuilders = map[string]func() FileSystem{
"MakeFsInMemory": MakeFsInMemory,
"MakeFsOnDisk": MakeFsOnDisk,
"MakeEmptyDirInMemory": func() FileSystem { return MakeEmptyDirInMemory() },
}
func TestNotExistErr(t *testing.T) {
for name, builder := range filesysBuilders {
t.Run(name, func(t *testing.T) {
testNotExistErr(t, builder())
})
}
}
func testNotExistErr(t *testing.T, fs FileSystem) {
const path = "bad-dir/file.txt"
err := fs.RemoveAll(path)
assert.Falsef(t, errors.Is(err, os.ErrNotExist), "RemoveAll should not return ErrNotExist, got %v", err)
_, err = fs.Open(path)
assert.Truef(t, errors.Is(err, os.ErrNotExist), "Open should return ErrNotExist, got %v", err)
_, err = fs.ReadDir(path)
assert.Truef(t, errors.Is(err, os.ErrNotExist), "ReadDir should return ErrNotExist, got %v", err)
_, _, err = fs.CleanedAbs(path)
assert.Truef(t, errors.Is(err, os.ErrNotExist), "CleanedAbs should return ErrNotExist, got %v", err)
_, err = fs.ReadFile(path)
assert.Truef(t, errors.Is(err, os.ErrNotExist), "ReadFile should return ErrNotExist, got %v", err)
err = fs.Walk(path, func(_ string, _ os.FileInfo, err error) error { return err })
assert.Truef(t, errors.Is(err, os.ErrNotExist), "Walk should return ErrNotExist, got %v", err)
}

View File

@@ -236,7 +236,7 @@ func (n *fsNode) CleanedAbs(path string) (ConfirmedDir, string, error) {
return "", "", errors.Wrap(err, "unable to clean")
}
if node == nil {
return "", "", fmt.Errorf("'%s' doesn't exist", path)
return "", "", notExistError(path)
}
if node.isNodeADir() {
return ConfirmedDir(node.Path()), "", nil
@@ -309,7 +309,8 @@ func (n *fsNode) RemoveAll(path string) error {
return err
}
if result == nil {
return fmt.Errorf("cannot find '%s' to remove it", path)
// If the path doesn't exist, no need to remove anything.
return nil
}
return result.Remove()
}
@@ -351,6 +352,9 @@ func (n *fsNode) IsDir(path string) bool {
// ReadDir implements FileSystem.
func (n *fsNode) ReadDir(path string) ([]string, error) {
if !n.Exists(path) {
return nil, notExistError(path)
}
if !n.IsDir(path) {
return nil, fmt.Errorf("%s is not a directory", path)
}
@@ -398,7 +402,7 @@ func (n *fsNode) Open(path string) (File, error) {
return nil, err
}
if result == nil {
return nil, fmt.Errorf("cannot find '%s' to open it", path)
return nil, notExistError(path)
}
if result.offset != nil {
return nil, fmt.Errorf("cannot open previously opened file '%s'", path)
@@ -423,7 +427,7 @@ func (n *fsNode) ReadFile(path string) (c []byte, err error) {
return nil, err
}
if result == nil {
return nil, fmt.Errorf("cannot find '%s' to read it", path)
return nil, notExistError(path)
}
if result.isNodeADir() {
return nil, fmt.Errorf("cannot read content from non-file '%s'", n.Path())
@@ -490,7 +494,7 @@ func (n *fsNode) Walk(path string, walkFn filepath.WalkFunc) error {
return err
}
if result == nil {
return fmt.Errorf("cannot find '%s' to walk it", path)
return notExistError(path)
}
return result.WalkMe(walkFn)
}
@@ -629,3 +633,10 @@ func (n *fsNode) Glob(pattern string) ([]string, error) {
sort.Strings(result)
return result, nil
}
// notExistError indicates that a file or directory does not exist.
// Unwrapping returns os.ErrNotExist so errors.Is(err, os.ErrNotExist) works correctly.
type notExistError string
func (err notExistError) Error() string { return fmt.Sprintf("'%s' doesn't exist", string(err)) }
func (err notExistError) Unwrap() error { return os.ErrNotExist }

View File

@@ -57,7 +57,7 @@ func (x fsOnDisk) CleanedAbs(
deLinked, err := filepath.EvalSymlinks(absRoot)
if err != nil {
return "", "", fmt.Errorf(
"evalsymlink failure on '%s' : %v", path, err)
"evalsymlink failure on '%s' : %w", path, err)
}
if x.IsDir(deLinked) {
return ConfirmedDir(deLinked), "", nil