mirror of
https://github.com/nicoverbruggen/phpmon.git
synced 2025-08-07 20:10:08 +02:00
🏗 WIP: Remove command
This commit is contained in:
@ -781,10 +781,6 @@
|
||||
C4F780CC25D80B75000DBC97 /* ActivePhpInstallation.swift in Sources */ = {isa = PBXBuildFile; fileRef = C41C1B4A22B019FF00E7CF16 /* ActivePhpInstallation.swift */; };
|
||||
C4F780CD25D80B75000DBC97 /* Alert.swift in Sources */ = {isa = PBXBuildFile; fileRef = C476FF9722B0DD830098105B /* Alert.swift */; };
|
||||
C4F780CE25D80B75000DBC97 /* LocalNotification.swift in Sources */ = {isa = PBXBuildFile; fileRef = C474B00524C0E98C00066A22 /* LocalNotification.swift */; };
|
||||
C4F8764E29BFAF00006BBE26 /* PhpVersionInstaller.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4F8764D29BFAF00006BBE26 /* PhpVersionInstaller.swift */; };
|
||||
C4F8764F29BFAF00006BBE26 /* PhpVersionInstaller.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4F8764D29BFAF00006BBE26 /* PhpVersionInstaller.swift */; };
|
||||
C4F8765029BFAF00006BBE26 /* PhpVersionInstaller.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4F8764D29BFAF00006BBE26 /* PhpVersionInstaller.swift */; };
|
||||
C4F8765129BFAF00006BBE26 /* PhpVersionInstaller.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4F8764D29BFAF00006BBE26 /* PhpVersionInstaller.swift */; };
|
||||
C4F8C0A422D4F12C002EFE61 /* DateExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4F8C0A322D4F12C002EFE61 /* DateExtension.swift */; };
|
||||
C4FACE80288F1C0D00FC478F /* PreferencesWindowController+Hotkey.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4FACE7F288F1C0D00FC478F /* PreferencesWindowController+Hotkey.swift */; };
|
||||
C4FACE81288F1C0D00FC478F /* PreferencesWindowController+Hotkey.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4FACE7F288F1C0D00FC478F /* PreferencesWindowController+Hotkey.swift */; };
|
||||
@ -1068,7 +1064,6 @@
|
||||
C4F7809B25D80344000DBC97 /* CommandTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CommandTest.swift; sourceTree = "<group>"; };
|
||||
C4F780A725D80AE8000DBC97 /* php.ini */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = php.ini; sourceTree = "<group>"; };
|
||||
C4F780AD25D80B37000DBC97 /* PhpExtensionTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PhpExtensionTest.swift; sourceTree = "<group>"; };
|
||||
C4F8764D29BFAF00006BBE26 /* PhpVersionInstaller.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PhpVersionInstaller.swift; sourceTree = "<group>"; };
|
||||
C4F8C0A322D4F12C002EFE61 /* DateExtension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DateExtension.swift; sourceTree = "<group>"; };
|
||||
C4F8C0A522D4FA41002EFE61 /* README.md */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = net.daringfireball.markdown; path = README.md; sourceTree = "<group>"; };
|
||||
C4FACE7F288F1C0D00FC478F /* PreferencesWindowController+Hotkey.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "PreferencesWindowController+Hotkey.swift"; sourceTree = "<group>"; };
|
||||
@ -1145,7 +1140,6 @@
|
||||
54B20EDF263AA22C00D3250E /* PHP */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
C4F8764D29BFAF00006BBE26 /* PhpVersionInstaller.swift */,
|
||||
C48D6C6E279CD29C00F26D7E /* PHP Version */,
|
||||
C4D9ADC2277610E4007277F4 /* Switcher */,
|
||||
C4F30B01278E169B00755FCE /* Homebrew */,
|
||||
@ -2286,7 +2280,6 @@
|
||||
C4205A7E27F4D21800191A39 /* ValetProxy.swift in Sources */,
|
||||
C4C8E818276F54D8003AC782 /* App+ConfigWatch.swift in Sources */,
|
||||
C4E49DE728F764050026AC4E /* ActiveCommand.swift in Sources */,
|
||||
C4F8764E29BFAF00006BBE26 /* PhpVersionInstaller.swift in Sources */,
|
||||
54FCFD30276C8DA4004CE748 /* HotkeyPreferenceView.swift in Sources */,
|
||||
C450C8C628C919EC002A2B4B /* PreferenceName.swift in Sources */,
|
||||
C4E4404627C56F4700D225E1 /* ValetSite.swift in Sources */,
|
||||
@ -2580,7 +2573,6 @@
|
||||
C471E80828F9BAD40021E251 /* PhpExtension.swift in Sources */,
|
||||
C471E7F928F9BACB0021E251 /* PhpSwitcher.swift in Sources */,
|
||||
C471E82A28F9BB330021E251 /* ValetListable.swift in Sources */,
|
||||
C4F8765029BFAF00006BBE26 /* PhpVersionInstaller.swift in Sources */,
|
||||
C471E82728F9BB310021E251 /* BrewDiagnostics.swift in Sources */,
|
||||
C471E81C28F9BB250021E251 /* BetterAlert.swift in Sources */,
|
||||
C471E7DB28F9BA8F0021E251 /* RealShell.swift in Sources */,
|
||||
@ -2778,7 +2770,6 @@
|
||||
C471E80028F9BAD10021E251 /* Xdebug.swift in Sources */,
|
||||
C471E7F528F9BAC80021E251 /* PhpEnv.swift in Sources */,
|
||||
C471E7ED28F9BAC30021E251 /* Process.swift in Sources */,
|
||||
C4F8765129BFAF00006BBE26 /* PhpVersionInstaller.swift in Sources */,
|
||||
C471E81128F9BAE80021E251 /* NSMenuItemExtension.swift in Sources */,
|
||||
C471E7CC28F9BA5B0021E251 /* TestableShell.swift in Sources */,
|
||||
C471E80C28F9BAE80021E251 /* NSWindowExtension.swift in Sources */,
|
||||
@ -2820,7 +2811,6 @@
|
||||
C485707128BF452E00539B36 /* WarningManager.swift in Sources */,
|
||||
C41CA5EE2774F8EE00A2C80E /* DomainListVC+Actions.swift in Sources */,
|
||||
C4FACE81288F1C0D00FC478F /* PreferencesWindowController+Hotkey.swift in Sources */,
|
||||
C4F8764F29BFAF00006BBE26 /* PhpVersionInstaller.swift in Sources */,
|
||||
C40934A3298EEB2C00D25014 /* CaskFile.swift in Sources */,
|
||||
54D9E0B727E4F51E003B9AD9 /* HotKey.swift in Sources */,
|
||||
C413E43528DA3EB100AE33C7 /* TestableShellTest.swift in Sources */,
|
||||
|
@ -1,271 +0,0 @@
|
||||
//
|
||||
// PhpVersionInstaller.swift
|
||||
// PHP Monitor
|
||||
//
|
||||
// Created by Nico Verbruggen on 13/03/2023.
|
||||
// Copyright © 2023 Nico Verbruggen. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import Cocoa
|
||||
|
||||
public enum PhpInstallAction {
|
||||
case install
|
||||
case remove
|
||||
case upgrade
|
||||
case purge
|
||||
}
|
||||
|
||||
public class PhpVersionInstaller {
|
||||
// TODO: Remove
|
||||
public static var installables = [
|
||||
// "8.2": "php",
|
||||
"8.1": "php@8.1",
|
||||
"8.0": "php@8.0",
|
||||
"7.4": "shivammathur/php/php@7.4",
|
||||
"7.3": "shivammathur/php/php@7.3",
|
||||
"7.2": "shivammathur/php/php@7.2",
|
||||
"7.1": "shivammathur/php/php@7.1",
|
||||
"7.0": "shivammathur/php/php@7.0"
|
||||
]
|
||||
|
||||
// swiftlint:disable cyclomatic_complexity function_body_length
|
||||
/**
|
||||
Performs the desired action on the provided PHP version.
|
||||
*/
|
||||
public static func modifyPhpVersion(version: String, action: PhpInstallAction) async {
|
||||
let title = {
|
||||
switch action {
|
||||
case .install:
|
||||
return "Installing PHP \(version)"
|
||||
case .upgrade:
|
||||
return "Upgrading to PHP \(version)"
|
||||
case .remove:
|
||||
return "Removing PHP \(version)"
|
||||
case .purge:
|
||||
return "Purging PHP \(version)"
|
||||
}
|
||||
}()
|
||||
|
||||
let description = {
|
||||
switch action {
|
||||
case .install:
|
||||
return "Please wait while Homebrew installs PHP \(version)..."
|
||||
case .upgrade:
|
||||
return "Please wait while Homebrew upgrades PHP \(version)..."
|
||||
case .remove:
|
||||
return "Please wait while Homebrew uninstalls PHP \(version)..."
|
||||
case .purge:
|
||||
return "Please wait while Homebrew purges PHP \(version)"
|
||||
}
|
||||
}()
|
||||
|
||||
let subject = ProgressViewSubject(
|
||||
title: title,
|
||||
description: description
|
||||
)
|
||||
|
||||
let installables = Self.installables
|
||||
|
||||
if installables.keys.contains(version) {
|
||||
let windowController = await ProgressWindowView.display(subject)
|
||||
await NSApp.activate(ignoringOtherApps: true)
|
||||
await windowController.window?.makeKeyAndOrderFront(nil)
|
||||
|
||||
let formula = installables[version]!
|
||||
|
||||
var command: String!
|
||||
|
||||
if action == .install {
|
||||
if formula.contains("shivammathur") && !BrewDiagnostics.installedTaps.contains("shivammathur/php") {
|
||||
await Shell.quiet("brew tap shivammathur/php")
|
||||
}
|
||||
|
||||
command = """
|
||||
export HOMEBREW_NO_INSTALL_UPGRADE=1 \
|
||||
&& export HOMEBREW_NO_INSTALL_CLEANUP=1 \
|
||||
&& brew install \(formula) --force
|
||||
"""
|
||||
}
|
||||
|
||||
if action == .upgrade {
|
||||
fatalError("This is not supported yet.")
|
||||
}
|
||||
|
||||
if action == .purge || action == .remove {
|
||||
// Removal always requires permission
|
||||
do {
|
||||
try await PhpVersionInstaller.fixPermissions(for: formula)
|
||||
} catch {
|
||||
Task { @MainActor in
|
||||
subject.progress = 1
|
||||
subject.title = "Could not take permission of required folder"
|
||||
subject.description = "Please try again!"
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// Actually do the removal
|
||||
command = "brew remove \(formula) --force --ignore-dependencies"
|
||||
|
||||
// Check if the permissions are correct; if not, fix permissions
|
||||
if action == .purge {
|
||||
command += " --zap"
|
||||
}
|
||||
}
|
||||
|
||||
let (process, _) = try! await Shell.attach(
|
||||
command,
|
||||
didReceiveOutput: { text, _ in
|
||||
if action == .install {
|
||||
if !text.isEmpty {
|
||||
Log.perf(text)
|
||||
}
|
||||
|
||||
// Check if we can recognize any of the typical progress steps
|
||||
if let (number, text) = Self.reportInstallationProgress(text) {
|
||||
Task { @MainActor in
|
||||
subject.progress = number
|
||||
subject.description = text
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
withTimeout: .minutes(5)
|
||||
)
|
||||
|
||||
if process.terminationStatus <= 0 {
|
||||
Task { @MainActor in
|
||||
subject.progress = 1
|
||||
}
|
||||
|
||||
await PhpEnv.detectPhpVersions()
|
||||
await MainMenu.shared.refreshActiveInstallation()
|
||||
|
||||
Task { @MainActor in
|
||||
windowController.close()
|
||||
}
|
||||
} else {
|
||||
// Do not close the window and notify about failure
|
||||
Task { @MainActor in
|
||||
subject.title = "Operation failed: something went wrong"
|
||||
subject.progress = 1
|
||||
subject.description = "Oops. You may close this window."
|
||||
}
|
||||
}
|
||||
} else {
|
||||
Log.err("\(version) is not contained within installable list")
|
||||
}
|
||||
}
|
||||
|
||||
/** Installs a given PHP version. Never requires administrative privileges. */
|
||||
public static func installPhpVersion(version: String) async {
|
||||
await self.modifyPhpVersion(version: version, action: .install)
|
||||
}
|
||||
|
||||
/** Uninstalls a given PHP version. Might require administrative privileges. */
|
||||
public static func removePhpVersion(version: String) async {
|
||||
await self.modifyPhpVersion(version: version, action: .remove)
|
||||
}
|
||||
|
||||
/**
|
||||
Takes ownership of the /BREW_PATH/Cellar/php/x.y.z/bin folder (if required).
|
||||
|
||||
This might not be required if the user has only used that version of PHP
|
||||
with site isolation, so this method checks if it's required first.
|
||||
*/
|
||||
public static func fixPermissions(for formula: String) async throws {
|
||||
// Omit the prefix
|
||||
let path = formula.replacingOccurrences(of: "shivammathur/php/", with: "")
|
||||
|
||||
// Binary path needs to be checked for ownership
|
||||
let binaryPath = "\(Paths.optPath)/\(path)/bin"
|
||||
|
||||
// Check if it's even necessary to perform the fix
|
||||
if !isOwnedByRoot(path: binaryPath) {
|
||||
return
|
||||
}
|
||||
|
||||
Log.info("The ownership of the folder at `\(binaryPath)` is currently not correct. Will prompt to take ownership!")
|
||||
|
||||
let script = """
|
||||
\(Paths.brew) services stop \(formula) \
|
||||
&& chown -R \(Paths.whoami):admin \(Paths.cellarPath)/\(path)
|
||||
"""
|
||||
|
||||
let appleScript = NSAppleScript(source:
|
||||
"do shell script \"\(script)\" with administrator privileges"
|
||||
)
|
||||
|
||||
let eventResult: NSAppleEventDescriptor? = appleScript?.executeAndReturnError(nil)
|
||||
|
||||
if eventResult == nil {
|
||||
throw HomebrewPermissionError(kind: .applescriptNilError)
|
||||
}
|
||||
|
||||
Log.info("Ownership was taken of the folder at `\(binaryPath)`.")
|
||||
}
|
||||
|
||||
/**
|
||||
Checks if a given path is owned by root. If so, ownership might need to be taken.
|
||||
*/
|
||||
private static func isOwnedByRoot(path: String) -> Bool {
|
||||
do {
|
||||
let attributes = try FileManager.default.attributesOfItem(atPath: path)
|
||||
if let owner = attributes[.ownerAccountName] as? String {
|
||||
return owner == "root"
|
||||
}
|
||||
} catch {
|
||||
return true
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
private static func reportInstallationProgress(_ text: String) -> (Double, String)? {
|
||||
if text.contains("Fetching") {
|
||||
return (0.1, "Fetching...")
|
||||
}
|
||||
if text.contains("Downloading") {
|
||||
return (0.25, "Downloading...")
|
||||
}
|
||||
if text.contains("Already downloaded") || text.contains("Downloaded") {
|
||||
return (0.50, "Downloaded!")
|
||||
}
|
||||
if text.contains("Installing") {
|
||||
return (0.60, "Installing...")
|
||||
}
|
||||
if text.contains("Pouring") {
|
||||
return (0.80, "Pouring... this can take a while!")
|
||||
}
|
||||
if text.contains("Summary") {
|
||||
return (1, "The installation is done!")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
/**
|
||||
Determine which action will be available in the PHP version manager.
|
||||
Some versions will be available to be removed, some to be installed.
|
||||
*/
|
||||
public static var availableActions: [(version: String, action: PhpInstallAction)] {
|
||||
var operations: [(version: String, action: PhpInstallAction)] = []
|
||||
|
||||
let installed = PhpEnv.shared.cachedPhpInstallations.keys
|
||||
let unsupported = PhpEnv.shared.incompatiblePhpVersions
|
||||
|
||||
for installable in installables.keys {
|
||||
// While technically possible to uninstall the main formula (`php`)
|
||||
// this should be disabled in the UI... this data should be correct though
|
||||
let availableOperation: PhpInstallAction =
|
||||
installed.contains(installable) || unsupported.contains(installable) ? .remove : .install
|
||||
|
||||
operations.append((version: installable, action: availableOperation))
|
||||
}
|
||||
|
||||
operations.sort { $1.version < $0.version }
|
||||
|
||||
return operations
|
||||
}
|
||||
|
||||
}
|
@ -8,6 +8,14 @@
|
||||
|
||||
import Foundation
|
||||
|
||||
protocol BrewCommand {
|
||||
func execute(onProgress: @escaping (BrewCommandProgress) -> Void) async throws
|
||||
}
|
||||
|
||||
extension BrewCommand {
|
||||
|
||||
}
|
||||
|
||||
struct BrewCommandProgress {
|
||||
let value: Double
|
||||
let title: String
|
||||
@ -18,14 +26,6 @@ struct BrewCommandProgress {
|
||||
}
|
||||
}
|
||||
|
||||
protocol BrewCommand {
|
||||
func execute(onProgress: @escaping (BrewCommandProgress) -> Void) async throws
|
||||
}
|
||||
|
||||
extension BrewCommand {
|
||||
|
||||
}
|
||||
|
||||
struct BrewCommandError: Error {
|
||||
let error: String
|
||||
}
|
||||
|
@ -35,7 +35,7 @@ class InstallPhpVersionCommand: BrewCommand {
|
||||
let command = """
|
||||
export HOMEBREW_NO_INSTALL_UPGRADE=true; \
|
||||
export HOMEBREW_NO_INSTALL_CLEANUP=true; \
|
||||
brew install \(formula) --force
|
||||
\(Paths.brew) install \(formula) --force
|
||||
"""
|
||||
|
||||
let (process, _) = try! await Shell.attach(
|
||||
@ -45,7 +45,6 @@ class InstallPhpVersionCommand: BrewCommand {
|
||||
Log.perf(text)
|
||||
}
|
||||
|
||||
// Check if we can recognize any of the typical progress steps
|
||||
if let (number, text) = self.reportInstallationProgress(text) {
|
||||
onProgress(.create(value: number, title: progressTitle, description: text))
|
||||
}
|
||||
@ -65,10 +64,10 @@ class InstallPhpVersionCommand: BrewCommand {
|
||||
|
||||
private func reportInstallationProgress(_ text: String) -> (Double, String)? {
|
||||
if text.contains("Fetching") {
|
||||
return (0.1, text)
|
||||
return (0.1, "Fetching...")
|
||||
}
|
||||
if text.contains("Downloading") {
|
||||
return (0.25, text)
|
||||
return (0.25, "Downloading package data...")
|
||||
}
|
||||
if text.contains("Already downloaded") || text.contains("Downloaded") {
|
||||
return (0.50, "Downloaded!")
|
||||
|
@ -8,6 +8,109 @@
|
||||
|
||||
import Foundation
|
||||
|
||||
class RemovePhpVersionCommand: Brew {
|
||||
// TODO
|
||||
class RemovePhpVersionCommand: BrewCommand {
|
||||
let formula: String
|
||||
let version: String
|
||||
|
||||
init(formula: String) {
|
||||
self.version = formula
|
||||
.replacingOccurrences(of: "php@", with: "")
|
||||
.replacingOccurrences(of: "shivammathur/php/", with: "")
|
||||
self.formula = formula
|
||||
}
|
||||
|
||||
func execute(onProgress: @escaping (BrewCommandProgress) -> Void) async throws {
|
||||
let progressTitle = "Removing PHP \(version)..."
|
||||
|
||||
onProgress(.create(
|
||||
value: 0.2,
|
||||
title: progressTitle,
|
||||
description: "Please wait while Homebrew removes PHP \(version)..."
|
||||
))
|
||||
|
||||
let command = """
|
||||
export HOMEBREW_NO_INSTALL_UPGRADE=true; \
|
||||
export HOMEBREW_NO_INSTALL_CLEANUP=true; \
|
||||
\(Paths.brew) remove \(formula) --force --ignore-dependencies
|
||||
"""
|
||||
|
||||
do {
|
||||
try await self.fixPermissions(for: formula)
|
||||
} catch {
|
||||
return
|
||||
}
|
||||
|
||||
let (process, _) = try! await Shell.attach(
|
||||
command,
|
||||
didReceiveOutput: { text, _ in
|
||||
if !text.isEmpty {
|
||||
Log.perf(text)
|
||||
}
|
||||
},
|
||||
withTimeout: .minutes(5)
|
||||
)
|
||||
|
||||
if process.terminationStatus <= 0 {
|
||||
onProgress(.create(value: 0.95, title: progressTitle, description: "Reloading PHP versions..."))
|
||||
await PhpEnv.detectPhpVersions()
|
||||
await MainMenu.shared.refreshActiveInstallation()
|
||||
onProgress(.create(value: 1, title: progressTitle, description: "The operation has succeeded."))
|
||||
} else {
|
||||
throw BrewCommandError(error: "The command failed to run correctly.")
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Takes ownership of the /BREW_PATH/Cellar/php/x.y.z/bin folder (if required).
|
||||
|
||||
This might not be required if the user has only used that version of PHP
|
||||
with site isolation, so this method checks if it's required first.
|
||||
*/
|
||||
private func fixPermissions(for formula: String) async throws {
|
||||
// Omit the prefix
|
||||
let path = formula.replacingOccurrences(of: "shivammathur/php/", with: "")
|
||||
|
||||
// Binary path needs to be checked for ownership
|
||||
let binaryPath = "\(Paths.optPath)/\(path)/bin"
|
||||
|
||||
// Check if it's even necessary to perform the fix
|
||||
if !isOwnedByRoot(path: binaryPath) {
|
||||
return
|
||||
}
|
||||
|
||||
Log.info("Need to take ownership of `\(binaryPath)`...")
|
||||
|
||||
let script = """
|
||||
\(Paths.brew) services stop \(formula) \
|
||||
&& chown -R \(Paths.whoami):admin \(Paths.cellarPath)/\(path)
|
||||
"""
|
||||
|
||||
let appleScript = NSAppleScript(
|
||||
source: "do shell script \"\(script)\" with administrator privileges"
|
||||
)
|
||||
|
||||
let eventResult: NSAppleEventDescriptor? = appleScript?.executeAndReturnError(nil)
|
||||
|
||||
if eventResult == nil {
|
||||
throw HomebrewPermissionError(kind: .applescriptNilError)
|
||||
}
|
||||
|
||||
Log.info("Ownership was taken of the folder at `\(binaryPath)`.")
|
||||
}
|
||||
|
||||
/**
|
||||
Checks if a given path is owned by root. If so, ownership might need to be taken.
|
||||
*/
|
||||
private func isOwnedByRoot(path: String) -> Bool {
|
||||
do {
|
||||
let attributes = try FileManager.default.attributesOfItem(atPath: path)
|
||||
if let owner = attributes[.ownerAccountName] as? String {
|
||||
return owner == "root"
|
||||
}
|
||||
} catch {
|
||||
return true
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
@ -206,14 +206,6 @@ class MainMenu: NSObject, NSWindowDelegate, NSMenuDelegate, PhpSwitcherDelegate
|
||||
Task { await AppUpdater().checkForUpdates(userInitiated: true) }
|
||||
}
|
||||
|
||||
@objc func installPhpVersion(sender: PhpMenuItem) {
|
||||
Task { await PhpVersionInstaller.installPhpVersion(version: sender.version) }
|
||||
}
|
||||
|
||||
@objc func removePhpVersion(sender: PhpMenuItem) {
|
||||
Task { await PhpVersionInstaller.removePhpVersion(version: sender.version) }
|
||||
}
|
||||
|
||||
// MARK: - Menu Delegate
|
||||
|
||||
func menuWillOpen(_ menu: NSMenu) {
|
||||
|
@ -61,6 +61,7 @@ struct PhpFormulaeView: View {
|
||||
.frame(maxWidth: .infinity, alignment: .leading)
|
||||
Text("phpman.disclaimer".localizedForSwiftUI)
|
||||
.font(.system(size: 12))
|
||||
.foregroundColor(.gray)
|
||||
.frame(maxWidth: .infinity, alignment: .leading)
|
||||
}
|
||||
}
|
||||
@ -122,17 +123,16 @@ struct PhpFormulaeView: View {
|
||||
.frame(maxWidth: .infinity, alignment: .leading)
|
||||
if formula.isInstalled {
|
||||
Button("Uninstall") {
|
||||
// handle uninstall action here
|
||||
Task { await self.uninstall(formula) }
|
||||
}
|
||||
} else {
|
||||
Button("Install") {
|
||||
// handle install action here
|
||||
Task { await self.install(formula) }
|
||||
}
|
||||
}
|
||||
if formula.hasUpgrade {
|
||||
Button("Update") {
|
||||
// handle uninstall action here
|
||||
Task { await self.install(formula) }
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -160,6 +160,21 @@ struct PhpFormulaeView: View {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public func uninstall(_ formula: BrewFormula) async {
|
||||
let command = RemovePhpVersionCommand(formula: formula.name)
|
||||
try! await command.execute { progress in
|
||||
Task { @MainActor in
|
||||
self.status.title = progress.title
|
||||
self.status.description = progress.description
|
||||
self.status.busy = progress.value != 1
|
||||
|
||||
if progress.value == 1 {
|
||||
await self.handler.refreshPhpVersions(loadOutdated: false)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct PhpFormulaeView_Previews: PreviewProvider {
|
||||
|
@ -92,7 +92,7 @@
|
||||
|
||||
"phpman.title" = "PHP Manager";
|
||||
"phpman.description" = "**PHP Manager** lets you install different PHP versions via Homebrew.";
|
||||
"phpman.disclaimer" = "PHP Manager may ask for administrative privileges to take ownership of certain folders during certain operations. If you prefer it, you can also manually install PHP versions via the terminal.";
|
||||
"phpman.disclaimer" = "Please note that installing or upgrading PHP versions may cause other Homebrew packages to be upgraded as well, but only if Homebrew would otherwise have broken those other packages via a shared dependency. (More in the FAQ!)";
|
||||
"phpman.refresh.button" = "Search for Updates";
|
||||
"phpman.refresh.button.description" = "You can press this button to check (again) if any updates are available to installed PHP versions. When you first open this window, PHP Monitor already does this check.";
|
||||
|
||||
|
Reference in New Issue
Block a user