CHGenerator/WebsiteGenerator/FileSystem.swift
Christoph Hagen 14b935249f First version
2022-08-16 10:39:05 +02:00

100 lines
2.5 KiB
Swift

import Foundation
enum FileSystem {
fileprivate static var fm: FileManager { .default }
static func folders(in folder: URL) throws -> [URL] {
try fm.contentsOfDirectory(at: folder, includingPropertiesForKeys: [.isDirectoryKey])
.filter { $0.isDirectory }
}
static func copy(_ source: URL, to destination: URL) throws {
try destination.ensureParentFolderExistence()
try source.copy(to: destination)
}
}
extension URL {
func ensureParentFolderExistence() throws {
try deletingLastPathComponent().ensureFolderExistence()
}
func ensureFolderExistence() throws {
if !exists {
print("Creating directory \(path)")
try wrap(.failedToWriteFile(path)) {
try FileManager.default.createDirectory(at: self, withIntermediateDirectories: true)
}
}
}
var isDirectory: Bool {
(try? resourceValues(forKeys: [.isDirectoryKey]))?.isDirectory == true
}
var exists: Bool {
FileSystem.fm.fileExists(atPath: path)
}
func delete() throws {
try FileSystem.fm.removeItem(at: self)
}
func copy(to url: URL) throws {
try wrap(.failedToWriteFile(url.path)) {
if url.exists {
try url.delete()
}
try url.ensureParentFolderExistence()
try FileSystem.fm.copyItem(at: self, to: url)
}
}
}
extension Data {
func createFolderAndWrite(to url: URL) throws {
try url.ensureParentFolderExistence()
// if url.exists {
// print("Overwriting \(url.path)")
// }
try wrap(.failedToWriteFile(url.path)) {
try write(to: url)
}
}
}
extension String {
func createFolderAndWrite(to url: URL) throws {
try data(using: .utf8)!.createFolderAndWrite(to: url)
}
}
extension Encodable {
func writeJSON(to url: URL) throws {
let encoder = JSONEncoder()
encoder.outputFormatting = .prettyPrinted
let content = try wrap(.failedToEncodeJSON(url.path)) {
try encoder.encode(self)
}
try content.createFolderAndWrite(to: url)
}
}
extension Decodable {
init(decodeFrom url: URL) throws {
let data = try wrap(.failedToOpenFile(url.path)) {
try Data(contentsOf: url)
}
self = try wrap({ .failedToDecodeJSON(file: url.path, error: $0.localizedDescription)}) {
try JSONDecoder().decode(Self.self, from: data)
}
}
}