mirror of
https://github.com/m-housh/dotfiles.git
synced 2026-02-14 14:12:41 +00:00
wip
This commit is contained in:
70
dots/Sources/FileClient/Client.swift
Normal file
70
dots/Sources/FileClient/Client.swift
Normal file
@@ -0,0 +1,70 @@
|
||||
import Dependencies
|
||||
import Foundation
|
||||
#if canImport(FoundationNetworking)
|
||||
import FoundationNetworking
|
||||
#endif
|
||||
import XCTestDynamicOverlay
|
||||
|
||||
/// Represents interactions with the file system.
|
||||
///
|
||||
public struct FileClient {
|
||||
|
||||
public var configDirectory: () -> URL
|
||||
public var createDirectory: (URL, Bool) async throws -> Void
|
||||
public var createSymlink: (URL, URL) async throws -> Void
|
||||
public var dotfilesDirectory: () -> URL
|
||||
public var homeDirectory: () -> URL
|
||||
public var exists: (URL) async throws -> Bool
|
||||
public var readFile: (URL) async throws -> Data
|
||||
public var moveToTrash: (URL) async throws -> Void
|
||||
public var writeFile: (Data, URL) async throws -> Void
|
||||
|
||||
public func createDirectory(
|
||||
at url: URL,
|
||||
withIntermediates: Bool = true
|
||||
) async throws {
|
||||
let exists = try await self.exists(url)
|
||||
if !exists {
|
||||
try await createDirectory(url, withIntermediates)
|
||||
}
|
||||
}
|
||||
|
||||
public func createSymlink(
|
||||
source: URL,
|
||||
destination: URL
|
||||
) async throws {
|
||||
try await self.createSymlink(source, destination)
|
||||
}
|
||||
|
||||
public func read(file: URL) async throws -> Data {
|
||||
try await self.readFile(file)
|
||||
}
|
||||
|
||||
public func write(data: Data, to file: URL) async throws {
|
||||
try await writeFile(data, file)
|
||||
}
|
||||
}
|
||||
|
||||
extension FileClient: TestDependencyKey {
|
||||
public static let noop = Self.init(
|
||||
configDirectory: unimplemented(placeholder: URL(string: "/")!),
|
||||
createDirectory: unimplemented(),
|
||||
createSymlink: unimplemented(),
|
||||
dotfilesDirectory: unimplemented(placeholder: URL(string: "/")!),
|
||||
homeDirectory: unimplemented(),
|
||||
exists: unimplemented(placeholder: false),
|
||||
readFile: unimplemented(placeholder: Data()),
|
||||
moveToTrash: unimplemented(),
|
||||
writeFile: unimplemented()
|
||||
)
|
||||
|
||||
public static let testValue: FileClient = .noop
|
||||
|
||||
}
|
||||
|
||||
extension DependencyValues {
|
||||
public var fileClient: FileClient {
|
||||
get { self[FileClient.self] }
|
||||
set { self[FileClient.self] = newValue }
|
||||
}
|
||||
}
|
||||
78
dots/Sources/FileClient/LiveKey.swift
Normal file
78
dots/Sources/FileClient/LiveKey.swift
Normal file
@@ -0,0 +1,78 @@
|
||||
import Dependencies
|
||||
import Foundation
|
||||
#if canImport(FoundationNetworking)
|
||||
import FoundationNetworking
|
||||
#endif
|
||||
|
||||
extension FileClient: DependencyKey {
|
||||
|
||||
public static var liveValue: FileClient {
|
||||
.live(environment: ProcessInfo.processInfo.environment)
|
||||
}
|
||||
|
||||
public static func live(environment: [String: String] = [:]) -> Self {
|
||||
let environment = Environment(environment: environment)
|
||||
return .init(
|
||||
configDirectory: {
|
||||
guard let xdgConfigHome = environment.xdgConfigHome,
|
||||
let configUrl = URL(string: xdgConfigHome)
|
||||
else {
|
||||
return FileManager.default.homeDirectoryForCurrentUser
|
||||
.appendingPathComponent(".config")
|
||||
}
|
||||
return configUrl
|
||||
},
|
||||
createDirectory: { url, withIntermediates in
|
||||
try FileManager.default.createDirectory(
|
||||
at: url,
|
||||
withIntermediateDirectories: withIntermediates
|
||||
)
|
||||
},
|
||||
createSymlink: { source, destination in
|
||||
try FileManager.default.createSymbolicLink(
|
||||
at: source,
|
||||
withDestinationURL: destination
|
||||
)
|
||||
},
|
||||
dotfilesDirectory: {
|
||||
guard let dotfiles = environment.dotfilesDirectory,
|
||||
let dotfilesUrl = URL(string: dotfiles)
|
||||
else {
|
||||
return FileManager.default.homeDirectoryForCurrentUser
|
||||
.appendingPathComponent(".dotfiles")
|
||||
}
|
||||
return dotfilesUrl
|
||||
},
|
||||
homeDirectory: {
|
||||
FileManager.default.homeDirectoryForCurrentUser
|
||||
},
|
||||
exists: { path in
|
||||
FileManager.default.fileExists(atPath: path.absoluteString)
|
||||
},
|
||||
readFile: { path in
|
||||
try Data(contentsOf: path)
|
||||
},
|
||||
moveToTrash: { path in
|
||||
try FileManager.default.trashItem(at: path, resultingItemURL: nil)
|
||||
},
|
||||
writeFile: { data, path in
|
||||
try data.write(to: path)
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
fileprivate struct Environment {
|
||||
let xdgConfigHome: String?
|
||||
let dotfilesDirectory: String?
|
||||
|
||||
enum CodingKeys: String, CodingKey {
|
||||
case xdgConfigHome = "XDG_CONFIG_HOME"
|
||||
case dotfilesDirectory = "DOTFILES"
|
||||
}
|
||||
|
||||
init(environment: [String: String]) {
|
||||
self.xdgConfigHome = environment[CodingKeys.xdgConfigHome.rawValue]
|
||||
self.dotfilesDirectory = environment[CodingKeys.dotfilesDirectory.rawValue]
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user