Sapling/Sources/SaplingStorage/Configuration.swift

78 lines
2.7 KiB
Swift

import Foundation
public struct SaplingConfiguration: Hashable, Codable, Sendable {
public var lastOpenedWorkspaceURL: URL?
public var recentWorkspaceURLs: [URL]
public var defaultBranchName: String
public var autosavesDrafts: Bool
public var showsHiddenFiles: Bool
public var preferredEditorFontSize: Double
public init(
lastOpenedWorkspaceURL: URL? = nil,
recentWorkspaceURLs: [URL] = [],
defaultBranchName: String = "main",
autosavesDrafts: Bool = true,
showsHiddenFiles: Bool = false,
preferredEditorFontSize: Double = 15
) {
self.lastOpenedWorkspaceURL = lastOpenedWorkspaceURL
self.recentWorkspaceURLs = recentWorkspaceURLs
self.defaultBranchName = defaultBranchName
self.autosavesDrafts = autosavesDrafts
self.showsHiddenFiles = showsHiddenFiles
self.preferredEditorFontSize = preferredEditorFontSize
}
}
public protocol ConfigurationStore: Sendable {
func loadConfiguration() throws -> SaplingConfiguration
func saveConfiguration(_ configuration: SaplingConfiguration) throws
}
public final class InMemoryConfigurationStore: ConfigurationStore, @unchecked Sendable {
private var configuration: SaplingConfiguration
public init(configuration: SaplingConfiguration = SaplingConfiguration()) {
self.configuration = configuration
}
public func loadConfiguration() throws -> SaplingConfiguration {
configuration
}
public func saveConfiguration(_ configuration: SaplingConfiguration) throws {
self.configuration = configuration
}
}
public final class JSONConfigurationStore: ConfigurationStore, @unchecked Sendable {
private let fileURL: URL
private let encoder: JSONEncoder
private let decoder: JSONDecoder
public init(fileURL: URL) {
self.fileURL = fileURL
self.encoder = JSONEncoder()
self.decoder = JSONDecoder()
encoder.outputFormatting = [.prettyPrinted, .sortedKeys]
}
public func loadConfiguration() throws -> SaplingConfiguration {
guard FileManager.default.fileExists(atPath: fileURL.path) else {
return SaplingConfiguration()
}
let data = try Data(contentsOf: fileURL)
return try decoder.decode(SaplingConfiguration.self, from: data)
}
public func saveConfiguration(_ configuration: SaplingConfiguration) throws {
try FileManager.default.createDirectory(
at: fileURL.deletingLastPathComponent(),
withIntermediateDirectories: true
)
let data = try encoder.encode(configuration)
try data.write(to: fileURL, options: [.atomic])
}
}