This commit is contained in:
2023-03-05 14:37:02 -05:00
parent 5b8b912844
commit 8524efb765
23 changed files with 926 additions and 11 deletions

View File

@@ -0,0 +1,95 @@
import Dependencies
import CliMiddleware
import FileClient
import Foundation
import LoggingDependency
import ShellClient
struct Brew {
@Dependency(\.fileClient) var fileClient
@Dependency(\.globals.dryRun) var dryRun
@Dependency(\.logger) var logger
@Dependency(\.shellClient) var shellClient
let context: CliMiddleware.BrewContext
func run() async throws {
logger.info("Installing homebrew dependencies.")
for brewfile in try context.routes.brewfiles() {
logger.info("Installing dependencies from brewfile: \(brewfile.absoluteString)")
if !dryRun {
try shellClient.install(brewfile: brewfile)
logger.debug("Done installing dependencies from brewfile: \(brewfile.absoluteString)")
}
}
logger.info("Done installing homebrew dependencies.")
}
}
extension ShellClient {
func install(brewfile: URL) throws {
try foregroundShell(
"/opt/homebrew/bin/brew",
"bundle",
"--no-lock",
"--cleanup",
"--debug",
"--file",
brewfile.absoluteString
)
}
}
fileprivate extension FileClient {
var brewFileDirectory: URL {
dotfilesDirectory()
.appendingPathComponent("macOS")
.appendingPathComponent(".config")
.appendingPathComponent("macOS")
}
}
fileprivate extension CliMiddleware.BrewContext.Route {
static func allBrews() throws -> [URL] {
let brews: [Self] = [.appStore, .brews, .casks]
return try brews.map { try $0.brewfile() }
}
func brewfile() throws -> URL {
@Dependency(\.fileClient) var fileClient
switch self {
case .all:
// should never happen.
throw BrewfileError()
case .appStore:
return fileClient.brewFileDirectory.appendingPathComponent("AppStore.Brewfile")
case .brews:
return fileClient.brewFileDirectory.appendingPathComponent("Brewfile")
case .casks:
return fileClient.brewFileDirectory.appendingPathComponent("Casks.Brewfile")
}
}
}
fileprivate extension Array where Element == CliMiddleware.BrewContext.Route {
func brewfiles() throws -> [URL] {
if self.count == 1 && self.first == .all {
return try CliMiddleware.BrewContext.Route.allBrews()
}
var urls = [URL]()
for route in self {
if route != .all {
let url = try route.brewfile()
urls.append(url)
}
}
return urls
}
}
struct BrewfileError: Error { }

View File

@@ -0,0 +1,87 @@
import CliMiddleware
import Dependencies
import FileClient
import Foundation
import LoggingDependency
#if canImport(FoundationNetworking)
import FoundationNetworking
#endif
struct Zsh {
@Dependency(\.globals.dryRun) var dryRun
@Dependency(\.fileClient) var fileClient
@Dependency(\.logger) var logger
let context: CliMiddleware.ZshContext
func install() async throws {
let configString = fileClient.zshConfigDestination.absoluteString
.replacingOccurrences(of: "file://", with: "")
let destination = fileClient.zshEnvDestination
let destinationString = destination.absoluteString
.replacingOccurrences(of: "file://", with: "")
logger.info("Linking zsh configuration to: \(configString)")
logger.info("Linking .zshenv file to: \(destinationString)")
if !dryRun {
try await linkZshConfig()
try await fileClient.createSymlink(
source: fileClient.zshEnvSource,
destination: destination
)
}
logger.info("Done installing zsh configuration files.")
}
func uninstall() async throws {
logger.info("Uninstalling zsh configuration from: \(fileClient.zshConfigDestination.absoluteString)")
if !dryRun {
logger.debug("Moving configuration to the trash.")
try await fileClient.moveToTrash(fileClient.zshConfigDestination)
logger.debug("Moving .zshenv to the trash.")
try await fileClient.moveToTrash(fileClient.zshEnvDestination)
}
logger.info("Done uninstalling zsh configuration, you will need to reload your shell.")
}
func run() async throws {
switch context.context {
case .install:
try await self.install()
case .uninstall:
try await self.uninstall()
}
}
func linkZshConfig() async throws {
try await fileClient.createDirectory(at: fileClient.configDirectory())
try await fileClient.createSymlink(
source: fileClient.zshDirectory,
destination: fileClient.zshConfigDestination
)
}
}
fileprivate extension FileClient {
var zshDirectory: URL {
dotfilesDirectory()
.appendingPathComponent("zsh")
.appendingPathComponent("config")
}
var zshConfigDestination: URL {
configDirectory().appendingPathComponent("zsh")
}
var zshEnvDestination: URL {
homeDirectory().appendingPathComponent(".zshenv")
}
var zshEnvSource: URL {
zshDirectory.appendingPathComponent(".zshenv")
}
}

View File

@@ -0,0 +1,19 @@
import Dependencies
@_exported import CliMiddleware
@_exported import FileClient
@_exported import LoggingDependency
@_exported import ShellClient
import Foundation
#if canImport(FoundationNetworking)
import FoundationNetworking
#endif
extension CliMiddleware: DependencyKey {
public static var liveValue: CliMiddleware {
.init(
brew: { try await Brew(context: $0).run() },
zsh: { try await Zsh(context: $0).run() }
)
}
}