Skip to content

Commit bf66ef5

Browse files
authored
Make FindFiles ignore (trivial) errors (#217)
Fixes #99
1 parent dd8d444 commit bf66ef5

File tree

2 files changed

+38
-8
lines changed

2 files changed

+38
-8
lines changed

script.go

+12-8
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import (
1010
"fmt"
1111
"hash"
1212
"io"
13+
"io/fs"
1314
"math"
1415
"net/http"
1516
"os"
@@ -76,8 +77,9 @@ func File(path string) *Pipe {
7677
}
7778

7879
// FindFiles creates a pipe listing all the files in the directory dir and its
79-
// subdirectories recursively, one per line, like Unix find(1). If dir doesn't
80-
// exist or can't be read, the pipe's error status will be set.
80+
// subdirectories recursively, one per line, like Unix find(1).
81+
// Errors are ignored unless no files are found (in which case the pipe's error
82+
// status will be set to the last error encountered).
8183
//
8284
// Each line of the output consists of a slash-separated path, starting with
8385
// the initial directory. For example, if the directory looks like this:
@@ -92,17 +94,19 @@ func File(path string) *Pipe {
9294
// test/2.txt
9395
func FindFiles(dir string) *Pipe {
9496
var paths []string
95-
err := filepath.Walk(dir, func(path string, info os.FileInfo, err error) error {
97+
var innerErr error
98+
fs.WalkDir(os.DirFS(dir), ".", func(path string, d fs.DirEntry, err error) error {
9699
if err != nil {
97-
return err
100+
innerErr = err
101+
return fs.SkipDir
98102
}
99-
if !info.IsDir() {
100-
paths = append(paths, path)
103+
if !d.IsDir() {
104+
paths = append(paths, filepath.Join(dir, path))
101105
}
102106
return nil
103107
})
104-
if err != nil {
105-
return NewPipe().WithError(err)
108+
if innerErr != nil && len(paths) == 0 {
109+
return NewPipe().WithError(innerErr)
106110
}
107111
return Slice(paths)
108112
}

script_unix_test.go

+26
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33
package script_test
44

55
import (
6+
"os"
7+
"path/filepath"
68
"testing"
79

810
"github.com/bitfield/script"
@@ -106,6 +108,30 @@ func TestExecPipesDataToExternalCommandAndGetsExpectedOutput(t *testing.T) {
106108
}
107109
}
108110

111+
func TestFindFiles_DoesNotErrorWhenSubDirectoryIsNotReadable(t *testing.T) {
112+
t.Parallel()
113+
tmpDir := t.TempDir()
114+
restrictedDirPath := filepath.Join(tmpDir, "a_restricted_dir")
115+
if err := os.Mkdir(restrictedDirPath, 0o000); err != nil {
116+
t.Fatal(err)
117+
}
118+
fileAPath := filepath.Join(tmpDir, "file_a.txt")
119+
if err := os.WriteFile(fileAPath, []byte("hello world!"), os.ModePerm); err != nil {
120+
t.Fatal(err)
121+
}
122+
got, err := script.FindFiles(tmpDir).String()
123+
if err != nil {
124+
t.Fatal(err)
125+
}
126+
want := fileAPath + "\n"
127+
if err != nil {
128+
t.Fatal(err)
129+
}
130+
if !cmp.Equal(want, got) {
131+
t.Fatal(cmp.Diff(want, got))
132+
}
133+
}
134+
109135
func ExampleExec_ok() {
110136
script.Exec("echo Hello, world!").Stdout()
111137
// Output:

0 commit comments

Comments
 (0)