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

Compare commits

...

14 Commits
v5.6 ... v5.6.2

Author SHA1 Message Date
45704fc736 🚀 Version 5.6.2 2022-10-02 13:28:58 +02:00
f28354e634 🐛 Use valet secure sitename (#197) 2022-10-02 13:28:01 +02:00
8055a32bde 🐛 Fix ComposerWindow deinit not firing 2022-09-29 18:50:40 +02:00
5b3054326e 🔧 Bump version number 2022-09-28 18:24:26 +02:00
e7f3c7e59c 🐛 Fix an issue with missing separator item 2022-09-28 18:24:01 +02:00
a407515534 🚀 Version 5.6.1 2022-09-24 12:56:14 +02:00
b827ffb869 🔧 Bump version number 2022-09-23 16:46:23 +02:00
bdb718598e 🐛 Various bugfixes
- Fixes issue with `scanApps` being non-optional in custom configuration
- Fixes issue with position of separator if Xdebug is not detected
- Ensure that `isRunningSwiftUIPreview` modifier always return false for debug builds
2022-09-23 16:46:13 +02:00
ddfc73e033 🐛 Resolve issue with determining PATH (#194)
In previous builds, PHP Monitor would use interactive mode when opening
a /bin/zsh shell, in order to be able to load the full PATH.

This is a problem because when launching PHP Monitor via the command
line or when you have some interactivity in an actual interactive
shell, it is possible to get stuck waiting for a particular input
which will effectively 'freeze' PHP Monitor's shell.

There are two options to fix this:
1) work with a timeout, which may or may not return a PATH
2) use a non-interactive shell and source .zshrc

I chose option 2, which is the more robust choice. If no .zshrc file
exists, it is also not sourced to avoid warnings or errors from ending
up in the PATH.
2022-09-23 16:44:06 +02:00
cfae520984 👌 Correctly resolve tagged version (#195) 2022-09-22 18:43:09 +02:00
0c176493e5 🔀 Merge branch 'main' into dev/5.6 2022-09-18 14:08:48 +02:00
71da62f954 📝 Update contribution guidelines 2022-09-18 14:08:10 +02:00
d6781568a3 📝 Update README 2022-09-18 13:39:40 +02:00
c9c7e14416 👌 Add support for <= and < version constraints
I am entirely unsure why one would need these, but I figured I'd get
these in the app before I start the work on PHP Monitor 6.0.

This ensures all common version constraints can now be parsed correctly.
2022-09-18 00:05:37 +02:00
25 changed files with 197 additions and 34 deletions

23
.github/contributing.md vendored Normal file
View File

@ -0,0 +1,23 @@
# Contribution Guidelines
Thank you for your interest in contributing to PHP Monitor.
I consider this project a bit of a nice side-project to my daily gig, so it is very much a personal affair where I love to tinker around.
**While the code of the latest PHP Monitor release is public, many things are constantly in flux that may not be pushed to this repository yet.**
I don't mean to be rude, but I don't want other people involved with the project beyond simply contributing a few small things here and there, as has been the case in the past.
The extra mental overhead of having additional contributors to report to, whose code will need to be reviewed... it's a lot and it makes working on PHP Monitor less enjoyable for me.
Plus, at this point, the majority of PHP Monitor's main functionality is also done.
As a result, I may refer you to this file at some point. Again, I don't wish to be rude, but this general rule stands:
**Making any changes in a fork and opening a pull request without opening an issue first will most likely result in your PR being closed without mercy.**
To repeat, I am **not opposed** to small contributions and fixes, if they are **meaningful or insightful**.
To learn more, please check out the [pull request template](/.github/pull_request_template.md) which contains more information about my contribution requirements. (This will also show up when you open a new PR.)
Thank you for respecting this!

View File

@ -16,7 +16,7 @@ In short: It is usually best to *get in touch first* if you are making substanti
## About destination branches
Please keep in mind that `main` is reserved for the current code state of the latest release and should *never* be the destination branch unless a new release is happening. **Merge requests that target `main` will be closed without mercy.**
Please keep in mind that `main` is reserved for the current code state of the latest release and should *never* be the destination branch unless a new release is happening. **Pull requests that target `main` will be closed without mercy.**
Usually, the best target is the stable `dev/x.x` branch that corresponds with the latest major version that is released.

View File

@ -1741,7 +1741,7 @@
CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic;
COMBINE_HIDPI_IMAGES = YES;
CURRENT_PROJECT_VERSION = 965;
CURRENT_PROJECT_VERSION = 976;
DEAD_CODE_STRIPPING = YES;
DEBUG = YES;
DEVELOPMENT_TEAM = 8M54J5J787;
@ -1752,7 +1752,7 @@
"@executable_path/../Frameworks",
);
MACOSX_DEPLOYMENT_TARGET = 11.0;
MARKETING_VERSION = 5.6.0;
MARKETING_VERSION = 5.6.2;
PRODUCT_BUNDLE_IDENTIFIER = com.nicoverbruggen.phpmon;
PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = "";
@ -1769,7 +1769,7 @@
CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic;
COMBINE_HIDPI_IMAGES = YES;
CURRENT_PROJECT_VERSION = 965;
CURRENT_PROJECT_VERSION = 976;
DEAD_CODE_STRIPPING = YES;
DEBUG = NO;
DEVELOPMENT_TEAM = 8M54J5J787;
@ -1780,7 +1780,7 @@
"@executable_path/../Frameworks",
);
MACOSX_DEPLOYMENT_TARGET = 11.0;
MARKETING_VERSION = 5.6.0;
MARKETING_VERSION = 5.6.2;
PRODUCT_BUNDLE_IDENTIFIER = com.nicoverbruggen.phpmon;
PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = "";

View File

@ -1,5 +1,5 @@
> **Note**
> If this software has been useful to you, I ask that you **please star the repository**, that way I know that the software is being used. Also, please consider leaving [a one-time donation](https://nicoverbruggen.be/sponsor) to support the project, as this is something I make in my free time. **Thank you!** ⭐️
> If this software has been useful to you, I ask that you **please star the repository**, that way I know that the software is being used. Also, please consider [sponsoring](https://nicoverbruggen.be/sponsor) to support the project, as this is something I make in my free time. **Thank you!** ⭐️
<p align="center"><img src="./docs/logo.png" alt="PHP Monitor Logo" width="500px" /></p>

View File

@ -18,4 +18,30 @@ class AppUpdaterCheckTest: XCTestCase {
XCTAssertNotNil(version)
}
func testTaggedReleaseOmitsZeroPatch() {
let version = AppVersion.from("3.5.0_333")!
XCTAssertEqual(version.tagged, "3.5")
XCTAssertEqual(version.version, "3.5.0")
}
func testTaggedReleaseDoesntOmitNonZeroPatch() {
let version = AppVersion.from("3.5.1_333")!
XCTAssertEqual(version.tagged, "3.5.1")
XCTAssertEqual(version.version, "3.5.1")
}
func testTagTruncationDoesntAffectMajorVersions() {
var version = AppVersion.from("5.0_333")!
XCTAssertEqual(version.tagged, "5.0")
XCTAssertEqual(version.version, "5.0")
version = AppVersion.from("5.0.0_333")!
XCTAssertEqual(version.tagged, "5.0")
XCTAssertEqual(version.version, "5.0.0")
}
}

View File

@ -8,6 +8,7 @@
import XCTest
// swiftlint:disable type_body_length
class PhpVersionNumberTest: XCTestCase {
func testCanDeconstructPhpVersion() throws {
@ -287,4 +288,76 @@ class PhpVersionNumberTest: XCTestCase {
.make(from: ["7.3.1", "7.2.9"]).all
)
}
func testCanCheckLessThanOrEqualConstraints() throws {
XCTAssertEqual(
PhpVersionNumberCollection
.make(from: ["7.4", "7.3", "7.2", "7.1", "7.0"])
.matching(constraint: "<=7.2", strict: true),
PhpVersionNumberCollection
.make(from: ["7.2", "7.1", "7.0"]).all
)
XCTAssertEqual(
PhpVersionNumberCollection
.make(from: ["7.4", "7.3", "7.2", "7.1", "7.0"])
.matching(constraint: "<=7.2.0", strict: true),
PhpVersionNumberCollection
.make(from: ["7.2", "7.1", "7.0"]).all
)
// Strict check (>7.2.5 is too new for 7.2 which resolves to 7.2.0)
XCTAssertEqual(
PhpVersionNumberCollection
.make(from: ["7.4", "7.3", "7.2", "7.1", "7.0"])
.matching(constraint: "<=7.2.5", strict: true),
PhpVersionNumberCollection
.make(from: ["7.2", "7.1", "7.0"]).all
)
// Non-strict check (ignoring patch has no effect)
XCTAssertEqual(
PhpVersionNumberCollection
.make(from: ["7.4", "7.3", "7.2", "7.1", "7.0"])
.matching(constraint: "<=7.2.5", strict: false),
PhpVersionNumberCollection
.make(from: ["7.2", "7.1", "7.0"]).all
)
}
func testCanCheckLessThanConstraints() throws {
XCTAssertEqual(
PhpVersionNumberCollection
.make(from: ["7.4", "7.3", "7.2", "7.1", "7.0"])
.matching(constraint: "<7.2", strict: true),
PhpVersionNumberCollection
.make(from: ["7.1", "7.0"]).all
)
XCTAssertEqual(
PhpVersionNumberCollection
.make(from: ["7.4", "7.3", "7.2", "7.1", "7.0"])
.matching(constraint: "<7.2.0", strict: true),
PhpVersionNumberCollection
.make(from: ["7.1", "7.0"]).all
)
// Strict check (>7.2.5 is too new for 7.2 which resolves to 7.2.0)
XCTAssertEqual(
PhpVersionNumberCollection
.make(from: ["7.4", "7.3", "7.2", "7.1", "7.0"])
.matching(constraint: "<7.2.5", strict: true),
PhpVersionNumberCollection
.make(from: ["7.2", "7.1", "7.0"]).all
)
// Non-strict check (patch resolves to 7.2.999, which is bigger than 7.2.5)
XCTAssertEqual(
PhpVersionNumberCollection
.make(from: ["7.4", "7.3", "7.2", "7.1", "7.0"])
.matching(constraint: "<7.2.5", strict: false),
PhpVersionNumberCollection
.make(from: ["7.1", "7.0"]).all
)
}
}

View File

@ -14,12 +14,18 @@ extension Shell {
let task = Process()
task.launchPath = "/bin/zsh"
// We need an interactive shell so the user's PATH is loaded in correctly
task.arguments = ["--login", "-ilc", "echo $PATH"]
let command = Filesystem.fileExists("~/.zshrc")
// source the user's .zshrc file if it exists to complete $PATH
? ". ~/.zshrc && echo $PATH"
// otherwise, non-interactive mode is sufficient
: "echo $PATH"
task.arguments = ["--login", "-lc", command]
let pipe = Pipe()
task.standardOutput = pipe
task.launch()
let data = pipe.fileHandleForReading.readDataToEndOfFile()
return String(data: data, encoding: String.Encoding.utf8) ?? ""

View File

@ -30,7 +30,7 @@ class PMWindowController: NSWindowController, NSWindowDelegate {
}
deinit {
Log.perf("Window controller '\(windowName)' was deinitialized")
Log.perf("deinit: \(String(describing: self)).\(#function)")
}
}

View File

@ -87,6 +87,14 @@ public struct PhpVersionNumberCollection: Equatable {
return self.versions.filter { $0.isNewerThan(version, strict) }
}
if let version = PhpVersionNumber.make(from: constraint, type: .smallerThanOrEqual) {
return self.versions.filter { $0.isSameAs(version, strict) || $0.isOlderThan(version, strict)}
}
if let version = PhpVersionNumber.make(from: constraint, type: .smallerThan) {
return self.versions.filter { $0.isOlderThan(version, strict)}
}
return []
}
}
@ -116,12 +124,8 @@ public struct PhpVersionNumber: Equatable, Hashable {
case tildeVersionRange = #"^~(?<major>\d+).(?<minor>\d+).?(?<patch>\d+)?\z"#
case greaterThanOrEqual = #"^>=(?<major>\d+).(?<minor>\d+).?(?<patch>\d+)?\z"#
case greaterThan = #"^>(?<major>\d+).(?<minor>\d+).?(?<patch>\d+)?\z"#
// TODO: (6.0) Handle these cases (even though I suspect these are uncommon)
/*
case smallerThanOrEqual = #"^<=(?<major>\d+).(?<minor>\d+).?(?<patch>\d+)?\z"#
case smallerThan = #"^<(?<major>\d+).(?<minor>\d+).?(?<patch>\d+)?\z"#
*/
}
public static func parse(_ text: String) throws -> Self {
@ -175,6 +179,15 @@ public struct PhpVersionNumber: Equatable, Hashable {
)
}
internal func isOlderThan(_ version: PhpVersionNumber, _ strict: Bool) -> Bool {
return (
self.major < version.major ||
self.major == version.major && self.minor < version.minor ||
self.major == version.major && self.minor == version.minor
&& self.patch(strict) < version.patch(strict)
)
}
internal func hasNewerMinorVersionOrPatch(_ version: PhpVersionNumber, _ strict: Bool) -> Bool {
return self.major == version.major &&
(

View File

@ -65,7 +65,7 @@ class AppDelegate: NSObject, NSApplicationDelegate, UNUserNotificationCenterDele
override init() {
logger.verbosity = .info
#if DEBUG
// logger.verbosity = .performance
logger.verbosity = .performance
#endif
if CommandLine.arguments.contains("--v") {
logger.verbosity = .performance

View File

@ -146,8 +146,9 @@ class AppUpdateChecker {
text: "updater.alerts.buttons.release_notes".localized,
action: { vc in
vc.close(with: .OK)
NSWorkspace.shared.open(
Constants.Urls.GitHubReleases.appendingPathComponent("/tag/v\(version.version)\(devSuffix)")
Constants.Urls.GitHubReleases.appendingPathComponent("/tag/v\(version.tagged)\(devSuffix)")
)
}
)

View File

@ -66,6 +66,14 @@ class AppVersion {
return AppVersion.from("\(App.shortVersion)_\(App.bundleVersion)")!
}
var tagged: String {
if version.suffix(2) == ".0" && version.count > 3 {
return String(version.dropLast(2))
}
return version
}
var computerReadable: String {
return "\(version)_\(build ?? "0")"
}

View File

@ -47,7 +47,7 @@ extension DomainListVC {
let originalSecureStatus = selectedSite!.secured
let action = selectedSite!.secured ? "unsecure" : "secure"
let selectedSite = selectedSite!
let command = "cd '\(selectedSite.absolutePath)' && sudo \(Paths.valet) \(action) && exit;"
let command = "sudo \(Paths.valet) \(action) '\(selectedSite.name)' && exit;"
waitAndExecute {
Shell.run(command, requiresPath: true)

View File

@ -292,6 +292,6 @@ class DomainListVC: NSViewController, NSTableViewDelegate, NSTableViewDataSource
// MARK: - Deinitialization
deinit {
Log.perf("DomainListVC deallocated")
Log.perf("deinit: \(String(describing: self)).\(#function)")
}
}

View File

@ -52,15 +52,15 @@ class ComposerWindow {
}
task.listen(
didReceiveStandardOutputData: { string in
didReceiveStandardOutputData: { [weak self] string in
DispatchQueue.main.async {
self.window?.addToConsole(string)
self?.window?.addToConsole(string)
}
// Log.perf("\(string.trimmingCharacters(in: .newlines))")
},
didReceiveStandardErrorData: { string in
didReceiveStandardErrorData: { [weak self] string in
DispatchQueue.main.async {
self.window?.addToConsole(string)
self?.window?.addToConsole(string)
}
// Log.perf("\(string.trimmingCharacters(in: .newlines))")
}
@ -91,6 +91,7 @@ class ComposerWindow {
}
window = nil
removeBusyStatus()
menu = nil
completion(true)
}
}
@ -103,6 +104,7 @@ class ComposerWindow {
window?.progressView?.labelDescription.stringValue = "alert.composer_failure.info".localized
window = nil
removeBusyStatus()
menu = nil
completion(false)
}
}
@ -128,4 +130,8 @@ class ComposerWindow {
.withPrimary(text: "OK")
.show()
}
deinit {
Log.perf("deinit: \(String(describing: self)).\(#function)")
}
}

View File

@ -155,11 +155,11 @@ extension MainMenu {
App.shared.detectedApplications = Application.detectPresetApplications()
let customApps = Preferences.custom.scanApps.map { appName in
let customApps = Preferences.custom.scanApps?.map { appName in
return Application(appName, .user_supplied)
}.filter { app in
return app.isInstalled()
}
} ?? []
App.shared.detectedApplications.append(contentsOf: customApps)

View File

@ -212,18 +212,19 @@ extension StatusMenu {
func addXdebugMenuItem() {
if !Xdebug.enabled {
addItem(NSMenuItem.separator())
return
}
addItems([
NSMenuItem.separator(),
NSMenuItem(title: "mi_xdebug_mode".localized, submenu: [
HeaderView.asMenuItem(text: "mi_xdebug_available_modes".localized)
] + Xdebug.asMenuItems() + [
HeaderView.asMenuItem(text: "mi_xdebug_actions".localized),
NSMenuItem(title: "mi_xdebug_disable_all".localized,
action: #selector(MainMenu.disableAllXdebugModes))
], target: MainMenu.shared)
], target: MainMenu.shared),
NSMenuItem.separator()
], target: MainMenu.shared)
}

View File

@ -48,8 +48,9 @@ class StatusMenu: NSMenu {
if Preferences.isEnabled(.displayExtensions) {
addExtensionsMenuItems()
addXdebugMenuItem()
NSMenuItem.separator()
addXdebugMenuItem()
}
addPhpDoctorMenuItem()

View File

@ -47,7 +47,7 @@ class BetterAlertVC: NSViewController {
}
deinit {
Log.perf("A BetterAlert has been deinitialized.")
Log.perf("deinit: \(String(describing: self)).\(#function)")
}
// MARK: Outlet Actions

View File

@ -9,7 +9,7 @@
import Foundation
struct CustomPrefs: Decodable {
let scanApps: [String]
let scanApps: [String]?
let presets: [Preset]?
let services: [String]?
let environmentVariables: [String: String]?

View File

@ -25,7 +25,7 @@ class GenericPreferenceVC: NSViewController {
// MARK: - Deinitialization
deinit {
Log.perf("PrefsVC deallocated")
Log.perf("deinit: \(String(describing: self)).\(#function)")
}
func getDynamicIconPV() -> NSView {

View File

@ -18,7 +18,7 @@ class ProgressViewController: NSViewController {
@IBOutlet weak var imageViewType: NSImageView!
deinit {
Log.perf("Deinitializing ProgressViewController")
Log.perf("deinit: \(String(describing: self)).\(#function)")
}
}

View File

@ -56,7 +56,7 @@ class TerminalProgressWindowController: NSWindowController, NSWindowDelegate {
}
deinit {
Log.perf("Deinitializing ProgressWindowController")
Log.perf("deinit: \(String(describing: self)).\(#function)")
}
}

View File

@ -10,8 +10,13 @@ import Foundation
import SwiftUI
var isRunningSwiftUIPreview: Bool {
return ProcessInfo.processInfo
.environment["XCODE_RUNNING_FOR_PREVIEWS"] != nil
#if DEBUG
// If running SwiftUI *and* when debugging
return ProcessInfo.processInfo.environment["XCODE_RUNNING_FOR_PREVIEWS"] != nil
#else
// Release builds should always return false here
return false
#endif
}
extension Color {

View File

@ -68,7 +68,7 @@ class PhpConfigWatcher {
}
deinit {
Log.perf("A PhpConfigWatcher has been deinitialized.")
Log.perf("deinit: \(String(describing: self)).\(#function)")
}
}