@@ -134,17 +134,13 @@ public func unlink(_ path: AbsolutePath) throws {
134134 - Warning: directories that cannot be entered due to permission problems
135135 are silently ignored. So keep that in mind.
136136
137- - Warning: If path doesn’t exist or cannot be entered this generator will
138- be empty. It is up to you to check `path` is valid before using this
139- function.
140-
141137 - Warning: Symbolic links that point to directories are *not* followed.
142138
143139 - Note: setting recursively to `false` still causes the generator to feed
144140 you the directory; just not its contents.
145141 */
146- public func walk( _ path: AbsolutePath , recursively: Bool = true ) -> RecursibleDirectoryContentsGenerator {
147- return RecursibleDirectoryContentsGenerator ( path: path, recursionFilter: { _ in recursively } )
142+ public func walk( _ path: AbsolutePath , fileSystem : FileSystem = localFileSystem , recursively: Bool = true ) throws -> RecursibleDirectoryContentsGenerator {
143+ return try RecursibleDirectoryContentsGenerator ( path: path, fileSystem : fileSystem , recursionFilter: { _ in recursively } )
148144}
149145
150146/**
@@ -155,86 +151,52 @@ public func walk(_ path: AbsolutePath, recursively: Bool = true) -> RecursibleDi
155151 - Warning: directories that cannot be entered due to permissions problems
156152 are silently ignored. So keep that in mind.
157153
158- - Warning: If path doesn’t exist or cannot be entered this generator will
159- be empty. It is up to you to check `path` is valid before using this
160- function.
161-
162154 - Warning: Symbolic links that point to directories are *not* followed.
163155
164156 - Note: returning `false` from `recursing` still produces that directory
165157 from the generator; just not its contents.
166158 */
167- public func walk( _ path: AbsolutePath , recursing: ( AbsolutePath ) -> Bool ) -> RecursibleDirectoryContentsGenerator {
168- return RecursibleDirectoryContentsGenerator ( path: path, recursionFilter: recursing)
169- }
170-
171- /**
172- A generator for a single directory’s contents
173- */
174- private class DirectoryContentsGenerator : IteratorProtocol {
175- private let dirptr : DirHandle ?
176- fileprivate let path : AbsolutePath
177-
178- fileprivate init ( path: AbsolutePath ) {
179- dirptr = libc. opendir ( path. asString)
180- self . path = path
181- }
182-
183- deinit {
184- if let openeddir = dirptr { closedir ( openeddir) }
185- }
186-
187- func next( ) -> dirent ? {
188- guard let validdir = dirptr else { return nil } // yuck, silently ignoring the error to maintain this pattern
189-
190- while true {
191- var entry = dirent ( )
192- var result : UnsafeMutablePointer < dirent > ? = nil
193- guard readdir_r ( validdir, & entry, & result) == 0 else { continue }
194- guard result != nil else { return nil }
195-
196- switch ( entry. d_name. 0 , entry. d_name. 1 , entry. d_name. 2 ) {
197- case ( 46 , 0 , _) : // "."
198- continue
199- case ( 46 , 46 , 0 ) : // ".."
200- continue
201- default :
202- return entry
203- }
204- }
205- }
159+ public func walk( _ path: AbsolutePath , fileSystem: FileSystem = localFileSystem, recursing: ( AbsolutePath ) -> Bool ) throws -> RecursibleDirectoryContentsGenerator {
160+ return try RecursibleDirectoryContentsGenerator ( path: path, fileSystem: fileSystem, recursionFilter: recursing)
206161}
207162
208163/**
209164 Produced by `walk`.
210165 */
211166public class RecursibleDirectoryContentsGenerator : IteratorProtocol , Sequence {
212- private var current : DirectoryContentsGenerator
167+ private var current : ( path : AbsolutePath , iterator : IndexingIterator < [ String ] > )
213168 private var towalk = [ AbsolutePath] ( )
169+
214170 private let shouldRecurse : ( AbsolutePath ) -> Bool
171+ private let fileSystem : FileSystem
215172
216- private init ( path: AbsolutePath , recursionFilter: ( AbsolutePath ) -> Bool ) {
217- current = DirectoryContentsGenerator ( path: path)
173+ private init ( path: AbsolutePath , fileSystem: FileSystem , recursionFilter: ( AbsolutePath ) -> Bool ) throws {
174+ self . fileSystem = fileSystem
175+ // FIXME: getDirectoryContents should have an iterator version.
176+ current = ( path, try fileSystem. getDirectoryContents ( path) . makeIterator ( ) )
218177 shouldRecurse = recursionFilter
219178 }
220-
179+
221180 public func next( ) -> AbsolutePath ? {
222181 outer: while true {
223- guard let entry = current. next ( ) else {
182+ guard let entry = current. iterator . next ( ) else {
224183 while !towalk. isEmpty {
184+ // FIXME: This looks inefficient.
225185 let path = towalk. removeFirst ( )
226186 guard shouldRecurse ( path) else { continue }
227- current = DirectoryContentsGenerator ( path: path)
187+ // Ignore if we can't get content for this path.
188+ guard let current = try ? fileSystem. getDirectoryContents ( path) . makeIterator ( ) else { continue }
189+ self . current = ( path, current)
228190 continue outer
229191 }
230192 return nil
231193 }
232- let name = entry . name ?? " "
233- let path = current. path. appending ( component: name )
234- if isDirectory ( path) && !isSymlink( path) {
194+
195+ let path = current. path. appending ( component: entry )
196+ if fileSystem . isDirectory ( path) && !fileSystem . isSymlink ( path) {
235197 towalk. append ( path)
236198 }
237- return current . path. appending ( component : name )
199+ return path
238200 }
239201 }
240202}
0 commit comments