Skip to content

Commit

Permalink
Improve FileEnumerator
Browse files Browse the repository at this point in the history
  • Loading branch information
Alkenso committed Sep 29, 2024
1 parent 6f9ec41 commit a404081
Showing 1 changed file with 13 additions and 9 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ public final class FileEnumerator {
public var locationFilter: ((URL) -> FilterVerdict)?

/// Forward flags to underlying `FileManager.DirectoryEnumerator`.
public var options: FileManager.DirectoryEnumerationOptions = []
public var options: (URL) -> FileManager.DirectoryEnumerationOptions = { _ in [] }

/// Creates `FileEnumerator` that enumerates given locations recursively
/// - Parameters:
Expand Down Expand Up @@ -99,21 +99,21 @@ extension FileEnumerator: Sequence, IteratorProtocol {
let type = try? next.resourceValues(forKeys: [.fileResourceTypeKey]).fileResourceType
var filterVerdict: FilterVerdict?

// If directory is not interested, skip whole content.
// If directory is not interested, skip whole content.
if type == .directory {
filterVerdict = locationFilter?(next)
if filterVerdict?.children == false {
enumerator?.skipDescendants()
}
}

// Check if `next` is interested according to its type.
// Check if `next` is interested according to its type.
if !types.isEmpty {
guard let type else { continue }
guard types.contains(type) else { continue }
}

// Check if `next` is interested according to its URL.
// Check if `next` is interested according to its URL.
if let verdict = filterVerdict ?? locationFilter?(next), !verdict.current {
continue
}
Expand All @@ -125,25 +125,29 @@ extension FileEnumerator: Sequence, IteratorProtocol {
}

private func nextUnfiltered() -> URL? {
// If next file exists, just return it.
// If next file exists, just return it.
if let next = enumerator?.nextObject() as? URL {
return next
}

// All files/locations enumerated. 'nil' means the end of the sequence.
// All files/locations enumerated. 'nil' means the end of the sequence.
guard let nextLocation = locations.popLast() else {
return nil
}

// If location doesn't exists, just skip it.
// If location doesn't exists, just skip it.
var isDirectory = false
guard FileManager.default.fileExists(at: nextLocation, isDirectory: &isDirectory) else {
return nextUnfiltered()
}

// If location is directory, update enumerator.
// If location is directory, update enumerator.
if isDirectory {
enumerator = FileManager.default.enumerator(at: nextLocation, includingPropertiesForKeys: [.fileResourceTypeKey], options: options)
enumerator = FileManager.default.enumerator(
at: nextLocation,
includingPropertiesForKeys: [.fileResourceTypeKey],
options: options(nextLocation)
)
}

return nextLocation
Expand Down

0 comments on commit a404081

Please sign in to comment.