mirror of
https://github.com/nicoverbruggen/phpmon.git
synced 2025-08-08 04:20:07 +02:00
129 lines
4.7 KiB
Swift
129 lines
4.7 KiB
Swift
//
|
|
// InternalSwitcher.swift
|
|
// PHP Monitor
|
|
//
|
|
// Created by Nico Verbruggen on 24/12/2021.
|
|
// Copyright © 2022 Nico Verbruggen. All rights reserved.
|
|
//
|
|
|
|
import Foundation
|
|
|
|
class InternalSwitcher: PhpSwitcher {
|
|
|
|
/**
|
|
Switching to a new PHP version involves:
|
|
- unlinking the current version
|
|
- stopping the active services
|
|
- linking the new desired version
|
|
|
|
Please note that depending on which version is installed,
|
|
the version that is switched to may or may not be identical to `php`
|
|
(without @version).
|
|
|
|
TODO: Use `async` and use structured concurrency: https://www.hackingwithswift.com/swift/5.5/structured-concurrency
|
|
*/
|
|
func performSwitch(to version: String, completion: @escaping () -> Void) {
|
|
Log.info("Switching to \(version), unlinking all versions...")
|
|
|
|
let versions = getVersionsToBeHandled(version)
|
|
|
|
let group = DispatchGroup()
|
|
|
|
PhpEnv.shared.availablePhpVersions.forEach { (available) in
|
|
group.enter()
|
|
|
|
Task { // TODO: Use structured concurrency
|
|
await self.disableDefaultPhpFpmPool(available)
|
|
await self.stopPhpVersion(available)
|
|
group.leave()
|
|
}
|
|
}
|
|
|
|
group.notify(queue: .global(qos: .userInitiated)) {
|
|
Task { // TODO: Use structured concurrency
|
|
Log.info("All versions have been unlinked!")
|
|
Log.info("Linking the new version!")
|
|
|
|
for formula in versions {
|
|
await self.startPhpVersion(formula, primary: (version == formula))
|
|
}
|
|
|
|
Log.info("Restarting nginx, just to be sure!")
|
|
await brew("services restart nginx", sudo: true)
|
|
|
|
Log.info("The new version(s) have been linked!")
|
|
completion()
|
|
}
|
|
}
|
|
}
|
|
|
|
func getVersionsToBeHandled(_ primary: String) -> Set<String> {
|
|
let isolated = Valet.shared.sites.filter { site in
|
|
site.isolatedPhpVersion != nil
|
|
}.map { site in
|
|
return site.isolatedPhpVersion!.versionNumber.short
|
|
}
|
|
|
|
var versions: Set<String> = [primary]
|
|
|
|
if Valet.enabled(feature: .isolatedSites) {
|
|
versions = versions.union(isolated)
|
|
}
|
|
|
|
return versions
|
|
}
|
|
|
|
func requiresDisablingOfDefaultPhpFpmPool(_ version: String) -> Bool {
|
|
let pool = "\(Paths.etcPath)/php/\(version)/php-fpm.d/www.conf"
|
|
return FileManager.default.fileExists(atPath: pool)
|
|
}
|
|
|
|
func disableDefaultPhpFpmPool(_ version: String) async {
|
|
let pool = "\(Paths.etcPath)/php/\(version)/php-fpm.d/www.conf"
|
|
if FileManager.default.fileExists(atPath: pool) {
|
|
Log.info("A default `www.conf` file was found in the php-fpm.d directory for PHP \(version).")
|
|
let existing = URL(string: "file://\(Paths.etcPath)/php/\(version)/php-fpm.d/www.conf")!
|
|
let new = URL(string: "file://\(Paths.etcPath)/php/\(version)/php-fpm.d/www.conf.disabled-by-phpmon")!
|
|
do {
|
|
if FileManager.default.fileExists(atPath: new.path) {
|
|
Log.info("A moved `www.conf.disabled-by-phpmon` file was found for PHP \(version), "
|
|
+ "cleaning up so the newer `www.conf` can be moved again.")
|
|
try FileManager.default.removeItem(at: new)
|
|
}
|
|
try FileManager.default.moveItem(at: existing, to: new)
|
|
Log.info("Success: A default `www.conf` file was disabled for PHP \(version).")
|
|
} catch {
|
|
Log.err(error)
|
|
}
|
|
}
|
|
}
|
|
|
|
func stopPhpVersion(_ version: String) async {
|
|
let formula = (version == PhpEnv.brewPhpAlias) ? "php" : "php@\(version)"
|
|
await brew("unlink \(formula)")
|
|
await brew("services stop \(formula)", sudo: true)
|
|
Log.info("Unlinked and stopped services for \(formula)")
|
|
}
|
|
|
|
func startPhpVersion(_ version: String, primary: Bool) async {
|
|
let formula = (version == PhpEnv.brewPhpAlias) ? "php" : "php@\(version)"
|
|
|
|
if primary {
|
|
Log.info("\(formula) is the primary formula, linking and starting services...")
|
|
await brew("link \(formula) --overwrite --force")
|
|
} else {
|
|
Log.info("\(formula) is an isolated PHP version, starting services only...")
|
|
}
|
|
|
|
await brew("services start \(formula)", sudo: true)
|
|
|
|
if Valet.enabled(feature: .isolatedSites) && primary {
|
|
let socketVersion = version.replacingOccurrences(of: ".", with: "")
|
|
await Shell.quiet("ln -sF ~/.config/valet/valet\(socketVersion).sock ~/.config/valet/valet.sock")
|
|
Log.info("Symlinked new socket version (valet\(socketVersion).sock → valet.sock).")
|
|
}
|
|
|
|
}
|
|
|
|
}
|