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

🚛 VersionNumber, PhpVersionNumberCollection

This commit is contained in:
2023-01-06 12:41:37 +01:00
parent d854dee2a1
commit 3d505aebde
4 changed files with 124 additions and 91 deletions

View File

@ -572,6 +572,10 @@
C4CE3BBA27B31F670086CA49 /* ComposerWindow.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4CE3BB927B31F670086CA49 /* ComposerWindow.swift */; };
C4CE3BBB27B324230086CA49 /* MainMenu+Switcher.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4CE3BB727B31F2E0086CA49 /* MainMenu+Switcher.swift */; };
C4CE3BBC27B324250086CA49 /* ComposerWindow.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4CE3BB927B31F670086CA49 /* ComposerWindow.swift */; };
C4CE7F9629683B43000102CF /* PhpVersionNumberCollection.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4CE7F9529683B43000102CF /* PhpVersionNumberCollection.swift */; };
C4CE7F9729683B43000102CF /* PhpVersionNumberCollection.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4CE7F9529683B43000102CF /* PhpVersionNumberCollection.swift */; };
C4CE7F9829683B43000102CF /* PhpVersionNumberCollection.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4CE7F9529683B43000102CF /* PhpVersionNumberCollection.swift */; };
C4CE7F9929683B43000102CF /* PhpVersionNumberCollection.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4CE7F9529683B43000102CF /* PhpVersionNumberCollection.swift */; };
C4D36601291132B7006BD146 /* ValetScanners.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4D36600291132B7006BD146 /* ValetScanners.swift */; };
C4D36602291132B7006BD146 /* ValetScanners.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4D36600291132B7006BD146 /* ValetScanners.swift */; };
C4D36603291132B7006BD146 /* ValetScanners.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4D36600291132B7006BD146 /* ValetScanners.swift */; };
@ -874,6 +878,7 @@
C4CDA892288F1A71007CE25F /* Keys.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Keys.swift; sourceTree = "<group>"; };
C4CE3BB727B31F2E0086CA49 /* MainMenu+Switcher.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "MainMenu+Switcher.swift"; sourceTree = "<group>"; };
C4CE3BB927B31F670086CA49 /* ComposerWindow.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ComposerWindow.swift; sourceTree = "<group>"; };
C4CE7F9529683B43000102CF /* PhpVersionNumberCollection.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PhpVersionNumberCollection.swift; sourceTree = "<group>"; };
C4D36600291132B7006BD146 /* ValetScanners.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ValetScanners.swift; sourceTree = "<group>"; };
C4D3660A29113F20006BD146 /* System.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = System.swift; sourceTree = "<group>"; };
C4D3660F291140BE006BD146 /* TestableFileSystemTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TestableFileSystemTest.swift; sourceTree = "<group>"; };
@ -1400,8 +1405,9 @@
C48D6C6E279CD29C00F26D7E /* PHP Version */ = {
isa = PBXGroup;
children = (
C40C7F1D2772136000DDDCDC /* PhpEnv.swift */,
C48D6C6F279CD2AC00F26D7E /* VersionNumber.swift */,
C4CE7F9529683B43000102CF /* PhpVersionNumberCollection.swift */,
C40C7F1D2772136000DDDCDC /* PhpEnv.swift */,
C4D936C827E3EB6100BD69FE /* PhpHelper.swift */,
);
path = "PHP Version";
@ -2067,6 +2073,7 @@
C4C8900528F0E3D100CE5E97 /* RealFileSystem.swift in Sources */,
C4A81CA428C67101008DD9D1 /* PMTableView.swift in Sources */,
C4927F0B27B2DFC200C55AFD /* Errors.swift in Sources */,
C4CE7F9629683B43000102CF /* PhpVersionNumberCollection.swift in Sources */,
C4B5853E2770FE3900DA4FBE /* Paths.swift in Sources */,
C41C1B4B22B019FF00E7CF16 /* ActivePhpInstallation.swift in Sources */,
C4FE011128084FC200D1DE6D /* SelectionVC.swift in Sources */,
@ -2190,6 +2197,7 @@
C4E2E84C28FC1E70003B070C /* DataExtension.swift in Sources */,
C471E86E28F9BB650021E251 /* MenuBarIcons.swift in Sources */,
C471E86F28F9BB650021E251 /* Stats.swift in Sources */,
C4CE7F9829683B43000102CF /* PhpVersionNumberCollection.swift in Sources */,
C471E87028F9BB650021E251 /* GlobalKeybindPreference.swift in Sources */,
C471E87228F9BB650021E251 /* CheckboxPreferenceView.swift in Sources */,
C471E87428F9BB650021E251 /* SelectPreferenceView.swift in Sources */,
@ -2381,6 +2389,7 @@
C471E8F128F9BB8F0021E251 /* KeyCombo.swift in Sources */,
C471E8F228F9BB8F0021E251 /* ModifierFlagsExtension.swift in Sources */,
C471E7F028F9BAC30021E251 /* Paths.swift in Sources */,
C4CE7F9929683B43000102CF /* PhpVersionNumberCollection.swift in Sources */,
C471E7FC28F9BACE0021E251 /* HomebrewPackage.swift in Sources */,
C471E7CF28F9BA600021E251 /* ActiveShell.swift in Sources */,
C471E7F628F9BAC80021E251 /* PhpHelper.swift in Sources */,
@ -2529,6 +2538,7 @@
C4068CAB27B0890D00544CD5 /* MenuBarIcons.swift in Sources */,
C4AD38B328ECD9D300FA8D83 /* TestableFileSystem.swift in Sources */,
C40C5C9D2846A40600E28255 /* Preset.swift in Sources */,
C4CE7F9729683B43000102CF /* PhpVersionNumberCollection.swift in Sources */,
C4F30B09278E1A0E00755FCE /* CustomPrefs.swift in Sources */,
C40FE738282ABA4F00A302C2 /* AppVersion.swift in Sources */,
C415D3E92770F692005EF286 /* AppDelegate+InterApp.swift in Sources */,

View File

@ -0,0 +1,100 @@
//
// PhpVersionNumberCollection.swift
// PHP Monitor
//
// Created by Nico Verbruggen on 06/01/2023.
// Copyright © 2023 Nico Verbruggen. All rights reserved.
//
import Foundation
public struct PhpVersionNumberCollection: Equatable {
let versions: [VersionNumber]
public static func make(from versions: [String]) -> Self {
return PhpVersionNumberCollection(
versions: versions.map { try! VersionNumber.parse($0) }
)
}
public var first: VersionNumber? {
return self.versions.first
}
public var all: [VersionNumber] {
return self.versions
}
/**
Checks if any versions of PHP are valid for the constraint provided.
Due to the complexity of evaluating these, a important test is maintained.
More information on these constraints can be found here:
https://getcomposer.org/doc/articles/versions.md#writing-version-constraints
- Parameter constraint: The full constraint as a string (e.g. "^7.0")
- 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.
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,
assumes that the patch version is .999, which means that in all cases the patch version check is
always going to pass.
**STRICT MODE (= patch precision on)**
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).
When checking against actual PHP versions installed by the user (with patch precision), use
strict mode.
**NON-STRICT MODE (= patch precision off)**
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.
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
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] {
if let version = VersionNumber.make(from: constraint, type: .versionOnly) {
// Strict constraint (e.g. "7.0") -> returns specific version
return self.versions.filter { $0.isSameAs(version, strict) }
}
if let version = VersionNumber.make(from: constraint, type: .caretVersionRange) {
// Caret range means that the major version is never higher but minor version can be higher
// ^7.2 will be compatible with all versions between 7.2 and 8.0
return self.versions.filter { $0.hasNewerMinorVersionOrPatch(version, strict) }
}
if let version = VersionNumber.make(from: constraint, type: .tildeVersionRange) {
// Tilde range means that most specific digit is used as the basis.
return self.versions.filter {
version.patch != nil
// If a patch is provided then the minor version cannot be bumped.
? $0.hasSameMajorAndMinorButNewerOrSamePatch(version, strict)
// If a patch is not provided then the major version cannot be bumped.
: $0.hasSameMajorButNewerOrSameMinor(version, strict)
}
}
if let version = VersionNumber.make(from: constraint, type: .greaterThanOrEqual) {
return self.versions.filter { $0.isSameAs(version, strict) || $0.isNewerThan(version, strict) }
}
if let version = VersionNumber.make(from: constraint, type: .greaterThan) {
return self.versions.filter { $0.isNewerThan(version, strict) }
}
if let version = VersionNumber.make(from: constraint, type: .smallerThanOrEqual) {
return self.versions.filter { $0.isSameAs(version, strict) || $0.isOlderThan(version, strict)}
}
if let version = VersionNumber.make(from: constraint, type: .smallerThan) {
return self.versions.filter { $0.isOlderThan(version, strict)}
}
return []
}
}

View File

@ -8,97 +8,12 @@
import Foundation
public struct PhpVersionNumberCollection: Equatable {
let versions: [VersionNumber]
public static func make(from versions: [String]) -> Self {
return PhpVersionNumberCollection(
versions: versions.map { try! VersionNumber.parse($0) }
)
}
public var first: VersionNumber? {
return self.versions.first
}
public var all: [VersionNumber] {
return self.versions
}
/**
Checks if any versions of PHP are valid for the constraint provided.
Due to the complexity of evaluating these, a important test is maintained.
More information on these constraints can be found here:
https://getcomposer.org/doc/articles/versions.md#writing-version-constraints
- Parameter constraint: The full constraint as a string (e.g. "^7.0")
- 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.
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,
assumes that the patch version is .999, which means that in all cases the patch version check is
always going to pass.
**STRICT MODE (= patch precision on)**
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).
When checking against actual PHP versions installed by the user (with patch precision), use
strict mode.
**NON-STRICT MODE (= patch precision off)**
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.
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
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] {
if let version = VersionNumber.make(from: constraint, type: .versionOnly) {
// Strict constraint (e.g. "7.0") -> returns specific version
return self.versions.filter { $0.isSameAs(version, strict) }
}
if let version = VersionNumber.make(from: constraint, type: .caretVersionRange) {
// Caret range means that the major version is never higher but minor version can be higher
// ^7.2 will be compatible with all versions between 7.2 and 8.0
return self.versions.filter { $0.hasNewerMinorVersionOrPatch(version, strict) }
}
if let version = VersionNumber.make(from: constraint, type: .tildeVersionRange) {
// Tilde range means that most specific digit is used as the basis.
return self.versions.filter {
version.patch != nil
// If a patch is provided then the minor version cannot be bumped.
? $0.hasSameMajorAndMinorButNewerOrSamePatch(version, strict)
// If a patch is not provided then the major version cannot be bumped.
: $0.hasSameMajorButNewerOrSameMinor(version, strict)
}
}
if let version = VersionNumber.make(from: constraint, type: .greaterThanOrEqual) {
return self.versions.filter { $0.isSameAs(version, strict) || $0.isNewerThan(version, strict) }
}
if let version = VersionNumber.make(from: constraint, type: .greaterThan) {
return self.versions.filter { $0.isNewerThan(version, strict) }
}
if let version = VersionNumber.make(from: constraint, type: .smallerThanOrEqual) {
return self.versions.filter { $0.isSameAs(version, strict) || $0.isOlderThan(version, strict)}
}
if let version = VersionNumber.make(from: constraint, type: .smallerThan) {
return self.versions.filter { $0.isOlderThan(version, strict)}
}
return []
}
}
/**
A version number that is (mostly) compatible with the semantic versioning standard.
For more information about semantic versioning, see: https://semver.org/
- Note: If you want to check version constraints for PHP versions, please see `PhpVersionNumberCollection`.
*/
public struct VersionNumber: Equatable, Hashable {
let major: Int
let minor: Int

View File

@ -8,6 +8,11 @@
import Foundation
/**
This class is responsible for handling the state of Valet throughout PHP Monitor. A singleton instance is created
and accessible throughout the lifecycle of the app, unless the user has decided to not use Valet. In that case,
only a restricted subset of functionality is available in the app.
*/
class Valet {
enum FeatureFlag {
@ -189,6 +194,9 @@ class Valet {
}
}
/**
Determine if any platform issues are detected when running `valet --version`.
*/
public func hasPlatformIssues() async -> Bool {
return await Shell.pipe("valet --version")
.out.contains("Composer detected issues in your platform")