2020-09-22 06:12:50 +00:00
|
|
|
import Foundation
|
|
|
|
import Cocoa
|
2021-01-19 04:08:52 +00:00
|
|
|
import SecretKit
|
2020-09-22 06:12:50 +00:00
|
|
|
|
|
|
|
struct ShellConfigurationController {
|
|
|
|
|
2021-01-19 04:08:52 +00:00
|
|
|
let socketPath = (NSHomeDirectory().replacingOccurrences(of: Bundle.main.hostBundleID, with: Bundle.main.agentBundleID) as NSString).appendingPathComponent("socket.ssh") as String
|
2020-09-22 06:12:50 +00:00
|
|
|
|
|
|
|
var shellInstructions: [ShellConfigInstruction] {
|
|
|
|
[
|
2021-03-06 23:21:33 +00:00
|
|
|
ShellConfigInstruction(shell: "global",
|
|
|
|
shellConfigDirectory: "~/.ssh/",
|
|
|
|
shellConfigFilename: "config",
|
|
|
|
text: "Host *\n\tIdentityAgent \(socketPath)"),
|
2020-09-22 06:12:50 +00:00
|
|
|
ShellConfigInstruction(shell: "zsh",
|
|
|
|
shellConfigDirectory: "~/",
|
|
|
|
shellConfigFilename: ".zshrc",
|
|
|
|
text: "export SSH_AUTH_SOCK=\(socketPath)"),
|
|
|
|
ShellConfigInstruction(shell: "bash",
|
|
|
|
shellConfigDirectory: "~/",
|
|
|
|
shellConfigFilename: ".bashrc",
|
|
|
|
text: "export SSH_AUTH_SOCK=\(socketPath)"),
|
|
|
|
ShellConfigInstruction(shell: "fish",
|
|
|
|
shellConfigDirectory: "~/.config/fish",
|
|
|
|
shellConfigFilename: "config.fish",
|
2020-11-13 03:07:47 +00:00
|
|
|
text: "set -x SSH_AUTH_SOCK \(socketPath)"),
|
2023-01-03 12:01:35 +00:00
|
|
|
ShellConfigInstruction(shell: "git",
|
|
|
|
shellConfigDirectory: "~/",
|
|
|
|
shellConfigFilename: ".gitconfig",
|
|
|
|
text: "[gpg]\n\tformat = ssh\n[commit]\n\tgpgsign = true\n[tag]\n\tgpgsign = true"),
|
2020-09-22 06:12:50 +00:00
|
|
|
]
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2021-12-15 05:03:42 +00:00
|
|
|
@MainActor func addToShell(shellInstructions: ShellConfigInstruction) -> Bool {
|
2020-09-22 06:12:50 +00:00
|
|
|
let openPanel = NSOpenPanel()
|
|
|
|
// This is sync, so no need to strongly retain
|
|
|
|
let delegate = Delegate(name: shellInstructions.shellConfigFilename)
|
|
|
|
openPanel.delegate = delegate
|
|
|
|
openPanel.message = "Select \(shellInstructions.shellConfigFilename) to let Secretive configure your shell automatically."
|
|
|
|
openPanel.prompt = "Add to \(shellInstructions.shellConfigFilename)"
|
|
|
|
openPanel.canChooseFiles = true
|
|
|
|
openPanel.canChooseDirectories = false
|
|
|
|
openPanel.showsHiddenFiles = true
|
|
|
|
openPanel.directoryURL = URL(fileURLWithPath: shellInstructions.shellConfigDirectory)
|
|
|
|
openPanel.nameFieldStringValue = shellInstructions.shellConfigFilename
|
|
|
|
openPanel.allowedContentTypes = [.symbolicLink, .data, .plainText]
|
|
|
|
openPanel.runModal()
|
|
|
|
guard let fileURL = openPanel.urls.first else { return false }
|
|
|
|
let handle: FileHandle
|
|
|
|
do {
|
|
|
|
handle = try FileHandle(forUpdating: fileURL)
|
|
|
|
guard let existing = try handle.readToEnd(),
|
|
|
|
let existingString = String(data: existing, encoding: .utf8) else { return false }
|
|
|
|
guard !existingString.contains(shellInstructions.text) else {
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
try handle.seekToEnd()
|
|
|
|
} catch {
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
handle.write("\n# Secretive Config\n\(shellInstructions.text)\n".data(using: .utf8)!)
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|