mirror of
https://github.com/nicoverbruggen/phpmon.git
synced 2025-11-07 21:20:07 +01:00
👌 Shell tweaks, fix ComposerWindow async issue
This commit is contained in:
15
phpmon/Common/Extensions/TimeIntervalExtension.swift
Normal file
15
phpmon/Common/Extensions/TimeIntervalExtension.swift
Normal file
@@ -0,0 +1,15 @@
|
||||
//
|
||||
// TimeExtension.swift
|
||||
// PHP Monitor
|
||||
//
|
||||
// Created by Nico Verbruggen on 29/09/2022.
|
||||
// Copyright © 2022 Nico Verbruggen. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
extension TimeInterval {
|
||||
public static func minutes(_ amount: Int) -> TimeInterval {
|
||||
return Double(amount * 60)
|
||||
}
|
||||
}
|
||||
@@ -8,8 +8,7 @@
|
||||
|
||||
import Foundation
|
||||
|
||||
class ComposerWindow {
|
||||
|
||||
@MainActor class ComposerWindow {
|
||||
private var menu: MainMenu?
|
||||
private var shouldNotify: Bool! = nil
|
||||
private var completion: ((Bool) -> Void)! = nil
|
||||
@@ -42,39 +41,37 @@ class ComposerWindow {
|
||||
|
||||
window?.setType(info: true)
|
||||
|
||||
DispatchQueue.global(qos: .userInitiated).async { [self] in
|
||||
let task = LegacyShell.user.createTask(
|
||||
for: "\(Paths.composer!) global update", requiresPath: true
|
||||
)
|
||||
Task { await performComposerUpdate() }
|
||||
}
|
||||
|
||||
private func performComposerUpdate() async {
|
||||
do {
|
||||
let command = "\(Paths.composer!) global update"
|
||||
|
||||
DispatchQueue.main.async {
|
||||
self.window?.addToConsole("\(Paths.composer!) global update\n")
|
||||
self.window?.addToConsole("\(command)\n")
|
||||
}
|
||||
|
||||
task.listen(
|
||||
didReceiveStandardOutputData: { [weak self] string in
|
||||
DispatchQueue.main.async {
|
||||
self?.window?.addToConsole(string)
|
||||
let (process, _) = try await Shell.attach(
|
||||
command,
|
||||
didReceiveOutput: { [weak self] output in
|
||||
if output.hasError {
|
||||
DispatchQueue.main.async { self?.window?.addToConsole(output.err) }
|
||||
}
|
||||
if !output.out.isEmpty {
|
||||
DispatchQueue.main.async { self?.window?.addToConsole(output.out) }
|
||||
}
|
||||
// Log.perf("\(string.trimmingCharacters(in: .newlines))")
|
||||
},
|
||||
didReceiveStandardErrorData: { [weak self] string in
|
||||
DispatchQueue.main.async {
|
||||
self?.window?.addToConsole(string)
|
||||
}
|
||||
// Log.perf("\(string.trimmingCharacters(in: .newlines))")
|
||||
}
|
||||
withTimeout: .minutes(5)
|
||||
)
|
||||
|
||||
task.launch()
|
||||
task.waitUntilExit()
|
||||
task.haltListening()
|
||||
|
||||
if task.terminationStatus <= 0 {
|
||||
composerUpdateSucceeded()
|
||||
} else {
|
||||
composerUpdateFailed()
|
||||
}
|
||||
if process.terminationStatus <= 0 {
|
||||
composerUpdateSucceeded()
|
||||
} else {
|
||||
composerUpdateFailed()
|
||||
}
|
||||
} catch {
|
||||
composerUpdateFailed()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -200,7 +200,7 @@ extension MainMenu {
|
||||
}
|
||||
}
|
||||
|
||||
@objc func updateGlobalComposerDependencies() {
|
||||
@MainActor @objc func updateGlobalComposerDependencies() {
|
||||
ComposerWindow().updateGlobalDependencies(
|
||||
notify: true,
|
||||
completion: { _ in }
|
||||
|
||||
@@ -58,7 +58,7 @@ protocol Shellable {
|
||||
_ command: String,
|
||||
didReceiveOutput: @escaping (ShellOutput) -> Void,
|
||||
withTimeout timeout: TimeInterval
|
||||
) async throws -> ShellOutput
|
||||
) async throws -> (Process, ShellOutput)
|
||||
}
|
||||
|
||||
enum ShellError: Error {
|
||||
|
||||
@@ -118,7 +118,7 @@ class SystemShell: Shellable {
|
||||
_ command: String,
|
||||
didReceiveOutput: @escaping (ShellOutput) -> Void,
|
||||
withTimeout timeout: TimeInterval = 5.0
|
||||
) async throws -> ShellOutput {
|
||||
) async throws -> (Process, ShellOutput) {
|
||||
let task = getShellProcess(for: command)
|
||||
|
||||
var allOut: String = ""
|
||||
@@ -139,10 +139,10 @@ class SystemShell: Shellable {
|
||||
timer?.invalidate()
|
||||
|
||||
if !allErr.isEmpty {
|
||||
return continuation.resume(returning: .err(allErr))
|
||||
return continuation.resume(returning: (process, .err(allErr)))
|
||||
}
|
||||
|
||||
return continuation.resume(returning: .out(allOut))
|
||||
return continuation.resume(returning: (process, .out(allOut)))
|
||||
}
|
||||
|
||||
timer = Timer.scheduledTimer(withTimeInterval: timeout, repeats: false) { _ in
|
||||
|
||||
@@ -29,8 +29,8 @@ public class TestableShell: Shellable {
|
||||
_ command: String,
|
||||
didReceiveOutput: @escaping (ShellOutput) -> Void,
|
||||
withTimeout timeout: TimeInterval
|
||||
) async throws -> ShellOutput {
|
||||
self.sync(command)
|
||||
) async throws -> (Process, ShellOutput) {
|
||||
return (Process(), self.sync(command))
|
||||
}
|
||||
|
||||
func sync(_ command: String) -> ShellOutput {
|
||||
|
||||
Reference in New Issue
Block a user