1
0
mirror of https://github.com/nicoverbruggen/phpmon.git synced 2025-08-07 12:00:09 +02:00

👌 Path based on architecture (#134)

This commit is contained in:
2022-02-11 18:58:07 +01:00
parent 6187eb3e4e
commit dc91d0e00c
6 changed files with 61 additions and 29 deletions

View File

@ -231,8 +231,15 @@ Since v3.4 all of the loaded .ini files are sourced to determine which extension
<details>
<summary><strong>I've got two Homebrew installations on my Apple Silicon Mac, can I choose which installation to use with PHP Monitor?</strong></summary>
Not at this time, no. PHP Monitor will prefer the `/opt/homebrew` installation over the classic installation directory.
If you are using PHP Monitor on an Intel machine or on an Apple Silicon machine with Rosetta enabled, PHP Monitor expects the main Homebrew binary in `/usr/local/bin/brew`.
If you are using PHP Monitor on Apple Silicon without Rosetta, PHP Monitor expects the main Homebrew binary in `/opt/homebrew/bin/brew`.
If there's an issue here, you'll get an alert at launch.
Make sure that the version of Homebrew that you are running normally is the same as the one that PHP Monitor expects. If you are on M1 hardware for example, but still using Rosetta for Homebrew, you'll need to run PHP Monitor under Rosetta as well.
PHP Monitor is a universal app and supports both architectures, so [find out here](https://support.apple.com/en-us/HT211861) how to enable Rosetta with PHP Monitor.
</details>
<details>

View File

@ -15,15 +15,15 @@ public class Paths {
public static let shared = Paths()
private var baseDir : Paths.HomebrewDir
internal var baseDir : Paths.HomebrewDir
private var userName : String
init() {
baseDir = FileManager.default.fileExists(atPath: "\(HomebrewDir.opt.rawValue)/bin/brew") ? .opt : .usr
baseDir = App.architecture != "x86_64" ? .opt : .usr
userName = String(Shell.pipe("whoami").split(separator: "\n")[0])
}
// - MARK: Binaries
public static var valet: String {

View File

@ -22,6 +22,20 @@ class App {
return "\(version) (\(build))"
}
static var architecture: String {
var systeminfo = utsname()
uname(&systeminfo)
let machine = withUnsafeBytes(of: &systeminfo.machine) {bufPtr->String in
let data = Data(bufPtr)
if let lastIndex = data.lastIndex(where: {$0 != 0}) {
return String(data: data[0...lastIndex], encoding: .isoLatin1)!
} else {
return String(data: data, encoding: .isoLatin1)!
}
}
return machine
}
/** Whether the app is busy doing something. Used to determine what UI to display. */
// TODO: Remove this, and always use PhpEnv.shared.isBusy
static var busy: Bool {

View File

@ -10,7 +10,7 @@ import AppKit
class Startup {
public var failed : Bool = false
public var failed: Bool = false
public var failureCallback = {}
/**
@ -27,40 +27,34 @@ class Startup {
performEnvironmentCheck(
!Shell.fileExists("\(Paths.binPath)/php"),
messageText: "startup.errors.php_binary.title".localized,
informativeText: "startup.errors.php_binary.desc".localized,
breaking: true
informativeText: "startup.errors.php_binary.desc".localized
)
performEnvironmentCheck(
!Shell.pipe("ls \(Paths.optPath) | grep php").contains("php"),
messageText: "startup.errors.php_opt.title".localized,
informativeText: "startup.errors.php_opt.desc".localized,
breaking: true
informativeText: "startup.errors.php_opt.desc".localized
)
performEnvironmentCheck(
// Check for Valet; it can be symlinked or in .composer/vendor/bin
!(Shell.fileExists("/usr/local/bin/valet")
|| Shell.fileExists("/opt/homebrew/bin/valet")
!(Shell.fileExists("\(Paths.binPath))/valet")
|| Shell.fileExists("~/.composer/vendor/bin/valet")
),
messageText: "startup.errors.valet_executable.title".localized,
informativeText: "startup.errors.valet_executable.desc".localized,
breaking: true
informativeText: "startup.errors.valet_executable.desc".localized
)
performEnvironmentCheck(
HomebrewDiagnostics.cannotLoadService(),
messageText: "startup.errors.services_json_error.title".localized,
informativeText: "startup.errors.services_json_error.desc".localized,
breaking: true
informativeText: "startup.errors.services_json_error.desc".localized
)
performEnvironmentCheck(
!Shell.pipe("cat /private/etc/sudoers.d/brew").contains("\(Paths.binPath)/brew"),
messageText: "startup.errors.sudoers_brew.title".localized,
informativeText: "startup.errors.sudoers_brew.desc".localized,
breaking: true
informativeText: "startup.errors.sudoers_brew.desc".localized
)
performEnvironmentCheck(
@ -69,8 +63,7 @@ class Startup {
|| Shell.pipe("cat /private/etc/sudoers.d/valet").contains("/opt/homebrew/bin/valet")
),
messageText: "startup.errors.sudoers_valet.title".localized,
informativeText: "startup.errors.sudoers_valet.desc".localized,
breaking: true
informativeText: "startup.errors.sudoers_valet.desc".localized
)
// Determine the Valet version only AFTER confirming the correct permission is in place
@ -78,8 +71,7 @@ class Startup {
performEnvironmentCheck(
Valet.shared.version == nil,
messageText: "startup.errors.valet_version_unknown.title".localized,
informativeText: "startup.errors.valet_version_unknown.desc".localized,
breaking: true
informativeText: "startup.errors.valet_version_unknown.desc".localized
)
if (!failed) {
@ -101,32 +93,28 @@ class Startup {
}
/**
Perform an environment check. Will cause the application to terminate, if `breaking` is set to true.
Perform an environment check.
- Parameter condition: Fail condition to check for; if this returns `true`, the alert will be shown
- Parameter messageText: Short description of what is wrong
- Parameter informativeText: Expanded description of the environment check that failed
- Parameter breaking: If the application should terminate afterwards
*/
private func performEnvironmentCheck(
_ condition: Bool,
messageText: String,
informativeText: String,
breaking: Bool
informativeText: String
) {
if (!condition) { return }
failed = breaking
DispatchQueue.main.async { [self] in
// Present the information to the user
Alert.notify(
message: messageText,
info: informativeText,
style: breaking ? .critical : .warning
style: .critical
)
// Only breaking issues will throw the extra retry modal
breaking ? failureCallback() : ()
failureCallback()
}
}

View File

@ -16,6 +16,25 @@ extension MainMenu {
// Start with the icon
setStatusBar(image: NSImage(named: NSImage.Name("StatusBarIcon"))!)
// Do the important system setup checks
Log.info("The user is running PHP Monitor with the architecture: \(App.architecture)")
// Make sure Homebrew is installed
if !FileManager.default.fileExists(atPath: Paths.brew) {
_ = Alert.present(
messageText: "alert.homebrew_missing.title".localized,
informativeText: "alert.homebrew_missing.info".localized(
App.architecture
.replacingOccurrences(of: "x86_64", with: "Intel")
.replacingOccurrences(of: "arm64", with: "Apple Silicon"),
Paths.brew
),
buttonTitle: "alert.homebrew_missing.quit".localized,
style: .critical
)
exit(1)
}
// Perform environment boot checks
DispatchQueue.global(qos: .userInitiated).async { [unowned self] in
Startup().checkEnvironment(success: { onEnvironmentPass() },

View File

@ -183,6 +183,10 @@
// ALERTS
"alert.homebrew_missing.title" = "PHP Monitor cannot start";
"alert.homebrew_missing.info" = "You are running PHP Monitor with the following architecture: %@.\n\nA working Homebrew binary is expected in `%@`, but was not found, so PHP Monitor cannot work.\n\nIf you have not installed Homebrew yet, please do so. (If you are on Apple Silicon, make sure your Homebrew and PHP Monitor use the same architecture, by enabling or disabling Rosetta where needed.)\n\nPHP Monitor will now quit, please restart the app after fixing this issue.";
"alert.homebrew_missing.quit" = "Quit";
// Composer Update
"alert.composer_missing.title" = "Composer not found!";
"alert.composer_missing.info" = "Make sure you have Composer available in `/usr/local/bin/composer`. If Composer is located somewhere else, please create a symlink, like so (make sure to use the correct path):\n\n`ln -s /path/to/composer /usr/local/bin`.";