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"
|
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 }) {
|
func runBrew(_ command: String, completion: @escaping (String) -> Void = { _ in }) {
|
||||||
DispatchQueue.global().async {
|
DispatchQueue.global().async {
|
||||||
let brew = self.resolveBrewPath()
|
let brew = self.resolveBrewPath()
|
||||||
|
|
@ -186,6 +203,10 @@ class AppDelegate: NSObject, NSApplicationDelegate {
|
||||||
process.executableURL = URL(fileURLWithPath: "/bin/zsh")
|
process.executableURL = URL(fileURLWithPath: "/bin/zsh")
|
||||||
process.arguments = ["-c", fullCommand]
|
process.arguments = ["-c", fullCommand]
|
||||||
|
|
||||||
|
var environment = ProcessInfo.processInfo.environment
|
||||||
|
environment["SUDO_ASKPASS"] = Self.askpassURL.path
|
||||||
|
process.environment = environment
|
||||||
|
|
||||||
let pipe = Pipe()
|
let pipe = Pipe()
|
||||||
process.standardOutput = pipe
|
process.standardOutput = pipe
|
||||||
process.standardError = pipe
|
process.standardError = pipe
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue