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

♻️ Add valet command (#34), read Valet configuration (#58)

This commit is contained in:
2021-11-29 01:17:23 +01:00
parent bbb04f7907
commit 0986b97051
12 changed files with 221 additions and 12 deletions

View File

@ -47,6 +47,14 @@
C4998F0B2617633900B2526E /* PrefsWC.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4998F092617633900B2526E /* PrefsWC.swift */; };
C49EAB46259FC305007F6C3B /* Paths.swift in Sources */ = {isa = PBXBuildFile; fileRef = C49EAB45259FC305007F6C3B /* Paths.swift */; };
C4ACA38F25C754C100060C66 /* PhpExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4ACA38E25C754C100060C66 /* PhpExtension.swift */; };
C4AF9F6E275445F600D44ED0 /* ValetConfiguration.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4AF9F6D275445F600D44ED0 /* ValetConfiguration.swift */; };
C4AF9F6F275445F600D44ED0 /* ValetConfiguration.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4AF9F6D275445F600D44ED0 /* ValetConfiguration.swift */; };
C4AF9F71275445FF00D44ED0 /* valet-config.json in Resources */ = {isa = PBXBuildFile; fileRef = C4AF9F70275445FF00D44ED0 /* valet-config.json */; };
C4AF9F72275445FF00D44ED0 /* valet-config.json in Resources */ = {isa = PBXBuildFile; fileRef = C4AF9F70275445FF00D44ED0 /* valet-config.json */; };
C4AF9F78275447F100D44ED0 /* ValetConfigParserTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4AF9F76275447F100D44ED0 /* ValetConfigParserTest.swift */; };
C4AF9F7A2754499000D44ED0 /* Valet.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4AF9F792754499000D44ED0 /* Valet.swift */; };
C4AF9F7B2754499000D44ED0 /* Valet.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4AF9F792754499000D44ED0 /* Valet.swift */; };
C4AF9F7D275454A900D44ED0 /* ValetTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4AF9F7C275454A900D44ED0 /* ValetTest.swift */; };
C4D8016622B1584700C6DA1B /* Startup.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4D8016522B1584700C6DA1B /* Startup.swift */; };
C4EE188422D3386B00E126E5 /* Constants.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4EE188322D3386B00E126E5 /* Constants.swift */; };
C4F2E4372752F0870020E974 /* HomebrewDiagnostics.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4F2E4362752F0870020E974 /* HomebrewDiagnostics.swift */; };
@ -129,6 +137,11 @@
C4998F092617633900B2526E /* PrefsWC.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PrefsWC.swift; sourceTree = "<group>"; };
C49EAB45259FC305007F6C3B /* Paths.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Paths.swift; sourceTree = "<group>"; };
C4ACA38E25C754C100060C66 /* PhpExtension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PhpExtension.swift; sourceTree = "<group>"; };
C4AF9F6D275445F600D44ED0 /* ValetConfiguration.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ValetConfiguration.swift; sourceTree = "<group>"; };
C4AF9F70275445FF00D44ED0 /* valet-config.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = "valet-config.json"; sourceTree = "<group>"; };
C4AF9F76275447F100D44ED0 /* ValetConfigParserTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ValetConfigParserTest.swift; sourceTree = "<group>"; };
C4AF9F792754499000D44ED0 /* Valet.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Valet.swift; sourceTree = "<group>"; };
C4AF9F7C275454A900D44ED0 /* ValetTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ValetTest.swift; sourceTree = "<group>"; };
C4D8016522B1584700C6DA1B /* Startup.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Startup.swift; sourceTree = "<group>"; };
C4E713562570150F00007428 /* SECURITY.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = SECURITY.md; sourceTree = "<group>"; };
C4E713572570151400007428 /* docs */ = {isa = PBXFileReference; lastKnownFileType = folder; path = docs; sourceTree = "<group>"; };
@ -244,6 +257,7 @@
C41E181722CB61EB0072CF09 /* Domain */ = {
isa = PBXGroup;
children = (
C4AF9F6B275445D300D44ED0 /* Integrations */,
C4B13B1D25C4915000548C3A /* Core */,
54B20EDF263AA22C00D3250E /* PHP */,
C4F7808A25D7F918000DBC97 /* Terminal */,
@ -274,10 +288,35 @@
C476FF9722B0DD830098105B /* Alert.swift */,
C41C1B4822B00A9800E7CF16 /* MenuBarImageGenerator.swift */,
C474B00524C0E98C00066A22 /* LocalNotification.swift */,
);
path = Helpers;
sourceTree = "<group>";
};
C4AF9F6A275445C900D44ED0 /* Valet */ = {
isa = PBXGroup;
children = (
C4AF9F792754499000D44ED0 /* Valet.swift */,
C4AF9F6D275445F600D44ED0 /* ValetConfiguration.swift */,
);
path = Valet;
sourceTree = "<group>";
};
C4AF9F6B275445D300D44ED0 /* Integrations */ = {
isa = PBXGroup;
children = (
C4AF9F6C275445D900D44ED0 /* Homebrew */,
C4AF9F6A275445C900D44ED0 /* Valet */,
);
path = Integrations;
sourceTree = "<group>";
};
C4AF9F6C275445D900D44ED0 /* Homebrew */ = {
isa = PBXGroup;
children = (
C4F2E4362752F0870020E974 /* HomebrewDiagnostics.swift */,
C412E5FB25700D5300A1FB67 /* HomebrewPackage.swift */,
);
path = Helpers;
path = Homebrew;
sourceTree = "<group>";
};
C4B13B1D25C4915000548C3A /* Core */ = {
@ -294,6 +333,7 @@
C4F7807A25D7F84B000DBC97 /* phpmon-tests */ = {
isa = PBXGroup;
children = (
C4AF9F70275445FF00D44ED0 /* valet-config.json */,
C43A8A1F25D9D1D700591B77 /* brew.json */,
C4F780A725D80AE8000DBC97 /* php.ini */,
C4F7807D25D7F84B000DBC97 /* Info.plist */,
@ -302,6 +342,8 @@
C43A8A2325D9D20D00591B77 /* BrewJsonParserTest.swift */,
C4FBFC512616485F00CDB8E1 /* PhpVersionDetectionTest.swift */,
C43A8A1925D9CD1000591B77 /* Utility.swift */,
C4AF9F76275447F100D44ED0 /* ValetConfigParserTest.swift */,
C4AF9F7C275454A900D44ED0 /* ValetTest.swift */,
);
path = "phpmon-tests";
sourceTree = "<group>";
@ -416,6 +458,7 @@
files = (
C41C1B3B22B0098000E7CF16 /* Assets.xcassets in Resources */,
C41C1B3E22B0098000E7CF16 /* Main.storyboard in Resources */,
C4AF9F71275445FF00D44ED0 /* valet-config.json in Resources */,
C48D0C9025CC7FD000CC7490 /* StatsView.xib in Resources */,
C405A4D124B9B9140062FAFA /* InternetAccessPolicy.plist in Resources */,
C4232EE52612526500158FC6 /* Credits.html in Resources */,
@ -431,6 +474,7 @@
files = (
C4F780A825D80AE8000DBC97 /* php.ini in Resources */,
C43A8A2025D9D1D700591B77 /* brew.json in Resources */,
C4AF9F72275445FF00D44ED0 /* valet-config.json in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@ -445,11 +489,13 @@
C4D8016622B1584700C6DA1B /* Startup.swift in Sources */,
C4998F0A2617633900B2526E /* PrefsWC.swift in Sources */,
C4F8C0A422D4F12C002EFE61 /* DateExtension.swift in Sources */,
C4AF9F7A2754499000D44ED0 /* Valet.swift in Sources */,
5420395926135DC100FB00FA /* PrefsVC.swift in Sources */,
C41C1B4722B009A400E7CF16 /* Shell.swift in Sources */,
C4F2E43A2752F7D00020E974 /* PhpInstallation.swift in Sources */,
C41C1B4D22B0215A00E7CF16 /* Actions.swift in Sources */,
C48D0CA325CC992000CC7490 /* StatsView.swift in Sources */,
C4AF9F6E275445F600D44ED0 /* ValetConfiguration.swift in Sources */,
C4F2E4372752F0870020E974 /* HomebrewDiagnostics.swift in Sources */,
C41CD0292628D8EE0065BBED /* GlobalKeybindPreference.swift in Sources */,
C42295DD2358D02000E263B2 /* Command.swift in Sources */,
@ -485,6 +531,8 @@
C4FBFC532616485F00CDB8E1 /* PhpVersionDetectionTest.swift in Sources */,
C43A8A2425D9D20D00591B77 /* BrewJsonParserTest.swift in Sources */,
C4F780CA25D80B75000DBC97 /* HomebrewPackage.swift in Sources */,
C4AF9F6F275445F600D44ED0 /* ValetConfiguration.swift in Sources */,
C4AF9F7B2754499000D44ED0 /* Valet.swift in Sources */,
C4F780C025D80B6E000DBC97 /* Startup.swift in Sources */,
C4F2E4382752F08D0020E974 /* HomebrewDiagnostics.swift in Sources */,
C4F780AE25D80B37000DBC97 /* ExtensionParserTest.swift in Sources */,
@ -492,6 +540,7 @@
C42759682627662800093CAE /* NSMenuExtension.swift in Sources */,
C4F780CD25D80B75000DBC97 /* Alert.swift in Sources */,
C481F79726164A78004FBCFF /* PrefsVC.swift in Sources */,
C4AF9F78275447F100D44ED0 /* ValetConfigParserTest.swift in Sources */,
C4F7809C25D80344000DBC97 /* CommandTest.swift in Sources */,
C4F780BA25D80B62000DBC97 /* AppDelegate.swift in Sources */,
C4998F0B2617633900B2526E /* PrefsWC.swift in Sources */,
@ -500,6 +549,7 @@
C4F780BD25D80B65000DBC97 /* Constants.swift in Sources */,
C4F780C325D80B75000DBC97 /* HeaderView.swift in Sources */,
C4F7809625D7FBF8000DBC97 /* Shell.swift in Sources */,
C4AF9F7D275454A900D44ED0 /* ValetTest.swift in Sources */,
C4F780C525D80B75000DBC97 /* MenuBarImageGenerator.swift in Sources */,
C4F780B725D80B5D000DBC97 /* App.swift in Sources */,
C4F780C925D80B75000DBC97 /* StringExtension.swift in Sources */,

View File

@ -0,0 +1,38 @@
//
// ValetConfigParserTest.swift
// phpmon-tests
//
// Created by Nico Verbruggen on 29/11/2021.
// Copyright © 2021 Nico Verbruggen. All rights reserved.
//
import XCTest
class ValetConfigParserTest: XCTestCase {
static var jsonConfigFileUrl: URL {
return Bundle(for: Self.self).url(
forResource: "valet-config",
withExtension: "json"
)!
}
func testCanLoadConfigFile() throws {
let json = try? String(
contentsOf: Self.jsonConfigFileUrl,
encoding: .utf8
)
let config = try! JSONDecoder().decode(
ValetConfiguration.self,
from: json!.data(using: .utf8)!
)
XCTAssertEqual(config.tld, "test")
XCTAssertEqual(config.paths, [
"/Users/username/.config/valet/Sites",
"/Users/username/Sites"
])
XCTAssertEqual(config.loopback, "127.0.0.1")
}
}

View File

@ -0,0 +1,18 @@
//
// ValetTest.swift
// phpmon-tests
//
// Created by Nico Verbruggen on 29/11/2021.
// Copyright © 2021 Nico Verbruggen. All rights reserved.
//
import XCTest
class ValetTest: XCTestCase {
func testDetermineValetVersion() {
let version = Actions.valet("--version")
XCTAssert(version.contains("Laravel Valet 2."))
}
}

View File

@ -0,0 +1,8 @@
{
"tld": "test",
"paths": [
"/Users/username/.config/valet/Sites",
"/Users/username/Sites"
],
"loopback": "127.0.0.1"
}

View File

@ -102,6 +102,19 @@ class Actions {
brew("services stop dnsmasq", sudo: true)
}
/**
Kindly asks Valet to switch to a specific PHP version.
*/
public static func switchToPhpVersionUsingValet(
version: String,
availableVersions: [String],
completed: @escaping () -> Void
) {
print("Switching to \(version) using Valet")
print(valet("use php@\(version)"))
completed()
}
/**
Switching to a new PHP version involves:
- unlinking the current version
@ -203,6 +216,14 @@ class Actions {
// MARK: Common Shell Commands
/**
Runs a `valet` command.
*/
public static func valet(_ command: String) -> String
{
return Shell.pipe("sudo \(Paths.valet) \(command)", requiresPath: true)
}
/**
Runs a `brew` command. Can run as superuser.
*/

View File

@ -16,7 +16,8 @@ struct HomebrewPackage: Decodable {
let linked_keg: String?
public var version: String {
return aliases.first!.replacingOccurrences(of: "php@", with: "")
return aliases.first!
.replacingOccurrences(of: "php@", with: "")
}
}

View File

@ -0,0 +1,26 @@
//
// Valet.swift
// PHP Monitor
//
// Created by Nico Verbruggen on 29/11/2021.
// Copyright © 2021 Nico Verbruggen. All rights reserved.
//
import Foundation
class Valet {
var version: String
var detectedSites: [String]
init() {
// Let's see if we can't discern what the Valet version is
// but in order to do so, we'll need to be able to run Valet
// which has, historically, been kind of a pain in the butt
self.version = Actions.valet("--version")
.replacingOccurrences(of: "Laravel Valet ", with: "")
self.detectedSites = []
}
}

View File

@ -0,0 +1,17 @@
//
// ValetConfiguration.swift
// PHP Monitor
//
// Created by Nico Verbruggen on 29/11/2021.
// Copyright © 2021 Nico Verbruggen. All rights reserved.
//
import Foundation
class ValetConfiguration: Decodable {
let tld: String
let paths: [String]
let loopback: String
}

View File

@ -55,9 +55,14 @@ class MainMenu: NSObject, NSWindowDelegate, NSMenuDelegate {
updatePhpVersionInStatusBar()
// Attempt to find out if PHP-FPM is broken
let installation = App.phpInstall!
installation.notifyAboutBrokenPhpFpm()
// Attempt to find out more info about Valet
let valet = Valet()
print("PHP Monitor has extracted the version number of Valet: \(valet.version)")
// Schedule a request to fetch the PHP version every 60 seconds
DispatchQueue.main.async { [self] in
App.shared.timer = Timer.scheduledTimer(
@ -349,8 +354,8 @@ class MainMenu: NSObject, NSWindowDelegate, NSMenuDelegate {
}
}
// Switch the PHP version
Actions.switchToPhpVersion(
// TODO: Allow for switcher to vary?
Actions.switchToPhpVersionUsingValet(
version: sender.version,
availableVersions: App.shared.availablePhpVersions,
completed: completion

View File

@ -39,6 +39,10 @@ class Paths {
// - MARK: Binaries
public static var valet: String {
return "/Users/\(whoami)/.composer/vendor/bin/valet"
}
public static var brew: String {
return "\(binPath)/brew"
}
@ -53,6 +57,10 @@ class Paths {
// - MARK: Paths
public static var whoami: String {
return String(Shell.pipe("whoami").split(separator: "\n")[0])
}
public static var binPath: String {
return "\(shared.baseDir.rawValue)/bin"
}

View File

@ -11,12 +11,18 @@ class Shell {
// MARK: - Invoke static functions
public static func run(_ command: String) {
public static func run(
_ command: String,
requiresPath: Bool = false
) {
Shell.user.run(command)
}
public static func pipe(_ command: String) -> String {
return Shell.user.pipe(command)
public static func pipe(
_ command: String,
requiresPath: Bool = false
) -> String {
return Shell.user.pipe(command, requiresPath: requiresPath)
}
// MARK: - Singleton
@ -49,25 +55,36 @@ class Shell {
Uses the default shell.
- Parameter command: The command to run
- Parameter requiresPath: By default, the PATH is not resolved but some binaries might require this
*/
func run(_ command: String) {
func run(
_ command: String,
requiresPath: Bool = false
) {
// Equivalent of piping to /dev/null; don't do anything with the string
_ = pipe(command)
_ = Shell.pipe(command)
}
/**
Runs a shell command and returns the output.
- Parameter command: The command to run
- Parameter shell: Path to the shell to invoke
- Parameter requiresPath: By default, the PATH is not resolved but some binaries might require this
*/
func pipe(_ command: String) -> String {
func pipe(
_ command: String,
requiresPath: Bool = false
) -> String {
let task = Process()
let outputPipe = Pipe()
let errorPipe = Pipe()
let tailoredCommand = requiresPath
? "export PATH=\(Paths.binPath):$PATH && \(command)"
: command
task.launchPath = self.shell
task.arguments = ["--login", "-c", command]
task.arguments = ["--login", "-c", tailoredCommand]
task.standardOutput = outputPipe
task.standardError = errorPipe
task.launch()