113 lines
3.4 KiB
Swift
113 lines
3.4 KiB
Swift
import Foundation
|
|
import ExpoModulesCore
|
|
|
|
internal final class FileSystemDirectory: FileSystemPath {
|
|
init(url: URL) {
|
|
super.init(url: url, isDirectory: true)
|
|
}
|
|
|
|
override func validateType() throws {
|
|
try withCorrectTypeAndScopedAccess(permission: .read) {
|
|
var isDirectory: ObjCBool = false
|
|
if FileManager.default.fileExists(atPath: url.path, isDirectory: &isDirectory) {
|
|
if !isDirectory.boolValue {
|
|
throw InvalidTypeDirectoryException()
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
func create(_ options: CreateOptions) throws {
|
|
try withCorrectTypeAndScopedAccess(permission: .write) {
|
|
guard try needsCreation(options) else {
|
|
return
|
|
}
|
|
try validateCanCreate(options)
|
|
do {
|
|
try FileManager.default.createDirectory(at: url, withIntermediateDirectories: options.intermediates, attributes: nil)
|
|
} catch {
|
|
throw UnableToCreateException(error.localizedDescription)
|
|
}
|
|
}
|
|
}
|
|
|
|
var size: Int64 {
|
|
get throws {
|
|
try validatePermission(.read)
|
|
var size: Int64 = 0
|
|
guard let subpaths = try? FileManager.default.subpathsOfDirectory(atPath: url.path) else {
|
|
throw UnableToGetSizeException("attributes do not contain size")
|
|
}
|
|
for subpath in subpaths {
|
|
let strSubpath = url.appendingPathComponent(subpath).path
|
|
guard let attributes: [FileAttributeKey: Any] = try? FileManager.default.attributesOfItem(atPath: strSubpath), let subpathSize = attributes[.size] as? Int64 else {
|
|
continue
|
|
}
|
|
size += subpathSize
|
|
}
|
|
return size
|
|
}
|
|
}
|
|
|
|
override var exists: Bool {
|
|
guard checkPermission(.read) else {
|
|
return false
|
|
}
|
|
var isDirectory: ObjCBool = false
|
|
if FileManager.default.fileExists(atPath: url.path, isDirectory: &isDirectory) {
|
|
return isDirectory.boolValue
|
|
}
|
|
return false
|
|
}
|
|
|
|
// Internal only function
|
|
func listAsRecords() throws -> [[String: Any]] {
|
|
try withCorrectTypeAndScopedAccess(permission: .read) {
|
|
var contents: [[String: Any]] = []
|
|
|
|
let items = try FileManager.default.contentsOfDirectory(at: url, includingPropertiesForKeys: nil)
|
|
for item in items {
|
|
contents.append(["isDirectory": item.hasDirectoryPath, "uri": item.absoluteString])
|
|
}
|
|
return contents
|
|
}
|
|
}
|
|
|
|
func validatePath() throws {
|
|
guard url.isFileURL && url.hasDirectoryPath else {
|
|
throw Exception(name: "wrong type", description: "tried to create a directory with a file path")
|
|
}
|
|
}
|
|
|
|
func info() throws -> DirectoryInfo {
|
|
try withCorrectTypeAndScopedAccess(permission: .read) {
|
|
if !exists {
|
|
let result = DirectoryInfo()
|
|
result.exists = false
|
|
result.uri = url.absoluteString
|
|
return result
|
|
}
|
|
switch url.scheme {
|
|
case "file":
|
|
let result = DirectoryInfo()
|
|
result.exists = true
|
|
result.uri = url.absoluteString
|
|
result.size = try size
|
|
result.files = (try? FileManager.default.contentsOfDirectory(atPath: url.path)) ?? []
|
|
result.modificationTime = try modificationTime
|
|
result.creationTime = try creationTime
|
|
return result
|
|
default:
|
|
throw UnableToGetInfoException("url scheme \(String(describing: url.scheme)) is not supported")
|
|
}
|
|
}
|
|
}
|
|
|
|
func needsCreation(_ options: CreateOptions) throws -> Bool {
|
|
if !exists {
|
|
return true
|
|
}
|
|
return !options.idempotent
|
|
}
|
|
}
|