From 1a1a53b472fd89ebdbee82ed9f9610b6f16ae293 Mon Sep 17 00:00:00 2001 From: Nico Verbruggen Date: Tue, 15 Mar 2022 22:39:46 +0100 Subject: [PATCH] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20Preliminary=20refactor=20f?= =?UTF-8?q?or=20Valet=203.0=20(#148)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- phpmon/Common/PHP/PhpInstallation.swift | 6 +-- .../PHP/Switcher/InternalSwitcher.swift | 54 +++++++++++++------ .../Valet/NginxConfigParser.swift | 16 +++--- .../Domain/Integrations/Valet/ValetSite.swift | 34 ++++++------ phpmon/Domain/Menu/StatusMenu.swift | 2 +- phpmon/Domain/SiteList/SiteListCell.swift | 8 ++- 6 files changed, 77 insertions(+), 43 deletions(-) diff --git a/phpmon/Common/PHP/PhpInstallation.swift b/phpmon/Common/PHP/PhpInstallation.swift index ba2682e..0ed9ae1 100644 --- a/phpmon/Common/PHP/PhpInstallation.swift +++ b/phpmon/Common/PHP/PhpInstallation.swift @@ -10,7 +10,7 @@ import Foundation class PhpInstallation { - var longVersion: PhpVersionNumber + var versionNumber: PhpVersionNumber /** In order to determine details about a PHP installation, we’ll simply run `php-config --version` @@ -19,7 +19,7 @@ class PhpInstallation { init(_ version: String) { let phpConfigExecutablePath = "\(Paths.optPath)/php@\(version)/bin/php-config" - self.longVersion = PhpVersionNumber.make(from: version)! + self.versionNumber = PhpVersionNumber.make(from: version)! if Filesystem.fileExists(phpConfigExecutablePath) { let longVersionString = Command.execute( @@ -29,7 +29,7 @@ class PhpInstallation { // The parser should always work, or the string has to be very unusual. // If so, the app SHOULD crash, so that the users report what's up. - self.longVersion = try! PhpVersionNumber.parse(longVersionString) + self.versionNumber = try! PhpVersionNumber.parse(longVersionString) } } diff --git a/phpmon/Common/PHP/Switcher/InternalSwitcher.swift b/phpmon/Common/PHP/Switcher/InternalSwitcher.swift index 14f8096..3ed7f46 100644 --- a/phpmon/Common/PHP/Switcher/InternalSwitcher.swift +++ b/phpmon/Common/PHP/Switcher/InternalSwitcher.swift @@ -24,22 +24,23 @@ class InternalSwitcher: PhpSwitcher { { Log.info("Switching to \(version), unlinking all versions...") + let isolated = Valet.shared.sites.filter { site in + site.isolatedPhpVersion != nil + }.map { site in + return site.isolatedPhpVersion!.versionNumber.homebrewVersion + } + + var versions: Set = [] + versions = versions.union(isolated) + versions = versions.union([version]) + let group = DispatchGroup() PhpEnv.shared.availablePhpVersions.forEach { (available) in group.enter() DispatchQueue.global(qos: .userInitiated).async { - let formula = (available == PhpEnv.brewPhpVersion) - ? "php" : "php@\(available)" - - brew("unlink \(formula)") - - // TODO: (ISOLATION) Only stop formulae that are not used for isolation - brew("services stop \(formula)", sudo: true) - - Log.perf("Unlinked and stopped services for \(formula)") - + self.stopPhpVersion(available) group.leave() } } @@ -48,16 +49,39 @@ class InternalSwitcher: PhpSwitcher { Log.info("All versions have been unlinked!") Log.info("Linking the new version!") - let formula = (version == PhpEnv.brewPhpVersion) ? "php" : "php@\(version)" - brew("link \(formula) --overwrite --force") - brew("services start \(formula)", sudo: true) - + for formula in versions { + self.startPhpVersion(formula, primary: (version == formula)) + } + Log.info("Restarting nginx, just to be sure!") brew("services restart nginx", sudo: true) - Log.info("The new version has been linked!") + Log.info("The new version(s) has been linked!") completion() } } + private func stopPhpVersion(_ version: String) { + let formula = (version == PhpEnv.brewPhpVersion) ? "php" : "php@\(version)" + brew("unlink \(formula)") + brew("services stop \(formula)", sudo: true) + Log.perf("Unlinked and stopped services for \(formula)") + } + + private func startPhpVersion(_ version: String, primary: Bool) { + let formula = (version == PhpEnv.brewPhpVersion) ? "php" : "php@\(version)" + + if (primary) { + Log.perf("PHP \(formula) is the primary formula, linking and starting services...") + brew("link \(formula) --overwrite --force") + } else { + Log.perf("PHP \(formula) is an isolated PHP version, starting services only...") + } + + brew("services start \(formula)", sudo: true) + let socketVersion = version.replacingOccurrences(of: ".", with: "") + Shell.run("ln -sF ~/.config/valet/valet\(socketVersion).sock ~/.config/valet/valet.sock") + Log.perf("Symlinked new socket version.") + } + } diff --git a/phpmon/Domain/Integrations/Valet/NginxConfigParser.swift b/phpmon/Domain/Integrations/Valet/NginxConfigParser.swift index db17bfe..c3316e5 100644 --- a/phpmon/Domain/Integrations/Valet/NginxConfigParser.swift +++ b/phpmon/Domain/Integrations/Valet/NginxConfigParser.swift @@ -13,12 +13,15 @@ class NginxConfigParser { var contents: String! init(filePath: String) { - self.contents = try! String(contentsOfFile: filePath) + self.contents = try! String(contentsOfFile: filePath + .replacingOccurrences(of: "~", with: "/Users/\(Paths.whoami)") + ) } lazy var isolatedVersion: String? = { let regex = try! NSRegularExpression( - pattern: #"(ISOLATED_PHP_VERSION=(php@)?)((?\d)(.)?(?\d))"#, + // PHP versions have (so far) never needed multiple digits for version numbers + pattern: #"(ISOLATED_PHP_VERSION=(php)?(@)?)((?\d)(.)?(?\d))"#, options: [] ) @@ -27,12 +30,9 @@ class NginxConfigParser { if match == nil { return nil } - - let majorRange = Range(match!.range(withName: "major"), in: contents)! - let minorRange = Range(match!.range(withName: "minor"), in: contents)! - - let major: String = contents[majorRange] - let minor: String = contents[minorRange] + + let major: String = contents[Range(match!.range(withName: "major"), in: contents)!] + let minor: String = contents[Range(match!.range(withName: "minor"), in: contents)!] return "\(major).\(minor)" }() diff --git a/phpmon/Domain/Integrations/Valet/ValetSite.swift b/phpmon/Domain/Integrations/Valet/ValetSite.swift index ba8adc6..5134454 100644 --- a/phpmon/Domain/Integrations/Valet/ValetSite.swift +++ b/phpmon/Domain/Integrations/Valet/ValetSite.swift @@ -60,27 +60,27 @@ class ValetSite { case valetphprc = "valetphprc" } - init(absolutePath: String, tld: String) { - self.absolutePath = absolutePath + init(name: String, tld: String, absolutePath: String, aliasPath: String? = nil) { + self.name = name self.tld = tld - self.name = URL(fileURLWithPath: absolutePath).lastPathComponent - self.aliasPath = nil - - determineSecured() - determineComposerPhpVersion() - determineDriver() - } - - convenience init(aliasPath: String, tld: String) { - let absolutePath = try! FileManager.default.destinationOfSymbolicLink(atPath: aliasPath) - - self.init(absolutePath: absolutePath, tld: tld) - self.name = URL(fileURLWithPath: aliasPath).lastPathComponent + self.absolutePath = absolutePath self.aliasPath = aliasPath determineSecured() determineComposerPhpVersion() determineDriver() + determineIsolated() + } + + convenience init(absolutePath: String, tld: String) { + let name = URL(fileURLWithPath: absolutePath).lastPathComponent + self.init(name: name, tld: tld, absolutePath: absolutePath) + } + + convenience init(aliasPath: String, tld: String) { + let name = URL(fileURLWithPath: aliasPath).lastPathComponent + let absolutePath = try! FileManager.default.destinationOfSymbolicLink(atPath: aliasPath) + self.init(name: name, tld: tld, absolutePath: absolutePath, aliasPath: aliasPath) } /** @@ -88,6 +88,10 @@ class ValetSite { */ public func determineIsolated() { if let version = ValetSite.isolatedVersion("~/.config/valet/Nginx/\(self.name).\(self.tld)") { + if (!PhpEnv.shared.cachedPhpInstallations.keys.contains(version)) { + Log.err("The PHP version \(version) is isolated for the site \(self.name) but that PHP version is unavailable.") + return + } self.isolatedPhpVersion = PhpEnv.shared.cachedPhpInstallations[version] } } diff --git a/phpmon/Domain/Menu/StatusMenu.swift b/phpmon/Domain/Menu/StatusMenu.swift index 639e2ae..a204c66 100644 --- a/phpmon/Domain/Menu/StatusMenu.swift +++ b/phpmon/Domain/Menu/StatusMenu.swift @@ -139,7 +139,7 @@ class StatusMenu : NSMenu { // Get the short and long version let shortVersion = PhpEnv.shared.availablePhpVersions[index] - let longVersion = PhpEnv.shared.cachedPhpInstallations[shortVersion]!.longVersion + let longVersion = PhpEnv.shared.cachedPhpInstallations[shortVersion]!.versionNumber let long = Preferences.preferences[.fullPhpVersionDynamicIcon] as! Bool let versionString = long ? longVersion.toString() : shortVersion diff --git a/phpmon/Domain/SiteList/SiteListCell.swift b/phpmon/Domain/SiteList/SiteListCell.swift index 4840fa5..05ef040 100644 --- a/phpmon/Domain/SiteList/SiteListCell.swift +++ b/phpmon/Domain/SiteList/SiteListCell.swift @@ -33,7 +33,13 @@ class SiteListCell: NSTableCellView self.site = site // Make sure to show the TLD - labelSiteName.stringValue = "\(site.name).\(Valet.shared.config.tld)" + var siteName = "\(site.name).\(Valet.shared.config.tld)" + + if (site.isolatedPhpVersion != nil) { + siteName += " [isolated \(site.isolatedPhpVersion!.versionNumber.homebrewVersion)]" + } + + labelSiteName.stringValue = siteName // Show the absolute path, except make sure to replace the /Users/username segment with ~ for readability labelPathName.stringValue = site.absolutePathRelative