Skip to content

Commit b275ba2

Browse files
authored
Merge pull request #19 from LandonTClipp/updates
Fixing a few things
2 parents 6f36438 + 35efbc1 commit b275ba2

File tree

5 files changed

+108
-73
lines changed

5 files changed

+108
-73
lines changed

path.go

Lines changed: 18 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,8 @@ import (
77
"strings"
88
"time"
99

10-
"github.com/pkg/errors"
1110
"github.com/LandonTClipp/afero"
11+
"github.com/pkg/errors"
1212
)
1313

1414
// Path is an object that represents a path
@@ -83,8 +83,9 @@ func doesNotImplementErr(interfaceName string, fs afero.Fs) error {
8383
// *******************************
8484

8585
// Create creates a file if possible, returning the file and an error, if any happens.
86-
func (p *Path) Create() (afero.File, error) {
87-
return p.Fs().Create(p.Path())
86+
func (p *Path) Create() (File, error) {
87+
file, err := p.Fs().Create(p.Path())
88+
return File{file}, err
8889
}
8990

9091
// Mkdir makes the current dir. If the parents don't exist, an error
@@ -200,12 +201,22 @@ func (p *Path) IsEmpty() (bool, error) {
200201
}
201202

202203
// ReadDir reads the current path and returns a list of the corresponding
203-
// Path objects.
204+
// Path objects. This function differs from os.Readdir in that it does
205+
// not call Stat() on the files. Instead, it calls Readdirnames which
206+
// is less expensive and does not force the caller to make expensive
207+
// Stat calls.
204208
func (p *Path) ReadDir() ([]*Path, error) {
205209
var paths []*Path
206-
fileInfos, err := afero.ReadDir(p.Fs(), p.Path())
207-
for _, fileInfo := range fileInfos {
208-
paths = append(paths, p.Join(fileInfo.Name()))
210+
handle, err := p.Open()
211+
if err != nil {
212+
return paths, err
213+
}
214+
children, err := handle.Readdirnames(-1)
215+
if err != nil {
216+
return paths, err
217+
}
218+
for _, child := range children {
219+
paths = append(paths, p.Join(child))
209220
}
210221
return paths, err
211222
}

path_test.go

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -301,6 +301,29 @@ func (p *PathSuite) TestEquals() {
301301
p.True(hello1.Equals(hello2))
302302
}
303303

304+
func (p *PathSuite) TestReadDir() {
305+
require.NoError(p.T(), TwoFilesAtRootTwoInSubdir(p.tmpdir))
306+
paths, err := p.tmpdir.ReadDir()
307+
p.NoError(err)
308+
p.Equal(3, len(paths))
309+
}
310+
311+
func (p *PathSuite) TestReadDirInvalidPath() {
312+
paths, err := p.tmpdir.Join("i_dont_exist").ReadDir()
313+
p.Error(err)
314+
p.Equal(0, len(paths))
315+
}
316+
317+
func (p *PathSuite) TestCreate() {
318+
msg := "hello world"
319+
file, err := p.tmpdir.Join("hello.txt").Create()
320+
p.NoError(err)
321+
defer file.Close()
322+
n, err := file.WriteString(msg)
323+
p.Equal(len(msg), n)
324+
p.NoError(err)
325+
}
326+
304327
func TestPathSuite(t *testing.T) {
305328
suite.Run(t, new(PathSuite))
306329
}

scenarios_test.go

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
package pathlib
2+
3+
import "fmt"
4+
5+
// The following functions provide different "scenarios"
6+
// that you might encounter in a filesystem tree.
7+
8+
func HelloWorld(root *Path) error {
9+
hello := root.Join("hello.txt")
10+
return hello.WriteFile([]byte("hello world"), 0o644)
11+
}
12+
13+
func OneFile(root *Path, name string, content string) error {
14+
file := root.Join(name)
15+
return file.WriteFile([]byte(content), 0o644)
16+
}
17+
18+
func NFiles(root *Path, n int) error {
19+
for i := 0; i < n; i++ {
20+
if err := OneFile(root, fmt.Sprintf("file%d.txt", i), fmt.Sprintf("file%d contents", i)); err != nil {
21+
return err
22+
}
23+
}
24+
return nil
25+
}
26+
27+
// TwoFilesAtRootTwoInSubdir creates two files in the root dir,
28+
// a directory, and creates two files inside that new directory.
29+
func TwoFilesAtRootTwoInSubdir(root *Path) error {
30+
if err := NFiles(root, 2); err != nil {
31+
return err
32+
}
33+
subdir := root.Join("subdir")
34+
if err := subdir.Mkdir(0o777); err != nil {
35+
return err
36+
}
37+
return NFiles(subdir, 2)
38+
}

walk.go

Lines changed: 20 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,9 @@ type WalkOpts struct {
1212
// infinite depth. 0 means only the direct children of root will be returned, etc.
1313
Depth int
1414

15-
// WalkAlgorithm specifies the algoritm that the Walk() function should use to
15+
// Algorithm specifies the algoritm that the Walk() function should use to
1616
// traverse the directory.
17-
WalkAlgorithm string
17+
Algorithm Algorithm
1818

1919
// FollowSymlinks defines whether symlinks should be dereferenced or not. If True,
2020
// the symlink itself will never be returned to WalkFunc, but rather whatever it
@@ -37,26 +37,25 @@ type WalkOpts struct {
3737
func DefaultWalkOpts() *WalkOpts {
3838
return &WalkOpts{
3939
Depth: -1,
40-
WalkAlgorithm: AlgorithmBasic(),
40+
Algorithm: AlgorithmBasic,
4141
FollowSymlinks: false,
42-
// VisitFirst: false,
4342
}
4443
}
4544

46-
// AlgorithmDepthFirst is a walk algorithm. It iterates over a filesystem tree
47-
// by first recursing as far down as it can in one path. Each directory is visited
48-
// only after all of its children directories have been recursed.
49-
func AlgorithmDepthFirst() string {
50-
return "depth-first"
51-
}
52-
53-
// AlgorithmBasic is a walk algorithm. It iterates over filesystem objects in the
54-
// order in which they are returned by the operating system. It guarantees no
55-
// ordering of any kind. This is the most efficient algorithm and should be used
56-
// in all cases where ordering does not matter.
57-
func AlgorithmBasic() string {
58-
return "basic"
59-
}
45+
// Algorithm represents the walk algorithm that will be performed.
46+
type Algorithm int
47+
48+
const (
49+
// AlgorithmBasic is a walk algorithm. It iterates over filesystem objects in the
50+
// order in which they are returned by the operating system. It guarantees no
51+
// ordering of any kind. This is the most efficient algorithm and should be used
52+
// in all cases where ordering does not matter.
53+
AlgorithmBasic Algorithm = iota
54+
// AlgorithmDepthFirst is a walk algorithm. It iterates over a filesystem tree
55+
// by first recursing as far down as it can in one path. Each directory is visited
56+
// only after all of its children directories have been recursed.
57+
AlgorithmDepthFirst
58+
)
6059

6160
// Walk is an object that handles walking through a directory tree
6261
type Walk struct {
@@ -207,16 +206,16 @@ type WalkFunc func(path *Path, info os.FileInfo, err error) error
207206
// Walk walks the directory using the algorithm specified in the configuration.
208207
func (w *Walk) Walk(walkFn WalkFunc) error {
209208

210-
switch w.Opts.WalkAlgorithm {
211-
case AlgorithmBasic():
209+
switch w.Opts.Algorithm {
210+
case AlgorithmBasic:
212211
if err := w.walkBasic(walkFn, w.root, 0); err != nil {
213212
if errors.Is(err, ErrStopWalk) {
214213
return nil
215214
}
216215
return err
217216
}
218217
return nil
219-
case AlgorithmDepthFirst():
218+
case AlgorithmDepthFirst:
220219
if err := w.walkDFS(walkFn, w.root, 0); err != nil {
221220
if errors.Is(err, ErrStopWalk) {
222221
return nil

walk_test.go

Lines changed: 9 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -11,44 +11,6 @@ import (
1111
"github.com/stretchr/testify/suite"
1212
)
1313

14-
// ***********************
15-
// * FILESYSTEM FIXTURES *
16-
// ***********************
17-
// The following functions provide different "scenarios"
18-
// that you might encounter in a filesystem tree.
19-
20-
func HelloWorld(root *Path) error {
21-
hello := root.Join("hello.txt")
22-
return hello.WriteFile([]byte("hello world"), 0o644)
23-
}
24-
25-
func OneFile(root *Path, name string, content string) error {
26-
file := root.Join(name)
27-
return file.WriteFile([]byte(content), 0o644)
28-
}
29-
30-
func NFiles(root *Path, n int) error {
31-
for i := 0; i < n; i++ {
32-
if err := OneFile(root, fmt.Sprintf("file%d.txt", i), fmt.Sprintf("file%d contents", i)); err != nil {
33-
return err
34-
}
35-
}
36-
return nil
37-
}
38-
39-
// TwoFilesAtRootTwoInSubdir creates two files in the root dir,
40-
// a directory, and creates two files inside that new directory.
41-
func TwoFilesAtRootTwoInSubdir(root *Path) error {
42-
if err := NFiles(root, 2); err != nil {
43-
return err
44-
}
45-
subdir := root.Join("subdir")
46-
if err := subdir.Mkdir(0o777); err != nil {
47-
return err
48-
}
49-
return NFiles(subdir, 2)
50-
}
51-
5214
// *********
5315
// * TESTS *
5416
// *********
@@ -60,7 +22,7 @@ type WalkSuiteAll struct {
6022
suite.Suite
6123
walk *Walk
6224
root *Path
63-
algorithm string
25+
algorithm Algorithm
6426
Fs afero.Fs
6527
}
6628

@@ -71,7 +33,7 @@ func (w *WalkSuiteAll) SetupTest() {
7133
w.root = NewPathAfero("/", w.Fs)
7234
w.walk, err = NewWalk(w.root)
7335
require.NoError(w.T(), err)
74-
w.walk.Opts.WalkAlgorithm = w.algorithm
36+
w.walk.Opts.Algorithm = w.algorithm
7537
}
7638

7739
func (w *WalkSuiteAll) TeardownTest() {
@@ -144,9 +106,9 @@ func (w *WalkSuiteAll) TestWalkFuncErr() {
144106
}
145107

146108
func TestWalkSuite(t *testing.T) {
147-
for _, algorithm := range []string{
148-
AlgorithmBasic(),
149-
AlgorithmDepthFirst(),
109+
for _, algorithm := range []Algorithm{
110+
AlgorithmBasic,
111+
AlgorithmDepthFirst,
150112
} {
151113
walkSuite := new(WalkSuiteAll)
152114
walkSuite.algorithm = algorithm
@@ -159,7 +121,7 @@ func TestDefaultWalkOpts(t *testing.T) {
159121
name string
160122
want *WalkOpts
161123
}{
162-
{"assert defaults", &WalkOpts{-1, AlgorithmBasic(), false, 100}},
124+
{"assert defaults", &WalkOpts{-1, AlgorithmBasic, false}},
163125
}
164126
for _, tt := range tests {
165127
t.Run(tt.name, func(t *testing.T) {
@@ -170,6 +132,8 @@ func TestDefaultWalkOpts(t *testing.T) {
170132
}
171133
}
172134

135+
var ConfusedWandering Algorithm = 0xBADC0DE
136+
173137
func TestWalk_Walk(t *testing.T) {
174138
type fields struct {
175139
Opts *WalkOpts
@@ -187,7 +151,7 @@ func TestWalk_Walk(t *testing.T) {
187151
{
188152
name: "Bad algoritm",
189153
fields: fields{
190-
Opts: &WalkOpts{WalkAlgorithm: "confused wandering"},
154+
Opts: &WalkOpts{Algorithm: ConfusedWandering},
191155
},
192156
wantErr: true,
193157
},

0 commit comments

Comments
 (0)