fix: show a GUI password dialog when brew needs sudo
Brew runs inside a Process with no terminal attached, so any sudo prompt (cask upgrades, some installers) would hang or fail silently — there was nowhere to type the password. Set SUDO_ASKPASS to a small helper script written to Application Support at launch. When sudo detects no tty, it runs the helper, which shows a native macOS password dialog via osascript and prints the answer for sudo to consume. Cancelling the dialog makes sudo fail cleanly instead of hanging. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
parent
7390d68a33
commit
e579ac1d56
|
|
@ -174,6 +174,23 @@ class AppDelegate: NSObject, NSApplicationDelegate {
|
|||
return "brew"
|
||||
}
|
||||
|
||||
/// Written once per launch; sudo runs it to show a GUI password dialog
|
||||
/// whenever brew needs admin rights (no terminal is attached to Process).
|
||||
static let askpassURL: URL = {
|
||||
let dir = FileManager.default.urls(for: .applicationSupportDirectory, in: .userDomainMask)[0]
|
||||
.appendingPathComponent("BrewBar", isDirectory: true)
|
||||
try? FileManager.default.createDirectory(at: dir, withIntermediateDirectories: true)
|
||||
|
||||
let url = dir.appendingPathComponent("askpass.sh")
|
||||
let script = """
|
||||
#!/bin/zsh
|
||||
osascript -e 'display dialog "BrewBar needs your administrator password to continue:" default answer "" with hidden answer with title "BrewBar" with icon caution buttons {"Cancel", "OK"} default button "OK"' -e 'text returned of result'
|
||||
"""
|
||||
try? script.write(to: url, atomically: true, encoding: .utf8)
|
||||
try? FileManager.default.setAttributes([.posixPermissions: 0o700], ofItemAtPath: url.path)
|
||||
return url
|
||||
}()
|
||||
|
||||
func runBrew(_ command: String, completion: @escaping (String) -> Void = { _ in }) {
|
||||
DispatchQueue.global().async {
|
||||
let brew = self.resolveBrewPath()
|
||||
|
|
@ -186,6 +203,10 @@ class AppDelegate: NSObject, NSApplicationDelegate {
|
|||
process.executableURL = URL(fileURLWithPath: "/bin/zsh")
|
||||
process.arguments = ["-c", fullCommand]
|
||||
|
||||
var environment = ProcessInfo.processInfo.environment
|
||||
environment["SUDO_ASKPASS"] = Self.askpassURL.path
|
||||
process.environment = environment
|
||||
|
||||
let pipe = Pipe()
|
||||
process.standardOutput = pipe
|
||||
process.standardError = pipe
|
||||
|
|
|
|||
Loading…
Reference in a new issue