mirror of
https://github.com/nicoverbruggen/phpmon.git
synced 2025-08-08 20:33:01 +02:00
Compare commits
9 Commits
Author | SHA1 | Date | |
---|---|---|---|
ec49257bcc | |||
9c6a21008a | |||
5dffbf57d1 | |||
21a1d6576e | |||
b08912ce11 | |||
7285d24ef3 | |||
ac60c66bb9 | |||
9a7575790a | |||
cd5cbccb04 |
@@ -2857,7 +2857,7 @@
|
|||||||
CODE_SIGN_IDENTITY = "Apple Development";
|
CODE_SIGN_IDENTITY = "Apple Development";
|
||||||
CODE_SIGN_STYLE = Automatic;
|
CODE_SIGN_STYLE = Automatic;
|
||||||
COMBINE_HIDPI_IMAGES = YES;
|
COMBINE_HIDPI_IMAGES = YES;
|
||||||
CURRENT_PROJECT_VERSION = 1060;
|
CURRENT_PROJECT_VERSION = 1065;
|
||||||
DEAD_CODE_STRIPPING = YES;
|
DEAD_CODE_STRIPPING = YES;
|
||||||
DEBUG = YES;
|
DEBUG = YES;
|
||||||
DEVELOPMENT_TEAM = 8M54J5J787;
|
DEVELOPMENT_TEAM = 8M54J5J787;
|
||||||
@@ -2886,7 +2886,7 @@
|
|||||||
CODE_SIGN_IDENTITY = "Apple Development";
|
CODE_SIGN_IDENTITY = "Apple Development";
|
||||||
CODE_SIGN_STYLE = Automatic;
|
CODE_SIGN_STYLE = Automatic;
|
||||||
COMBINE_HIDPI_IMAGES = YES;
|
COMBINE_HIDPI_IMAGES = YES;
|
||||||
CURRENT_PROJECT_VERSION = 1060;
|
CURRENT_PROJECT_VERSION = 1065;
|
||||||
DEAD_CODE_STRIPPING = YES;
|
DEAD_CODE_STRIPPING = YES;
|
||||||
DEBUG = NO;
|
DEBUG = NO;
|
||||||
DEVELOPMENT_TEAM = 8M54J5J787;
|
DEVELOPMENT_TEAM = 8M54J5J787;
|
||||||
@@ -3114,7 +3114,7 @@
|
|||||||
CODE_SIGN_IDENTITY = "Apple Development";
|
CODE_SIGN_IDENTITY = "Apple Development";
|
||||||
CODE_SIGN_STYLE = Automatic;
|
CODE_SIGN_STYLE = Automatic;
|
||||||
COMBINE_HIDPI_IMAGES = YES;
|
COMBINE_HIDPI_IMAGES = YES;
|
||||||
CURRENT_PROJECT_VERSION = 1060;
|
CURRENT_PROJECT_VERSION = 1065;
|
||||||
DEBUG = NO;
|
DEBUG = NO;
|
||||||
DEVELOPMENT_TEAM = 8M54J5J787;
|
DEVELOPMENT_TEAM = 8M54J5J787;
|
||||||
ENABLE_HARDENED_RUNTIME = YES;
|
ENABLE_HARDENED_RUNTIME = YES;
|
||||||
@@ -3224,7 +3224,7 @@
|
|||||||
CODE_SIGN_IDENTITY = "Apple Development";
|
CODE_SIGN_IDENTITY = "Apple Development";
|
||||||
CODE_SIGN_STYLE = Automatic;
|
CODE_SIGN_STYLE = Automatic;
|
||||||
COMBINE_HIDPI_IMAGES = YES;
|
COMBINE_HIDPI_IMAGES = YES;
|
||||||
CURRENT_PROJECT_VERSION = 1060;
|
CURRENT_PROJECT_VERSION = 1065;
|
||||||
DEBUG = YES;
|
DEBUG = YES;
|
||||||
DEVELOPMENT_TEAM = 8M54J5J787;
|
DEVELOPMENT_TEAM = 8M54J5J787;
|
||||||
ENABLE_HARDENED_RUNTIME = YES;
|
ENABLE_HARDENED_RUNTIME = YES;
|
||||||
|
@@ -13,21 +13,21 @@ class Actions {
|
|||||||
// MARK: - Services
|
// MARK: - Services
|
||||||
|
|
||||||
public static func restartPhpFpm() async {
|
public static func restartPhpFpm() async {
|
||||||
await brew("services restart \(Homebrew.Formulae.php.name)", sudo: Homebrew.Formulae.php.elevated)
|
await brew("services restart \(Homebrew.Formulae.php)", sudo: Homebrew.Formulae.php.elevated)
|
||||||
}
|
}
|
||||||
|
|
||||||
public static func restartNginx() async {
|
public static func restartNginx() async {
|
||||||
await brew("services restart \(Homebrew.Formulae.nginx.name)", sudo: Homebrew.Formulae.nginx.elevated)
|
await brew("services restart \(Homebrew.Formulae.nginx)", sudo: Homebrew.Formulae.nginx.elevated)
|
||||||
}
|
}
|
||||||
|
|
||||||
public static func restartDnsMasq() async {
|
public static func restartDnsMasq() async {
|
||||||
await brew("services restart \(Homebrew.Formulae.dnsmasq.name)", sudo: Homebrew.Formulae.dnsmasq.elevated)
|
await brew("services restart \(Homebrew.Formulae.dnsmasq)", sudo: Homebrew.Formulae.dnsmasq.elevated)
|
||||||
}
|
}
|
||||||
|
|
||||||
public static func stopValetServices() async {
|
public static func stopValetServices() async {
|
||||||
await brew("services stop \(Homebrew.Formulae.php.name)", sudo: Homebrew.Formulae.php.elevated)
|
await brew("services stop \(Homebrew.Formulae.php)", sudo: Homebrew.Formulae.php.elevated)
|
||||||
await brew("services stop \(Homebrew.Formulae.nginx.name)", sudo: Homebrew.Formulae.nginx.elevated)
|
await brew("services stop \(Homebrew.Formulae.nginx)", sudo: Homebrew.Formulae.nginx.elevated)
|
||||||
await brew("services stop \(Homebrew.Formulae.dnsmasq.name)", sudo: Homebrew.Formulae.dnsmasq.elevated)
|
await brew("services stop \(Homebrew.Formulae.dnsmasq)", sudo: Homebrew.Formulae.dnsmasq.elevated)
|
||||||
}
|
}
|
||||||
|
|
||||||
public static func fixHomebrewPermissions() throws {
|
public static func fixHomebrewPermissions() throws {
|
||||||
@@ -54,9 +54,10 @@ class Actions {
|
|||||||
+ " && "
|
+ " && "
|
||||||
+ cellarCommands.joined(separator: " && ")
|
+ cellarCommands.joined(separator: " && ")
|
||||||
|
|
||||||
let appleScript = NSAppleScript(
|
let source = "do shell script \"\(script)\" with administrator privileges"
|
||||||
source: "do shell script \"\(script)\" with administrator privileges"
|
|
||||||
)
|
Log.perf(source)
|
||||||
|
let appleScript = NSAppleScript(source: source)
|
||||||
|
|
||||||
let eventResult: NSAppleEventDescriptor? = appleScript?.executeAndReturnError(nil)
|
let eventResult: NSAppleEventDescriptor? = appleScript?.executeAndReturnError(nil)
|
||||||
|
|
||||||
|
@@ -36,10 +36,14 @@ class Homebrew {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class HomebrewFormula: Equatable, Hashable {
|
class HomebrewFormula: Equatable, Hashable, CustomStringConvertible {
|
||||||
let name: String
|
let name: String
|
||||||
let elevated: Bool
|
let elevated: Bool
|
||||||
|
|
||||||
|
var description: String {
|
||||||
|
return name
|
||||||
|
}
|
||||||
|
|
||||||
init(_ name: String, elevated: Bool = true) {
|
init(_ name: String, elevated: Bool = true) {
|
||||||
self.name = name
|
self.name = name
|
||||||
self.elevated = elevated
|
self.elevated = elevated
|
||||||
|
@@ -16,16 +16,12 @@ public class Paths {
|
|||||||
public static let shared = Paths()
|
public static let shared = Paths()
|
||||||
|
|
||||||
internal var baseDir: Paths.HomebrewDir
|
internal var baseDir: Paths.HomebrewDir
|
||||||
|
private var userName: String
|
||||||
private var userName: String! = nil
|
|
||||||
|
|
||||||
init() {
|
init() {
|
||||||
baseDir = App.architecture != "x86_64" ? .opt : .usr
|
baseDir = App.architecture != "x86_64" ? .opt : .usr
|
||||||
}
|
userName = identity()
|
||||||
|
Log.info("[ID] The current username is `\(userName)`.")
|
||||||
public func loadUser() async {
|
|
||||||
let output = await Shell.pipe("id -un").out
|
|
||||||
userName = String(output.split(separator: "\n")[0])
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public func detectBinaryPaths() {
|
public func detectBinaryPaths() {
|
||||||
|
@@ -27,6 +27,30 @@ public func system(_ command: String) -> String {
|
|||||||
return output
|
return output
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Same as the `system` command, but does not return the output. */
|
||||||
public func system_quiet(_ command: String) {
|
public func system_quiet(_ command: String) {
|
||||||
_ = system(command)
|
_ = system(command)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Retrieves the username for the currently signed in user via `/usr/bin/id`.
|
||||||
|
This cannot fail or the application will crash.
|
||||||
|
*/
|
||||||
|
public func identity() -> String {
|
||||||
|
let task = Process()
|
||||||
|
task.launchPath = "/usr/bin/id"
|
||||||
|
task.arguments = ["-un"]
|
||||||
|
|
||||||
|
let pipe = Pipe()
|
||||||
|
task.standardOutput = pipe
|
||||||
|
task.launch()
|
||||||
|
|
||||||
|
guard let output = String(
|
||||||
|
data: pipe.fileHandleForReading.readDataToEndOfFile(),
|
||||||
|
encoding: String.Encoding.utf8
|
||||||
|
) else {
|
||||||
|
fatalError("Could not retrieve username via `id -un`!")
|
||||||
|
}
|
||||||
|
|
||||||
|
return output.trimmingCharacters(in: .whitespacesAndNewlines)
|
||||||
|
}
|
||||||
|
@@ -8,8 +8,6 @@
|
|||||||
import Foundation
|
import Foundation
|
||||||
|
|
||||||
struct HomebrewPackage: Decodable {
|
struct HomebrewPackage: Decodable {
|
||||||
|
|
||||||
let name: String
|
|
||||||
let full_name: String
|
let full_name: String
|
||||||
let aliases: [String]
|
let aliases: [String]
|
||||||
let installed: [HomebrewInstalled]
|
let installed: [HomebrewInstalled]
|
||||||
|
@@ -35,6 +35,7 @@ public struct PhpVersionNumberCollection: Equatable {
|
|||||||
- Parameter strict: Whether the patch version check is strict. See more below.
|
- Parameter strict: Whether the patch version check is strict. See more below.
|
||||||
|
|
||||||
The strict mode does not matter if a patch version is provided for all versions in the collection.
|
The strict mode does not matter if a patch version is provided for all versions in the collection.
|
||||||
|
It also does not matter for certain comparisons (e.g. when dealing with wildcards).
|
||||||
|
|
||||||
Strict mode assumes that any PHP version lacking precise patch information, e.g. inferred
|
Strict mode assumes that any PHP version lacking precise patch information, e.g. inferred
|
||||||
from Homebrew corresponds to the .0 patch version of that version. The default, which is imprecise,
|
from Homebrew corresponds to the .0 patch version of that version. The default, which is imprecise,
|
||||||
@@ -45,6 +46,7 @@ public struct PhpVersionNumberCollection: Equatable {
|
|||||||
|
|
||||||
Given versions 8.0.? and 8.1.?, but the requirement is ^8.0.1, in strict mode only 8.1.? will
|
Given versions 8.0.? and 8.1.?, but the requirement is ^8.0.1, in strict mode only 8.1.? will
|
||||||
be considered valid (8.0 translates to 8.0.0 and as such is older than 8.0.1, 8.1.0 is OK).
|
be considered valid (8.0 translates to 8.0.0 and as such is older than 8.0.1, 8.1.0 is OK).
|
||||||
|
|
||||||
When checking against actual PHP versions installed by the user (with patch precision), use
|
When checking against actual PHP versions installed by the user (with patch precision), use
|
||||||
strict mode.
|
strict mode.
|
||||||
|
|
||||||
@@ -52,11 +54,26 @@ public struct PhpVersionNumberCollection: Equatable {
|
|||||||
|
|
||||||
Given versions 8.0.? and 8.1.?, but the requirement is ^8.0.1, in non-strict mode version 8.0
|
Given versions 8.0.? and 8.1.?, but the requirement is ^8.0.1, in non-strict mode version 8.0
|
||||||
is assumed to be equal to version 8.0.999, which is actually fine if 8.0.1 is the required version.
|
is assumed to be equal to version 8.0.999, which is actually fine if 8.0.1 is the required version.
|
||||||
|
|
||||||
In non-strict mode, the patch version is ignored for regular version checks (no caret / tilde).
|
In non-strict mode, the patch version is ignored for regular version checks (no caret / tilde).
|
||||||
If checking compatibility with general Homebrew versions of PHP, do NOT use strict mode, since
|
If checking compatibility with general Homebrew versions of PHP, do NOT use strict mode, since
|
||||||
the patch version there is not used. (The formula php@8.0 suffices for ^8.0.1.)
|
the patch version there is not used. (The formula php@8.0 suffices for ^8.0.1.)
|
||||||
*/
|
*/
|
||||||
public func matching(constraint: String, strict: Bool = false) -> [VersionNumber] {
|
public func matching(constraint: String, strict: Bool = false) -> [VersionNumber] {
|
||||||
|
if constraint == "*" {
|
||||||
|
return self.versions
|
||||||
|
}
|
||||||
|
|
||||||
|
if let version = VersionNumber.make(from: constraint, type: .wildCardPatch) {
|
||||||
|
// Wildcard for patch (e.g. "7.4.*") must match major and minor (any patch)
|
||||||
|
return self.versions.filter { $0.hasSameMajorAndMinor(version) }
|
||||||
|
}
|
||||||
|
|
||||||
|
if let version = VersionNumber.make(from: constraint, type: .wildCardMinor) {
|
||||||
|
// Strict constraint (e.g. "7.*") -> must only match major (any patch, minor)
|
||||||
|
return self.versions.filter { $0.isSameMajorVersionAs(version) }
|
||||||
|
}
|
||||||
|
|
||||||
if let version = VersionNumber.make(from: constraint, type: .versionOnly) {
|
if let version = VersionNumber.make(from: constraint, type: .versionOnly) {
|
||||||
// Strict constraint (e.g. "7.0") -> returns specific version
|
// Strict constraint (e.g. "7.0") -> returns specific version
|
||||||
return self.versions.filter { $0.isSameAs(version, strict) }
|
return self.versions.filter { $0.isSameAs(version, strict) }
|
||||||
|
@@ -39,6 +39,8 @@ public struct VersionNumber: Equatable, Hashable {
|
|||||||
|
|
||||||
public enum MatchType: String {
|
public enum MatchType: String {
|
||||||
case versionOnly = #"^(?<major>\d+).(?<minor>\d+).?(?<patch>\d+)?\z"#
|
case versionOnly = #"^(?<major>\d+).(?<minor>\d+).?(?<patch>\d+)?\z"#
|
||||||
|
case wildCardPatch = #"^(?<major>\d+).(?<minor>\d+).?(?<patch>\*)?\z"#
|
||||||
|
case wildCardMinor = #"^(?<major>\d+).(?<minor>\*)?\z"#
|
||||||
case caretVersionRange = #"^\^(?<major>\d+).(?<minor>\d+).?(?<patch>\d+)?\z"#
|
case caretVersionRange = #"^\^(?<major>\d+).(?<minor>\d+).?(?<patch>\d+)?\z"#
|
||||||
case tildeVersionRange = #"^~(?<major>\d+).(?<minor>\d+).?(?<patch>\d+)?\z"#
|
case tildeVersionRange = #"^~(?<major>\d+).(?<minor>\d+).?(?<patch>\d+)?\z"#
|
||||||
case greaterThanOrEqual = #"^>=(?<major>\d+).(?<minor>\d+).?(?<patch>\d+)?\z"#
|
case greaterThanOrEqual = #"^>=(?<major>\d+).(?<minor>\d+).?(?<patch>\d+)?\z"#
|
||||||
@@ -64,21 +66,25 @@ public struct VersionNumber: Equatable, Hashable {
|
|||||||
range: NSRange(location: 0, length: versionString.count)
|
range: NSRange(location: 0, length: versionString.count)
|
||||||
).first
|
).first
|
||||||
|
|
||||||
if match != nil {
|
guard let match else { return nil }
|
||||||
let major = Int(
|
|
||||||
versionString[Range(match!.range(withName: "major"), in: versionString)!]
|
let major = Int(versionString[Range(match.range(withName: "major"), in: versionString)!])!
|
||||||
)!
|
var minor: Int = 0
|
||||||
let minor = Int(
|
var patch: Int?
|
||||||
versionString[Range(match!.range(withName: "minor"), in: versionString)!]
|
|
||||||
)!
|
if let minorRange = Range(match.range(withName: "minor"), in: versionString) {
|
||||||
var patch: Int?
|
let value = versionString[minorRange] as String
|
||||||
if let minorRange = Range(match!.range(withName: "patch"), in: versionString) {
|
// Zero is the fallback if a wildcard was used
|
||||||
patch = Int(versionString[minorRange])
|
minor = Int(value) ?? 0
|
||||||
}
|
|
||||||
return Self(major: major, minor: minor, patch: patch)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
if let patchRange = Range(match.range(withName: "patch"), in: versionString) {
|
||||||
|
let value = versionString[patchRange] as String
|
||||||
|
// nil is the fallback if a wildcard was used
|
||||||
|
patch = Int(value) ?? nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return Self(major: major, minor: minor, patch: patch)
|
||||||
}
|
}
|
||||||
|
|
||||||
// MARK: Comparison Logic
|
// MARK: Comparison Logic
|
||||||
@@ -93,6 +99,10 @@ public struct VersionNumber: Equatable, Hashable {
|
|||||||
&& (strict ? self.patch(strict, version) == version.patch(strict) : true)
|
&& (strict ? self.patch(strict, version) == version.patch(strict) : true)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal func hasSameMajorAndMinor(_ version: VersionNumber) -> Bool {
|
||||||
|
return self.major == version.major && self.minor == version.minor
|
||||||
|
}
|
||||||
|
|
||||||
internal func isNewerThan(_ version: VersionNumber, _ strict: Bool) -> Bool {
|
internal func isNewerThan(_ version: VersionNumber, _ strict: Bool) -> Bool {
|
||||||
return (
|
return (
|
||||||
self.major > version.major ||
|
self.major > version.major ||
|
||||||
|
@@ -22,7 +22,6 @@ class InternalSwitcher: PhpSwitcher {
|
|||||||
*/
|
*/
|
||||||
func performSwitch(to version: String) async {
|
func performSwitch(to version: String) async {
|
||||||
Log.info("Switching to \(version), unlinking all versions...")
|
Log.info("Switching to \(version), unlinking all versions...")
|
||||||
|
|
||||||
let versions = getVersionsToBeHandled(version)
|
let versions = getVersionsToBeHandled(version)
|
||||||
|
|
||||||
await withTaskGroup(of: String.self, body: { group in
|
await withTaskGroup(of: String.self, body: { group in
|
||||||
|
@@ -111,7 +111,6 @@ class AppDelegate: NSObject, NSApplicationDelegate, UNUserNotificationCenterDele
|
|||||||
// Make sure notifications will work
|
// Make sure notifications will work
|
||||||
setupNotifications()
|
setupNotifications()
|
||||||
Task { // Make sure the menu performs its initial checks
|
Task { // Make sure the menu performs its initial checks
|
||||||
await paths.loadUser()
|
|
||||||
await menu.startup()
|
await menu.startup()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -17,7 +17,7 @@ public class EnvironmentManager {
|
|||||||
|
|
||||||
// Failure condition #1: does not contain Laravel Valet
|
// Failure condition #1: does not contain Laravel Valet
|
||||||
if !output.contains("Laravel Valet") {
|
if !output.contains("Laravel Valet") {
|
||||||
return true
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
// Extract the version number
|
// Extract the version number
|
||||||
@@ -25,7 +25,6 @@ public class EnvironmentManager {
|
|||||||
|
|
||||||
// Get the actual version
|
// Get the actual version
|
||||||
return Valet.shared.version == nil
|
return Valet.shared.version == nil
|
||||||
|
|
||||||
}() // returns true if none of the failure conditions are met
|
}() // returns true if none of the failure conditions are met
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -110,9 +110,9 @@ extension MainMenu {
|
|||||||
Task { @MainActor in
|
Task { @MainActor in
|
||||||
OnboardingWindowController.show()
|
OnboardingWindowController.show()
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
await AppUpdater().checkForUpdates(interactive: false)
|
||||||
}
|
}
|
||||||
|
|
||||||
await AppUpdater().checkForUpdates(interactive: false)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if the linked version has changed between launches of phpmon
|
// Check if the linked version has changed between launches of phpmon
|
||||||
|
@@ -42,4 +42,13 @@ class OnboardingWindowController: PMWindowController {
|
|||||||
|
|
||||||
NSApp.activate(ignoringOtherApps: true)
|
NSApp.activate(ignoringOtherApps: true)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override func close() {
|
||||||
|
super.close()
|
||||||
|
|
||||||
|
// Search for updates after closing the window
|
||||||
|
if Stats.successfulLaunchCount == 1 {
|
||||||
|
Task { await AppUpdater().checkForUpdates(interactive: false) }
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -40,7 +40,7 @@
|
|||||||
<key>LSUIElement</key>
|
<key>LSUIElement</key>
|
||||||
<true/>
|
<true/>
|
||||||
<key>NSHumanReadableCopyright</key>
|
<key>NSHumanReadableCopyright</key>
|
||||||
<string>Copyright © 2019-2022 Nico Verbruggen. All rights reserved.</string>
|
<string>Copyright © 2019-2023 Nico Verbruggen. All rights reserved.</string>
|
||||||
<key>NSMainStoryboardFile</key>
|
<key>NSMainStoryboardFile</key>
|
||||||
<string>Main</string>
|
<string>Main</string>
|
||||||
<key>NSPrincipalClass</key>
|
<key>NSPrincipalClass</key>
|
||||||
|
@@ -355,6 +355,9 @@ This has no effect on other terminals, only for the particular terminal session
|
|||||||
"notification.preset_reverted_title" = "Preset reverted";
|
"notification.preset_reverted_title" = "Preset reverted";
|
||||||
"notification.preset_reverted_desc" = "The last preset you applied has been undone. Your previous configuration is now active.";
|
"notification.preset_reverted_desc" = "The last preset you applied has been undone. Your previous configuration is now active.";
|
||||||
|
|
||||||
|
"notification.phpmon_updated.title" = "PHP Monitor has been updated!";
|
||||||
|
"notification.phpmon_updated.desc" = "You are now running PHP Monitor v%@.";
|
||||||
|
|
||||||
// Composer Update
|
// Composer Update
|
||||||
"alert.composer_missing.title" = "Composer not found!";
|
"alert.composer_missing.title" = "Composer not found!";
|
||||||
"alert.composer_missing.subtitle" = "PHP Monitor could not find Composer. Make sure that Composer is installed and try again.";
|
"alert.composer_missing.subtitle" = "PHP Monitor could not find Composer. Make sure that Composer is installed and try again.";
|
||||||
|
@@ -23,11 +23,10 @@ class HomebrewPackageTest: XCTestCase {
|
|||||||
[HomebrewPackage].self, from: json.data(using: .utf8)!
|
[HomebrewPackage].self, from: json.data(using: .utf8)!
|
||||||
).first!
|
).first!
|
||||||
|
|
||||||
XCTAssertEqual(package.name, "php")
|
|
||||||
XCTAssertEqual(package.full_name, "php")
|
XCTAssertEqual(package.full_name, "php")
|
||||||
XCTAssertEqual(package.aliases.first!, "php@8.1")
|
XCTAssertEqual(package.aliases.first!, "php@8.2")
|
||||||
XCTAssertEqual(package.installed.contains(where: { installed in
|
XCTAssertEqual(package.installed.contains(where: { installed in
|
||||||
installed.version.starts(with: "8.1")
|
installed.version.starts(with: "8.2")
|
||||||
}), true)
|
}), true)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -1,69 +1,77 @@
|
|||||||
[
|
[
|
||||||
{
|
{
|
||||||
"name": "php",
|
|
||||||
"full_name": "php",
|
"full_name": "php",
|
||||||
"tap": "homebrew/core",
|
"tap": "homebrew/core",
|
||||||
"oldname": null,
|
"oldname": null,
|
||||||
"aliases": [
|
"aliases": [
|
||||||
"php@8.1"
|
"php@8.2"
|
||||||
],
|
],
|
||||||
"versioned_formulae": [
|
"versioned_formulae": [
|
||||||
|
"php@8.1",
|
||||||
"php@8.0",
|
"php@8.0",
|
||||||
"php@7.4",
|
"php@7.4"
|
||||||
"php@7.3",
|
|
||||||
"php@7.2"
|
|
||||||
],
|
],
|
||||||
"desc": "General-purpose scripting language",
|
"desc": "General-purpose scripting language",
|
||||||
"license": "PHP-3.01",
|
"license": "PHP-3.01",
|
||||||
"homepage": "https://www.php.net/",
|
"homepage": "https://www.php.net/",
|
||||||
"versions": {
|
"versions": {
|
||||||
"stable": "8.1.10",
|
"stable": "8.2.2",
|
||||||
"head": "HEAD",
|
"head": "HEAD",
|
||||||
"bottle": true
|
"bottle": true
|
||||||
},
|
},
|
||||||
"urls": {
|
"urls": {
|
||||||
"stable": {
|
"stable": {
|
||||||
"url": "https://www.php.net/distributions/php-8.1.10.tar.xz",
|
"url": "https://www.php.net/distributions/php-8.2.2.tar.xz",
|
||||||
"tag": null,
|
"tag": null,
|
||||||
"revision": null
|
"revision": null,
|
||||||
|
"checksum": "bdc4aa38e652bac86039601840bae01c0c3653972eaa6f9f93d5f71953a7ee33"
|
||||||
|
},
|
||||||
|
"head": {
|
||||||
|
"url": "https://github.com/php/php-src.git",
|
||||||
|
"branch": "master"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"revision": 1,
|
"revision": 0,
|
||||||
"version_scheme": 0,
|
"version_scheme": 0,
|
||||||
"bottle": {
|
"bottle": {
|
||||||
"stable": {
|
"stable": {
|
||||||
"rebuild": 0,
|
"rebuild": 0,
|
||||||
"root_url": "https://ghcr.io/v2/homebrew/core",
|
"root_url": "https://ghcr.io/v2/homebrew/core",
|
||||||
"files": {
|
"files": {
|
||||||
|
"arm64_ventura": {
|
||||||
|
"cellar": "/opt/homebrew/Cellar",
|
||||||
|
"url": "https://ghcr.io/v2/homebrew/core/php/blobs/sha256:ad2e6a6f1cdc65c22b39bd607cbb7305958951cf58ee87d5060717be5a8b5a45",
|
||||||
|
"sha256": "ad2e6a6f1cdc65c22b39bd607cbb7305958951cf58ee87d5060717be5a8b5a45"
|
||||||
|
},
|
||||||
"arm64_monterey": {
|
"arm64_monterey": {
|
||||||
"cellar": "/opt/homebrew/Cellar",
|
"cellar": "/opt/homebrew/Cellar",
|
||||||
"url": "https://ghcr.io/v2/homebrew/core/php/blobs/sha256:dcee33c9f445db3026a7e867805eb8f6d82e9e5599599b8c6cd8645475f7961c",
|
"url": "https://ghcr.io/v2/homebrew/core/php/blobs/sha256:27069c973e63f38a3cb4fad1c7a2e17853bcffe318c8a957ff96a1026dff0cac",
|
||||||
"sha256": "dcee33c9f445db3026a7e867805eb8f6d82e9e5599599b8c6cd8645475f7961c"
|
"sha256": "27069c973e63f38a3cb4fad1c7a2e17853bcffe318c8a957ff96a1026dff0cac"
|
||||||
},
|
},
|
||||||
"arm64_big_sur": {
|
"arm64_big_sur": {
|
||||||
"cellar": "/opt/homebrew/Cellar",
|
"cellar": "/opt/homebrew/Cellar",
|
||||||
"url": "https://ghcr.io/v2/homebrew/core/php/blobs/sha256:e0590064cd32f2baa4102fa49c80056f3886a0a89aec0589d0134ecbf0e7923e",
|
"url": "https://ghcr.io/v2/homebrew/core/php/blobs/sha256:ceef280bcd57e5f794ae59cc75e83d407c9704aa3d238b282bda52cbc644d0dd",
|
||||||
"sha256": "e0590064cd32f2baa4102fa49c80056f3886a0a89aec0589d0134ecbf0e7923e"
|
"sha256": "ceef280bcd57e5f794ae59cc75e83d407c9704aa3d238b282bda52cbc644d0dd"
|
||||||
|
},
|
||||||
|
"ventura": {
|
||||||
|
"cellar": "/usr/local/Cellar",
|
||||||
|
"url": "https://ghcr.io/v2/homebrew/core/php/blobs/sha256:22f733b7b0b0ed95cd6b0a1534b9eca4cf63fe54647394c3f7e7ac019eb019ff",
|
||||||
|
"sha256": "22f733b7b0b0ed95cd6b0a1534b9eca4cf63fe54647394c3f7e7ac019eb019ff"
|
||||||
},
|
},
|
||||||
"monterey": {
|
"monterey": {
|
||||||
"cellar": "/usr/local/Cellar",
|
"cellar": "/usr/local/Cellar",
|
||||||
"url": "https://ghcr.io/v2/homebrew/core/php/blobs/sha256:62481320613b19c6ff310bf6ed50c7d2a2253cdbf403af12ec97bccd8a97a84c",
|
"url": "https://ghcr.io/v2/homebrew/core/php/blobs/sha256:9ff8f5e1df5e849567cdb2ddea6d3c2a2b9cae024842c9ac65b35a01657bfc37",
|
||||||
"sha256": "62481320613b19c6ff310bf6ed50c7d2a2253cdbf403af12ec97bccd8a97a84c"
|
"sha256": "9ff8f5e1df5e849567cdb2ddea6d3c2a2b9cae024842c9ac65b35a01657bfc37"
|
||||||
},
|
},
|
||||||
"big_sur": {
|
"big_sur": {
|
||||||
"cellar": "/usr/local/Cellar",
|
"cellar": "/usr/local/Cellar",
|
||||||
"url": "https://ghcr.io/v2/homebrew/core/php/blobs/sha256:b34d96f7aad3c580a7cbdaadb8054fb9b6872111a5eec8e1bcb4a529970c8e03",
|
"url": "https://ghcr.io/v2/homebrew/core/php/blobs/sha256:11fd1ea6da8ef728b7cacd4da8a51ed125069595abf4e37ae1552d418560c5fb",
|
||||||
"sha256": "b34d96f7aad3c580a7cbdaadb8054fb9b6872111a5eec8e1bcb4a529970c8e03"
|
"sha256": "11fd1ea6da8ef728b7cacd4da8a51ed125069595abf4e37ae1552d418560c5fb"
|
||||||
},
|
|
||||||
"catalina": {
|
|
||||||
"cellar": "/usr/local/Cellar",
|
|
||||||
"url": "https://ghcr.io/v2/homebrew/core/php/blobs/sha256:cc0b85dcfdd60e1d8d7fa74c9f53be5d249d068835dbc7a81edacb7a076b6c76",
|
|
||||||
"sha256": "cc0b85dcfdd60e1d8d7fa74c9f53be5d249d068835dbc7a81edacb7a076b6c76"
|
|
||||||
},
|
},
|
||||||
"x86_64_linux": {
|
"x86_64_linux": {
|
||||||
"cellar": "/home/linuxbrew/.linuxbrew/Cellar",
|
"cellar": "/home/linuxbrew/.linuxbrew/Cellar",
|
||||||
"url": "https://ghcr.io/v2/homebrew/core/php/blobs/sha256:b934a5a4ad2d29b629f83962b57f638a654801d1ba21ba659a42da2e5afe3fae",
|
"url": "https://ghcr.io/v2/homebrew/core/php/blobs/sha256:baaa41e60f9e8125fe8f549d4813a8476a8947a1f10d7817a2ee36d8baa625f3",
|
||||||
"sha256": "b934a5a4ad2d29b629f83962b57f638a654801d1ba21ba659a42da2e5afe3fae"
|
"sha256": "baaa41e60f9e8125fe8f549d4813a8476a8947a1f10d7817a2ee36d8baa625f3"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -127,34 +135,35 @@
|
|||||||
"conflicts_with": [
|
"conflicts_with": [
|
||||||
|
|
||||||
],
|
],
|
||||||
"caveats": "To enable PHP in Apache add the following to httpd.conf and restart Apache:\n LoadModule php_module $(brew --prefix)/opt/php/lib/httpd/modules/libphp.so\n\n <FilesMatch \\.php$>\n SetHandler application/x-httpd-php\n </FilesMatch>\n\nFinally, check DirectoryIndex includes index.php\n DirectoryIndex index.php index.html\n\nThe php.ini and php-fpm.ini file can be found in:\n $(brew --prefix)/etc/php/8.1/\n",
|
"caveats": "To enable PHP in Apache add the following to httpd.conf and restart Apache:\n LoadModule php_module $(brew --prefix)/opt/php/lib/httpd/modules/libphp.so\n\n <FilesMatch \\.php$>\n SetHandler application/x-httpd-php\n </FilesMatch>\n\nFinally, check DirectoryIndex includes index.php\n DirectoryIndex index.php index.html\n\nThe php.ini and php-fpm.ini file can be found in:\n $(brew --prefix)/etc/php/8.2/\n",
|
||||||
"installed": [
|
"installed": [
|
||||||
{
|
{
|
||||||
"version": "8.1.10_1",
|
"version": "8.2.2",
|
||||||
"used_options": [
|
"used_options": [
|
||||||
|
|
||||||
],
|
],
|
||||||
"built_as_bottle": true,
|
"built_as_bottle": true,
|
||||||
"poured_from_bottle": true,
|
"poured_from_bottle": true,
|
||||||
|
"time": 1675654665,
|
||||||
"runtime_dependencies": [
|
"runtime_dependencies": [
|
||||||
{
|
{
|
||||||
"full_name": "apr",
|
"full_name": "apr",
|
||||||
"version": "1.7.0",
|
"version": "1.7.2",
|
||||||
"declared_directly": true
|
"declared_directly": true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"full_name": "ca-certificates",
|
"full_name": "ca-certificates",
|
||||||
"version": "2022-07-19",
|
"version": "2023-01-10",
|
||||||
"declared_directly": false
|
"declared_directly": false
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"full_name": "openssl@1.1",
|
"full_name": "openssl@1.1",
|
||||||
"version": "1.1.1q",
|
"version": "1.1.1s",
|
||||||
"declared_directly": true
|
"declared_directly": true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"full_name": "apr-util",
|
"full_name": "apr-util",
|
||||||
"version": "1.6.1",
|
"version": "1.6.3",
|
||||||
"declared_directly": true
|
"declared_directly": true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -182,24 +191,24 @@
|
|||||||
"version": "1.0.9",
|
"version": "1.0.9",
|
||||||
"declared_directly": false
|
"declared_directly": false
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"full_name": "gettext",
|
|
||||||
"version": "0.21",
|
|
||||||
"declared_directly": true
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"full_name": "libunistring",
|
"full_name": "libunistring",
|
||||||
"version": "1.0",
|
"version": "1.1",
|
||||||
"declared_directly": false
|
"declared_directly": false
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"full_name": "gettext",
|
||||||
|
"version": "0.21.1",
|
||||||
|
"declared_directly": true
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"full_name": "libidn2",
|
"full_name": "libidn2",
|
||||||
"version": "2.3.3",
|
"version": "2.3.4",
|
||||||
"declared_directly": false
|
"declared_directly": false
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"full_name": "libnghttp2",
|
"full_name": "libnghttp2",
|
||||||
"version": "1.49.0",
|
"version": "1.51.0",
|
||||||
"declared_directly": false
|
"declared_directly": false
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -224,7 +233,7 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"full_name": "xz",
|
"full_name": "xz",
|
||||||
"version": "5.2.6",
|
"version": "5.4.1",
|
||||||
"declared_directly": false
|
"declared_directly": false
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -234,7 +243,7 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"full_name": "curl",
|
"full_name": "curl",
|
||||||
"version": "7.85.0",
|
"version": "7.87.0",
|
||||||
"declared_directly": true
|
"declared_directly": true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -249,12 +258,12 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"full_name": "freetds",
|
"full_name": "freetds",
|
||||||
"version": "1.3.13",
|
"version": "1.3.17",
|
||||||
"declared_directly": true
|
"declared_directly": true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"full_name": "libpng",
|
"full_name": "libpng",
|
||||||
"version": "1.6.37",
|
"version": "1.6.39",
|
||||||
"declared_directly": false
|
"declared_directly": false
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -264,12 +273,12 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"full_name": "fontconfig",
|
"full_name": "fontconfig",
|
||||||
"version": "2.14.0",
|
"version": "2.14.2",
|
||||||
"declared_directly": false
|
"declared_directly": false
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"full_name": "jpeg-turbo",
|
"full_name": "jpeg-turbo",
|
||||||
"version": "2.1.4",
|
"version": "2.1.5",
|
||||||
"declared_directly": false
|
"declared_directly": false
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -278,13 +287,13 @@
|
|||||||
"declared_directly": false
|
"declared_directly": false
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"full_name": "imath",
|
"full_name": "highway",
|
||||||
"version": "3.1.5",
|
"version": "1.0.3",
|
||||||
"declared_directly": false
|
"declared_directly": false
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"full_name": "openexr",
|
"full_name": "imath",
|
||||||
"version": "3.1.5",
|
"version": "3.1.6",
|
||||||
"declared_directly": false
|
"declared_directly": false
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -292,14 +301,24 @@
|
|||||||
"version": "4.4.0",
|
"version": "4.4.0",
|
||||||
"declared_directly": false
|
"declared_directly": false
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"full_name": "little-cms2",
|
||||||
|
"version": "2.14",
|
||||||
|
"declared_directly": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"full_name": "openexr",
|
||||||
|
"version": "3.1.5",
|
||||||
|
"declared_directly": false
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"full_name": "webp",
|
"full_name": "webp",
|
||||||
"version": "1.2.4",
|
"version": "1.3.0",
|
||||||
"declared_directly": false
|
"declared_directly": false
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"full_name": "jpeg-xl",
|
"full_name": "jpeg-xl",
|
||||||
"version": "0.6.1",
|
"version": "0.8.1",
|
||||||
"declared_directly": false
|
"declared_directly": false
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -309,12 +328,12 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"full_name": "aom",
|
"full_name": "aom",
|
||||||
"version": "3.4.0",
|
"version": "3.5.0",
|
||||||
"declared_directly": false
|
"declared_directly": false
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"full_name": "libavif",
|
"full_name": "libavif",
|
||||||
"version": "0.10.1",
|
"version": "0.11.1",
|
||||||
"declared_directly": false
|
"declared_directly": false
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -329,17 +348,17 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"full_name": "icu4c",
|
"full_name": "icu4c",
|
||||||
"version": "71.1",
|
"version": "72.1",
|
||||||
"declared_directly": true
|
"declared_directly": true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"full_name": "krb5",
|
"full_name": "krb5",
|
||||||
"version": "1.20",
|
"version": "1.20.1",
|
||||||
"declared_directly": true
|
"declared_directly": true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"full_name": "libpq",
|
"full_name": "libpq",
|
||||||
"version": "14.5",
|
"version": "15.1",
|
||||||
"declared_directly": true
|
"declared_directly": true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -359,17 +378,17 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"full_name": "pcre2",
|
"full_name": "pcre2",
|
||||||
"version": "10.40",
|
"version": "10.42",
|
||||||
"declared_directly": true
|
"declared_directly": true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"full_name": "readline",
|
"full_name": "readline",
|
||||||
"version": "8.1.2",
|
"version": "8.2.1",
|
||||||
"declared_directly": false
|
"declared_directly": false
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"full_name": "sqlite",
|
"full_name": "sqlite",
|
||||||
"version": "3.39.2",
|
"version": "3.40.1",
|
||||||
"declared_directly": true
|
"declared_directly": true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -382,7 +401,7 @@
|
|||||||
"installed_on_request": true
|
"installed_on_request": true
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"linked_keg": "8.1.10_1",
|
"linked_keg": "8.2.2",
|
||||||
"pinned": false,
|
"pinned": false,
|
||||||
"outdated": false,
|
"outdated": false,
|
||||||
"deprecated": false,
|
"deprecated": false,
|
||||||
@@ -390,6 +409,8 @@
|
|||||||
"deprecation_reason": null,
|
"deprecation_reason": null,
|
||||||
"disabled": false,
|
"disabled": false,
|
||||||
"disable_date": null,
|
"disable_date": null,
|
||||||
"disable_reason": null
|
"disable_reason": null,
|
||||||
|
"tap_git_head": "0bbb89420e74756a5a5c145ed7efa4a32f7e7e7c"
|
||||||
}
|
}
|
||||||
]
|
|
||||||
|
]
|
||||||
|
@@ -44,6 +44,53 @@ class PhpVersionNumberTest: XCTestCase {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func test_can_parse_wildcard() throws {
|
||||||
|
let version = VersionNumber.make(from: "7.*", type: .wildCardMinor)
|
||||||
|
XCTAssertNotNil(version)
|
||||||
|
XCTAssertEqual(version!.major, 7)
|
||||||
|
XCTAssertEqual(version!.minor, 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
func test_can_check_wildcard_version_constraint() throws {
|
||||||
|
// Wildcard for patch only
|
||||||
|
XCTAssertEqual(
|
||||||
|
PhpVersionNumberCollection
|
||||||
|
.make(from: ["7.4.10", "7.3.10", "7.3.9"])
|
||||||
|
.matching(constraint: "7.3.*", strict: false),
|
||||||
|
PhpVersionNumberCollection
|
||||||
|
.make(from: ["7.3.10", "7.3.9"]).all
|
||||||
|
)
|
||||||
|
|
||||||
|
// Wildcard for minor
|
||||||
|
XCTAssertEqual(
|
||||||
|
PhpVersionNumberCollection
|
||||||
|
.make(from: ["8.0.0", "7.4.10", "7.3.10", "7.3.9"])
|
||||||
|
.matching(constraint: "7.*", strict: false),
|
||||||
|
PhpVersionNumberCollection
|
||||||
|
.make(from: ["7.4.10", "7.3.10", "7.3.9"]).all
|
||||||
|
)
|
||||||
|
|
||||||
|
// Full wildcard
|
||||||
|
XCTAssertEqual(
|
||||||
|
PhpVersionNumberCollection
|
||||||
|
.make(from: ["7.4.10", "7.3.10", "7.2.10", "7.1.10", "7.0.10"])
|
||||||
|
.matching(constraint: "*", strict: false),
|
||||||
|
PhpVersionNumberCollection
|
||||||
|
.make(from: ["7.4.10", "7.3.10", "7.2.10", "7.1.10", "7.0.10"]).all
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
func test_can_check_any_version_constraint() throws {
|
||||||
|
XCTAssertEqual(
|
||||||
|
PhpVersionNumberCollection
|
||||||
|
.make(from: ["7.4.10", "7.3.10", "7.2.10", "7.1.10", "7.0.10"])
|
||||||
|
.matching(constraint: "*", strict: false),
|
||||||
|
PhpVersionNumberCollection
|
||||||
|
.make(from: ["7.4.10", "7.3.10", "7.2.10", "7.1.10", "7.0.10"]).all
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
func test_can_check_fixed_constraints() throws {
|
func test_can_check_fixed_constraints() throws {
|
||||||
XCTAssertEqual(
|
XCTAssertEqual(
|
||||||
PhpVersionNumberCollection
|
PhpVersionNumberCollection
|
||||||
|
Reference in New Issue
Block a user