From c6ce1e6f7763d45eba242b3f3b7a2b44211da82e Mon Sep 17 00:00:00 2001 From: ohaiibuzzle <23693150+ohaiibuzzle@users.noreply.github.com> Date: Tue, 13 Jun 2023 21:01:18 +0700 Subject: [PATCH 1/2] feat: New logging engine (also serve as an example for Isaac on Actors) --- Harbor.xcodeproj/project.pbxproj | 4 ++++ Harbor/Models/HarborBottle.swift | 20 ++++++++++++++++++ Harbor/Models/Logger.swift | 35 ++++++++++++++++++++++++++++++++ 3 files changed, 59 insertions(+) create mode 100644 Harbor/Models/Logger.swift diff --git a/Harbor.xcodeproj/project.pbxproj b/Harbor.xcodeproj/project.pbxproj index 305542e..1fc12f3 100644 --- a/Harbor.xcodeproj/project.pbxproj +++ b/Harbor.xcodeproj/project.pbxproj @@ -22,6 +22,7 @@ AB6A967F2A31045A003A019E /* SetupView.swift in Sources */ = {isa = PBXBuildFile; fileRef = AB6A967E2A31045A003A019E /* SetupView.swift */; }; AB7A81002A30CC7100AA71A6 /* BrewUtils.swift in Sources */ = {isa = PBXBuildFile; fileRef = AB7A80FF2A30CC7100AA71A6 /* BrewUtils.swift */; }; AB7A81022A30D2FE00AA71A6 /* HarborUtils.swift in Sources */ = {isa = PBXBuildFile; fileRef = AB7A81012A30D2FE00AA71A6 /* HarborUtils.swift */; }; + AB7F9D182A38AC58003014D8 /* Logger.swift in Sources */ = {isa = PBXBuildFile; fileRef = AB7F9D172A38AC58003014D8 /* Logger.swift */; }; ABC0BFCE2A31627400382A42 /* BottleManagementView.swift in Sources */ = {isa = PBXBuildFile; fileRef = ABC0BFCD2A31627400382A42 /* BottleManagementView.swift */; }; ABC0BFD12A31629300382A42 /* HarborBottle.swift in Sources */ = {isa = PBXBuildFile; fileRef = ABC0BFD02A31629300382A42 /* HarborBottle.swift */; }; ABC0BFD42A31691500382A42 /* BottleOpsDropdown.swift in Sources */ = {isa = PBXBuildFile; fileRef = ABC0BFD32A31691500382A42 /* BottleOpsDropdown.swift */; }; @@ -50,6 +51,7 @@ AB6A967E2A31045A003A019E /* SetupView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SetupView.swift; sourceTree = ""; }; AB7A80FF2A30CC7100AA71A6 /* BrewUtils.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BrewUtils.swift; sourceTree = ""; }; AB7A81012A30D2FE00AA71A6 /* HarborUtils.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HarborUtils.swift; sourceTree = ""; }; + AB7F9D172A38AC58003014D8 /* Logger.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Logger.swift; sourceTree = ""; }; ABC0BFCD2A31627400382A42 /* BottleManagementView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BottleManagementView.swift; sourceTree = ""; }; ABC0BFD02A31629300382A42 /* HarborBottle.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HarborBottle.swift; sourceTree = ""; }; ABC0BFD32A31691500382A42 /* BottleOpsDropdown.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BottleOpsDropdown.swift; sourceTree = ""; }; @@ -166,6 +168,7 @@ isa = PBXGroup; children = ( ABC0BFD02A31629300382A42 /* HarborBottle.swift */, + AB7F9D172A38AC58003014D8 /* Logger.swift */, ); path = Models; sourceTree = ""; @@ -289,6 +292,7 @@ ABD56AB42A36E419002A439C /* GPKFastInstallView.swift in Sources */, FC682EDA2A35FD57000C53D6 /* Environment+GPKUtils.swift in Sources */, AB7A81002A30CC7100AA71A6 /* BrewUtils.swift in Sources */, + AB7F9D182A38AC58003014D8 /* Logger.swift in Sources */, AB6652CD2A3350EC00F3FC5D /* BottleConfigDropdown.swift in Sources */, AB5CC6D62A30910300AEBB2B /* GPKUtils.swift in Sources */, AB3BE5EE2A32248D00358BBC /* LaunchExtDropdown.swift in Sources */, diff --git a/Harbor/Models/HarborBottle.swift b/Harbor/Models/HarborBottle.swift index 005930f..b5cfa04 100644 --- a/Harbor/Models/HarborBottle.swift +++ b/Harbor/Models/HarborBottle.swift @@ -21,6 +21,8 @@ struct HarborBottle: Identifiable, Equatable, Codable { func launchApplication(_ application: String, arguments: [String] = [], workDir: String = "") { let task = Process() + let logger = Logger() + task.launchPath = "/usr/local/opt/game-porting-toolkit/bin/wine64" task.arguments = ["start"] @@ -48,6 +50,19 @@ struct HarborBottle: Identifiable, Equatable, Codable { if pleaseShutUp { task.standardOutput = nil task.standardError = nil + } else { + let pipe = Pipe() + task.standardOutput = pipe + task.standardError = pipe + + pipe.fileHandleForReading.readabilityHandler = { handle in + let data = handle.availableData + if let output = String(data: data, encoding: .utf8) { + Task.detached { + await logger.log(output) + } + } + } } do { @@ -55,6 +70,11 @@ struct HarborBottle: Identifiable, Equatable, Codable { } catch { HarborUtils.shared.quickError(error.localizedDescription) } + + Task(priority: .background) { + task.waitUntilExit() + await logger.dump() + } } func launchExtApplication(_ application: String, arguments: [String] = [], workDir: String = "") { diff --git a/Harbor/Models/Logger.swift b/Harbor/Models/Logger.swift new file mode 100644 index 0000000..35f7e3c --- /dev/null +++ b/Harbor/Models/Logger.swift @@ -0,0 +1,35 @@ +// +// Logger.swift +// Harbor +// +// Created by Venti on 13/06/2023. +// + +import Foundation + +actor Logger { + var logContent: [String] = [] + + func log(_ message: String) { + logContent.append(message) + } + + func dump() { + for message in logContent { + print(message) + } + } + + func clear() { + logContent = [] + } + + func save() { + let logFile = HarborUtils.shared.getContainerHome().appendingPathComponent("log.txt") + do { + try logContent.joined(separator: "\n").write(to: logFile, atomically: true, encoding: .utf8) + } catch { + print("Failed to save log file") + } + } +} From 0fe56537a44e76fd67ddc14203186411ab9f3bd5 Mon Sep 17 00:00:00 2001 From: ohaiibuzzle <23693150+ohaiibuzzle@users.noreply.github.com> Date: Tue, 13 Jun 2023 21:46:17 +0700 Subject: [PATCH 2/2] fix: log straight to disk --- Harbor/Models/HarborBottle.swift | 22 +++-------- Harbor/Models/Logger.swift | 37 +++++++++++-------- .../BottleManagement/LaunchExtDropdown.swift | 5 +-- 3 files changed, 29 insertions(+), 35 deletions(-) diff --git a/Harbor/Models/HarborBottle.swift b/Harbor/Models/HarborBottle.swift index b5cfa04..02e25b0 100644 --- a/Harbor/Models/HarborBottle.swift +++ b/Harbor/Models/HarborBottle.swift @@ -19,7 +19,8 @@ struct HarborBottle: Identifiable, Equatable, Codable { var enableESync: Bool = false var pleaseShutUp: Bool = true - func launchApplication(_ application: String, arguments: [String] = [], workDir: String = "") { + func launchApplication(_ application: String, arguments: [String] = [], + workDir: String = "", isUnixPath: Bool = false) { let task = Process() let logger = Logger() @@ -31,6 +32,9 @@ struct HarborBottle: Identifiable, Equatable, Codable { task.arguments?.append(workDir) } + if isUnixPath { + task.arguments?.append("/unix") + } task.arguments?.append(application) if !arguments.isEmpty { @@ -70,24 +74,10 @@ struct HarborBottle: Identifiable, Equatable, Codable { } catch { HarborUtils.shared.quickError(error.localizedDescription) } - - Task(priority: .background) { - task.waitUntilExit() - await logger.dump() - } } func launchExtApplication(_ application: String, arguments: [String] = [], workDir: String = "") { - // if the app is not inside the bottle, we copy it to bottle's drive_c - if isAppOutsideBottle(application) { - do { - try FileManager.default.copyItem(atPath: application, toPath: "\(path.path)/drive_c/\(application)") - } catch { - NSLog("Failed to copy \(application) to \(path.path)/drive_c/\(application)") - } - } - let newApplication = "C:\\\(application)" - launchApplication(newApplication, arguments: arguments) + launchApplication(application, arguments: arguments, workDir: workDir, isUnixPath: true) } func launchPrimaryApplication() { diff --git a/Harbor/Models/Logger.swift b/Harbor/Models/Logger.swift index 35f7e3c..6ae1016 100644 --- a/Harbor/Models/Logger.swift +++ b/Harbor/Models/Logger.swift @@ -8,28 +8,33 @@ import Foundation actor Logger { - var logContent: [String] = [] + // File handle to log directly to disk + private var fileHandle: FileHandle? - func log(_ message: String) { - logContent.append(message) - } - - func dump() { - for message in logContent { - print(message) + init() { + do { + let logFile = HarborUtils.shared.getContainerHome().appendingPathComponent("harbor.log") + FileManager.default.createFile(atPath: logFile.path, contents: nil, attributes: nil) + fileHandle = try FileHandle(forWritingTo: logFile) + } catch { + print("Failed to create log file") } } - func clear() { - logContent = [] + deinit { + fileHandle?.closeFile() } - func save() { - let logFile = HarborUtils.shared.getContainerHome().appendingPathComponent("log.txt") - do { - try logContent.joined(separator: "\n").write(to: logFile, atomically: true, encoding: .utf8) - } catch { - print("Failed to save log file") + func log(_ message: String) { + if !message.isEmpty { + let dateFormatter = DateFormatter() + dateFormatter.dateFormat = "yyyy-MM-dd HH:mm:ss.SSS" + let timestamp = dateFormatter.string(from: Date()) + let logMessage = "\(timestamp) \(message)" + print(logMessage) + if let logMessageData = logMessage.data(using: .utf8) { + fileHandle?.write(logMessageData) + } } } } diff --git a/Harbor/UIElements/BottleManagement/LaunchExtDropdown.swift b/Harbor/UIElements/BottleManagement/LaunchExtDropdown.swift index b8e0f5b..552c742 100644 --- a/Harbor/UIElements/BottleManagement/LaunchExtDropdown.swift +++ b/Harbor/UIElements/BottleManagement/LaunchExtDropdown.swift @@ -90,9 +90,8 @@ struct LaunchExtDropdown: View { isPresented = false } Button("btn.launch") { - bottle.launchApplication(applicationPath, - arguments: bottle.primaryApplicationArgument - .split(separator: " ").map { String($0) }, + bottle.launchExtApplication(applicationPath, + arguments: applicationArgument.components(separatedBy: " "), workDir: applicationWorkDir) isPresented = false }