30
30
package paths
31
31
32
32
import (
33
- "io/ioutil"
33
+ "errors"
34
+ "os"
34
35
"strings"
35
36
)
36
37
@@ -41,7 +42,7 @@ type ReadDirFilter func(file *Path) bool
41
42
// ReadDir returns a PathList containing the content of the directory
42
43
// pointed by the current Path. The resulting list is filtered by the given filters chained.
43
44
func (p * Path ) ReadDir (filters ... ReadDirFilter ) (PathList , error ) {
44
- infos , err := ioutil .ReadDir (p .path )
45
+ infos , err := os .ReadDir (p .path )
45
46
if err != nil {
46
47
return nil , err
47
48
}
@@ -69,27 +70,7 @@ func (p *Path) ReadDir(filters ...ReadDirFilter) (PathList, error) {
69
70
// ReadDirRecursive returns a PathList containing the content of the directory
70
71
// and its subdirectories pointed by the current Path
71
72
func (p * Path ) ReadDirRecursive () (PathList , error ) {
72
- infos , err := ioutil .ReadDir (p .path )
73
- if err != nil {
74
- return nil , err
75
- }
76
- paths := PathList {}
77
- for _ , info := range infos {
78
- path := p .Join (info .Name ())
79
- paths .Add (path )
80
-
81
- if isDir , err := path .IsDirCheck (); err != nil {
82
- return nil , err
83
- } else if isDir {
84
- subPaths , err := path .ReadDirRecursive ()
85
- if err != nil {
86
- return nil , err
87
- }
88
- paths .AddAll (subPaths )
89
- }
90
-
91
- }
92
- return paths , nil
73
+ return p .ReadDirRecursiveFiltered (nil )
93
74
}
94
75
95
76
// ReadDirRecursiveFiltered returns a PathList containing the content of the directory
@@ -101,41 +82,55 @@ func (p *Path) ReadDirRecursive() (PathList, error) {
101
82
// - `filters` are the filters that are checked to determine if the entry should be
102
83
// added to the resulting PathList
103
84
func (p * Path ) ReadDirRecursiveFiltered (recursionFilter ReadDirFilter , filters ... ReadDirFilter ) (PathList , error ) {
104
- infos , err := ioutil .ReadDir (p .path )
105
- if err != nil {
106
- return nil , err
107
- }
85
+ var search func (* Path ) (PathList , error )
108
86
109
- accept := func ( p * Path ) bool {
110
- for _ , filter := range filters {
111
- if ! filter ( p ) {
112
- return false
113
- }
87
+ explored := map [ string ] bool {}
88
+ search = func ( currPath * Path ) ( PathList , error ) {
89
+ canonical := currPath . Canonical (). path
90
+ if explored [ canonical ] {
91
+ return nil , errors . New ( "directories symlink loop detected" )
114
92
}
115
- return true
116
- }
93
+ explored [ canonical ] = true
94
+ defer delete ( explored , canonical )
117
95
118
- paths := PathList {}
119
- for _ , info := range infos {
120
- path := p .Join (info .Name ())
96
+ infos , err := os .ReadDir (currPath .path )
97
+ if err != nil {
98
+ return nil , err
99
+ }
121
100
122
- if accept (path ) {
123
- paths .Add (path )
101
+ accept := func (p * Path ) bool {
102
+ for _ , filter := range filters {
103
+ if ! filter (p ) {
104
+ return false
105
+ }
106
+ }
107
+ return true
124
108
}
125
109
126
- if recursionFilter == nil || recursionFilter (path ) {
127
- if isDir , err := path .IsDirCheck (); err != nil {
128
- return nil , err
129
- } else if isDir {
130
- subPaths , err := path .ReadDirRecursiveFiltered (recursionFilter , filters ... )
131
- if err != nil {
110
+ paths := PathList {}
111
+ for _ , info := range infos {
112
+ path := currPath .Join (info .Name ())
113
+
114
+ if accept (path ) {
115
+ paths .Add (path )
116
+ }
117
+
118
+ if recursionFilter == nil || recursionFilter (path ) {
119
+ if isDir , err := path .IsDirCheck (); err != nil {
132
120
return nil , err
121
+ } else if isDir {
122
+ subPaths , err := search (path )
123
+ if err != nil {
124
+ return nil , err
125
+ }
126
+ paths .AddAll (subPaths )
133
127
}
134
- paths .AddAll (subPaths )
135
128
}
136
129
}
130
+ return paths , nil
137
131
}
138
- return paths , nil
132
+
133
+ return search (p )
139
134
}
140
135
141
136
// FilterDirectories is a ReadDirFilter that accepts only directories
0 commit comments