From bcf3dcc0c467c72c87ae6014adf7782262537ce2 Mon Sep 17 00:00:00 2001 From: Isaac Marovitz Date: Wed, 17 Jan 2024 20:35:52 -0500 Subject: [PATCH 01/19] Bump build --- Whisky.xcodeproj/project.pbxproj | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/Whisky.xcodeproj/project.pbxproj b/Whisky.xcodeproj/project.pbxproj index 8b5c73bfb..5de5d36f1 100644 --- a/Whisky.xcodeproj/project.pbxproj +++ b/Whisky.xcodeproj/project.pbxproj @@ -767,7 +767,7 @@ "CODE_SIGN_IDENTITY[sdk=macosx*]" = "Developer ID Application"; CODE_SIGN_STYLE = Manual; COMBINE_HIDPI_IMAGES = YES; - CURRENT_PROJECT_VERSION = 35; + CURRENT_PROJECT_VERSION = 36; DEVELOPMENT_ASSET_PATHS = "\"Whisky/Preview Content\""; DEVELOPMENT_TEAM = ""; "DEVELOPMENT_TEAM[sdk=macosx*]" = 92S3SG4PTH; @@ -785,7 +785,7 @@ "@executable_path/../Frameworks", ); MACOSX_DEPLOYMENT_TARGET = 14.0; - MARKETING_VERSION = 2.2.2; + MARKETING_VERSION = 2.2.3; PRODUCT_BUNDLE_IDENTIFIER = com.isaacmarovitz.Whisky; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE_SPECIFIER = ""; @@ -805,7 +805,7 @@ "CODE_SIGN_IDENTITY[sdk=macosx*]" = "Developer ID Application"; CODE_SIGN_STYLE = Manual; COMBINE_HIDPI_IMAGES = YES; - CURRENT_PROJECT_VERSION = 35; + CURRENT_PROJECT_VERSION = 36; DEVELOPMENT_ASSET_PATHS = "\"Whisky/Preview Content\""; DEVELOPMENT_TEAM = ""; "DEVELOPMENT_TEAM[sdk=macosx*]" = 92S3SG4PTH; @@ -823,7 +823,7 @@ "@executable_path/../Frameworks", ); MACOSX_DEPLOYMENT_TARGET = 14.0; - MARKETING_VERSION = 2.2.2; + MARKETING_VERSION = 2.2.3; PRODUCT_BUNDLE_IDENTIFIER = com.isaacmarovitz.Whisky; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE_SPECIFIER = ""; @@ -889,7 +889,7 @@ CODE_SIGN_ENTITLEMENTS = WhiskyThumbnail/WhiskyThumbnail.entitlements; "CODE_SIGN_IDENTITY[sdk=macosx*]" = "Developer ID Application"; CODE_SIGN_STYLE = Manual; - CURRENT_PROJECT_VERSION = 35; + CURRENT_PROJECT_VERSION = 36; DEVELOPMENT_TEAM = ""; "DEVELOPMENT_TEAM[sdk=macosx*]" = 92S3SG4PTH; ENABLE_HARDENED_RUNTIME = YES; @@ -905,7 +905,7 @@ "@executable_path/../../../../Frameworks", ); LOCALIZATION_PREFERS_STRING_CATALOGS = YES; - MARKETING_VERSION = 2.2.2; + MARKETING_VERSION = 2.2.3; PRODUCT_BUNDLE_IDENTIFIER = com.isaacmarovitz.Whisky.WhiskyThumbnail; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE_SPECIFIER = ""; @@ -923,7 +923,7 @@ CODE_SIGN_ENTITLEMENTS = WhiskyThumbnail/WhiskyThumbnail.entitlements; "CODE_SIGN_IDENTITY[sdk=macosx*]" = "Developer ID Application"; CODE_SIGN_STYLE = Manual; - CURRENT_PROJECT_VERSION = 35; + CURRENT_PROJECT_VERSION = 36; DEVELOPMENT_TEAM = ""; "DEVELOPMENT_TEAM[sdk=macosx*]" = 92S3SG4PTH; ENABLE_HARDENED_RUNTIME = YES; @@ -939,7 +939,7 @@ "@executable_path/../../../../Frameworks", ); LOCALIZATION_PREFERS_STRING_CATALOGS = YES; - MARKETING_VERSION = 2.2.2; + MARKETING_VERSION = 2.2.3; PRODUCT_BUNDLE_IDENTIFIER = com.isaacmarovitz.Whisky.WhiskyThumbnail; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE_SPECIFIER = ""; From af7bf8b8f953b8ff6d96e5718ca93c4ab585419b Mon Sep 17 00:00:00 2001 From: Isaac Marovitz <42140194+IsaacMarovitz@users.noreply.github.com> Date: Wed, 17 Jan 2024 23:11:36 -0500 Subject: [PATCH 02/19] Update bug.yml --- .github/ISSUE_TEMPLATE/bug.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/ISSUE_TEMPLATE/bug.yml b/.github/ISSUE_TEMPLATE/bug.yml index 336608f28..347144c36 100644 --- a/.github/ISSUE_TEMPLATE/bug.yml +++ b/.github/ISSUE_TEMPLATE/bug.yml @@ -37,8 +37,8 @@ body: attributes: label: What version of Whisky are you using? options: - - "2.2.2" - - "<2.2.2" + - "2.2.3" + - "<2.2.3" validations: required: true - type: dropdown From b099f633ae7465488472af9e9293e7ba7b2645b9 Mon Sep 17 00:00:00 2001 From: Isaac Marovitz Date: Wed, 24 Jan 2024 19:15:57 -0500 Subject: [PATCH 03/19] D3DM MSYNC Fix --- WhiskyKit/Sources/WhiskyKit/Whisky/BottleSettings.swift | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/WhiskyKit/Sources/WhiskyKit/Whisky/BottleSettings.swift b/WhiskyKit/Sources/WhiskyKit/Whisky/BottleSettings.swift index ffe9d8d59..7e05bf9de 100644 --- a/WhiskyKit/Sources/WhiskyKit/Whisky/BottleSettings.swift +++ b/WhiskyKit/Sources/WhiskyKit/Whisky/BottleSettings.swift @@ -279,6 +279,10 @@ public struct BottleSettings: Codable, Equatable { wineEnv.updateValue("1", forKey: "WINEESYNC") case .msync: wineEnv.updateValue("1", forKey: "WINEMSYNC") + // D3DM detects ESYNC and changes behaviour accordingly + // so we have to lie to it so that it doesn't break + // under MSYNC. Values hardcoded in lid3dshared.dylib + wineEnv.updateValue("1", forKey: "WINEESYNC") } if metalHud { From 0d77eeea41030de61ac66753b0c62b4c92cfb0e1 Mon Sep 17 00:00:00 2001 From: OHaiiBuzzle <23693150+ohaiibuzzle@users.noreply.github.com> Date: Thu, 25 Jan 2024 09:19:36 +0900 Subject: [PATCH 04/19] feat: basic process management (#793) --- Whisky.xcodeproj/project.pbxproj | 4 + Whisky/Localizable.xcstrings | 62 +++++++++- Whisky/Views/Bottle/BottleView.swift | 6 + .../Views/Bottle/RunningProcessesView.swift | 113 ++++++++++++++++++ 4 files changed, 184 insertions(+), 1 deletion(-) create mode 100644 Whisky/Views/Bottle/RunningProcessesView.swift diff --git a/Whisky.xcodeproj/project.pbxproj b/Whisky.xcodeproj/project.pbxproj index 5de5d36f1..a786023fb 100644 --- a/Whisky.xcodeproj/project.pbxproj +++ b/Whisky.xcodeproj/project.pbxproj @@ -56,6 +56,7 @@ 8C73E1342AF472FC00B6FB45 /* ProgramMenuView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8C73E1332AF472FC00B6FB45 /* ProgramMenuView.swift */; }; 8CB681E52AED7C6F0018D319 /* WhiskyKit in Resources */ = {isa = PBXBuildFile; fileRef = 8CB681E42AED7C6F0018D319 /* WhiskyKit */; }; 8CB681E72AED7CD00018D319 /* WhiskyKit in Frameworks */ = {isa = PBXBuildFile; productRef = 8CB681E62AED7CD00018D319 /* WhiskyKit */; }; + AB0BCABD2B61036E00E21C31 /* RunningProcessesView.swift in Sources */ = {isa = PBXBuildFile; fileRef = AB0BCABC2B61036E00E21C31 /* RunningProcessesView.swift */; }; DB696FC82AFAE5DA0037EB2F /* PinCreationView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB696FC72AFAE5DA0037EB2F /* PinCreationView.swift */; }; EB58FB552A499896002DC184 /* SemanticVersion in Frameworks */ = {isa = PBXBuildFile; productRef = EB58FB542A499896002DC184 /* SemanticVersion */; }; EEA5A2462A31DD65008274AE /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = EEA5A2452A31DD65008274AE /* AppDelegate.swift */; }; @@ -153,6 +154,7 @@ 6EFDF6652AAE303300EF622F /* Icons.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Icons.xcassets; sourceTree = ""; }; 8C73E1332AF472FC00B6FB45 /* ProgramMenuView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProgramMenuView.swift; sourceTree = ""; }; 8CB681E42AED7C6F0018D319 /* WhiskyKit */ = {isa = PBXFileReference; lastKnownFileType = wrapper; path = WhiskyKit; sourceTree = ""; }; + AB0BCABC2B61036E00E21C31 /* RunningProcessesView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RunningProcessesView.swift; sourceTree = ""; }; DB696FC72AFAE5DA0037EB2F /* PinCreationView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PinCreationView.swift; sourceTree = ""; }; EEA5A2452A31DD65008274AE /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; /* End PBXFileReference section */ @@ -248,6 +250,7 @@ 6E50D98429CDF25B008C39F6 /* BottleCreationView.swift */, 6E355E5729D78249002D83BE /* ConfigView.swift */, 6E182FC92B0BF64E00AADE81 /* WinetricksView.swift */, + AB0BCABC2B61036E00E21C31 /* RunningProcessesView.swift */, 6E17B6422AF3FD6E00831173 /* Pins */, ); path = Bottle; @@ -590,6 +593,7 @@ 6E50D98529CDF25B008C39F6 /* BottleCreationView.swift in Sources */, 6E182FCA2B0BF64E00AADE81 /* WinetricksView.swift in Sources */, 6330DD962B1B0EA4007A625A /* RenameView.swift in Sources */, + AB0BCABD2B61036E00E21C31 /* RunningProcessesView.swift in Sources */, 6E17B6492AF4118F00831173 /* EnvironmentArgView.swift in Sources */, 6E6C0CF42A419A7600356232 /* RosettaView.swift in Sources */, 6E6C0CF82A419A8C00356232 /* GPTKInstallView.swift in Sources */, diff --git a/Whisky/Localizable.xcstrings b/Whisky/Localizable.xcstrings index 3a8b0935f..62cfd582e 100644 --- a/Whisky/Localizable.xcstrings +++ b/Whisky/Localizable.xcstrings @@ -9439,6 +9439,56 @@ } } }, + "process.table.executable" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Executable" + } + } + } + }, + "process.table.kill" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Stop Process" + } + } + } + }, + "process.table.loading" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Fetching Processes" + } + } + } + }, + "process.table.pid" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Process ID" + } + } + } + }, + "process.table.refresh" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Refresh" + } + } + } + }, "program.add.blocklist" : { "localizations" : { "da" : { @@ -15025,6 +15075,16 @@ } } }, + "tab.processes" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Running Processes" + } + } + } + }, "tab.programs" : { "localizations" : { "da" : { @@ -16595,4 +16655,4 @@ } }, "version" : "1.0" -} \ No newline at end of file +} diff --git a/Whisky/Views/Bottle/BottleView.swift b/Whisky/Views/Bottle/BottleView.swift index 377b23702..243d15319 100644 --- a/Whisky/Views/Bottle/BottleView.swift +++ b/Whisky/Views/Bottle/BottleView.swift @@ -23,6 +23,7 @@ import WhiskyKit enum BottleStage { case config case programs + case processes } struct BottleView: View { @@ -52,6 +53,9 @@ struct BottleView: View { NavigationLink(value: BottleStage.config) { Label("tab.config", systemImage: "gearshape") } + NavigationLink(value: BottleStage.processes) { + Label("tab.processes", systemImage: "hockey.puck.circle") + } } .formStyle(.grouped) .scrollDisabled(true) @@ -128,6 +132,8 @@ struct BottleView: View { ProgramsView( bottle: bottle, path: $path ) + case .processes: + RunningProcessesView(bottle: bottle) } } .navigationDestination(for: Program.self) { program in diff --git a/Whisky/Views/Bottle/RunningProcessesView.swift b/Whisky/Views/Bottle/RunningProcessesView.swift new file mode 100644 index 000000000..b87cf0cd0 --- /dev/null +++ b/Whisky/Views/Bottle/RunningProcessesView.swift @@ -0,0 +1,113 @@ +// +// RunningProcessView.swift +// Whisky +// +// This file is part of Whisky. +// +// Whisky is free software: you can redistribute it and/or modify it under the terms +// of the GNU General Public License as published by the Free Software Foundation, +// either version 3 of the License, or (at your option) any later version. +// +// Whisky is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; +// without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +// See the GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License along with Whisky. +// If not, see https://www.gnu.org/licenses/. +// + +import SwiftUI +import WhiskyKit + +struct BottleProcess: Identifiable { + var id = UUID() + var pid: String + var procName: String +} + +struct RunningProcessesView: View { + @ObservedObject var bottle: Bottle + + @State private var processes = [BottleProcess]() + @State private var processSortOrder = [KeyPathComparator(\BottleProcess.pid)] + @State private var selectedProcess: BottleProcess.ID? + + var body: some View { + ZStack { + if !processes.isEmpty { + VStack { + Table(processes, selection: $selectedProcess, sortOrder: $processSortOrder) { + TableColumn("process.table.pid", value: \.pid) + TableColumn("process.table.executable", value: \.procName) + } + .frame(maxWidth: .infinity, maxHeight: .infinity) + + HStack { + Spacer() + Button("process.table.refresh") { + Task.detached(priority: .userInitiated) { + await fetchProcesses() + } + } + Button("process.table.kill") { + Task.detached(priority: .userInitiated) { + await killProcess() + } + } + } + .padding() + } + } else { + HStack(alignment: .center) { + Spacer() + VStack(alignment: .center) { + ProgressView() + .padding() + Text("process.table.loading") + } + Spacer() + } + } + } + .onAppear { + Task.detached(priority: .userInitiated) { + await fetchProcesses() + } + } + } + + func fetchProcesses() async { + var newProcessList = [BottleProcess]() + let output: String? + + do { + output = try await Wine.runWine(["tasklist.exe"], bottle: bottle) + } catch { + print("Error running tasklist.exe: \(error)") + output = "" + } + + let lines = output?.split(omittingEmptySubsequences: true, whereSeparator: \.isNewline) + for line in lines ?? [] { + let lineParts = line.split(separator: ",", omittingEmptySubsequences: true) + if lineParts.count > 1 { + let pid = String(lineParts[1]) + let procName = String(lineParts[0]) + newProcessList.append(BottleProcess(pid: pid, procName: procName)) + } + } + processes = newProcessList + } + + func killProcess() async { + if let thisProcess = processes.first(where: { $0.id == selectedProcess }) { + do { + try await Wine.runWine(["taskkill.exe", "/PID", thisProcess.pid, "/F"], bottle: bottle) + try await Task.sleep(nanoseconds: 2000) + } catch { + print("Error running taskkill.exe: \(error)") + } + await fetchProcesses() + } + } +} From e38646a05d1d6f5b665ecb372edeccbaf978a750 Mon Sep 17 00:00:00 2001 From: blackxfiied <41133734+blackxfiied@users.noreply.github.com> Date: Mon, 29 Jan 2024 12:38:53 +0800 Subject: [PATCH 05/19] Update Wine.swift (#799) Fix typo in backend of the word registry --- WhiskyKit/Sources/WhiskyKit/Wine/Wine.swift | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/WhiskyKit/Sources/WhiskyKit/Wine/Wine.swift b/WhiskyKit/Sources/WhiskyKit/Wine/Wine.swift index c523288a8..1a3976f28 100644 --- a/WhiskyKit/Sources/WhiskyKit/Wine/Wine.swift +++ b/WhiskyKit/Sources/WhiskyKit/Wine/Wine.swift @@ -256,7 +256,7 @@ extension Wine { case desktop = #"HKCU\Control Panel\Desktop"# } - private static func addRegistyKey( + private static func addRegistryKey( bottle: Bottle, key: String, name: String, data: String, type: RegistryType ) async throws { try await runWine( @@ -265,7 +265,7 @@ extension Wine { ) } - private static func queryRegistyKey( + private static func queryRegistryKey( bottle: Bottle, key: String, name: String, type: RegistryType ) async throws -> String? { let output = try await runWine(["reg", "query", key, "-v", name], bottle: bottle) @@ -278,9 +278,9 @@ extension Wine { } public static func changeBuildVersion(bottle: Bottle, version: Int) async throws { - try await addRegistyKey(bottle: bottle, key: RegistryKey.currentVersion.rawValue, + try await addRegistryKey(bottle: bottle, key: RegistryKey.currentVersion.rawValue, name: "CurrentBuild", data: "\(version)", type: .string) - try await addRegistyKey(bottle: bottle, key: RegistryKey.currentVersion.rawValue, + try await addRegistryKey(bottle: bottle, key: RegistryKey.currentVersion.rawValue, name: "CurrentBuildNumber", data: "\(version)", type: .string) } @@ -300,7 +300,7 @@ extension Wine { } public static func buildVersion(bottle: Bottle) async throws -> String? { - return try await Wine.queryRegistyKey( + return try await Wine.queryRegistryKey( bottle: bottle, key: RegistryKey.currentVersion.rawValue, name: "CurrentBuild", type: .string ) @@ -308,7 +308,7 @@ extension Wine { public static func retinaMode(bottle: Bottle) async throws -> Bool { let values: Set = ["y", "n"] - guard let output = try await Wine.queryRegistyKey( + guard let output = try await Wine.queryRegistryKey( bottle: bottle, key: RegistryKey.macDriver.rawValue, name: "RetinaMode", type: .string ), values.contains(output) else { try await changeRetinaMode(bottle: bottle, retinaMode: false) @@ -318,14 +318,14 @@ extension Wine { } public static func changeRetinaMode(bottle: Bottle, retinaMode: Bool) async throws { - try await Wine.addRegistyKey( + try await Wine.addRegistryKey( bottle: bottle, key: RegistryKey.macDriver.rawValue, name: "RetinaMode", data: retinaMode ? "y" : "n", type: .string ) } public static func dpiResolution(bottle: Bottle) async throws -> Int? { - guard let output = try await Wine.queryRegistyKey(bottle: bottle, key: RegistryKey.desktop.rawValue, + guard let output = try await Wine.queryRegistryKey(bottle: bottle, key: RegistryKey.desktop.rawValue, name: "LogPixels", type: .dword ) else { return nil } @@ -336,7 +336,7 @@ extension Wine { } public static func changeDpiResolution(bottle: Bottle, dpi: Int) async throws { - try await Wine.addRegistyKey( + try await Wine.addRegistryKey( bottle: bottle, key: RegistryKey.desktop.rawValue, name: "LogPixels", data: String(dpi), type: .dword ) From 512b7597de022570c3a6e16f6b9f975bf236ec69 Mon Sep 17 00:00:00 2001 From: Joshua Brest <36625023+JoshuaBrest@users.noreply.github.com> Date: Wed, 6 Mar 2024 04:13:52 -0800 Subject: [PATCH 06/19] Delete logs older than 7 days (#784) * Add localization for "Delete Old Logs" and implement functionality to delete logs older than 7 days * Code cleanup * Remove extension * SwiftLint --------- Co-authored-by: Isaac Marovitz --- Whisky/Views/WhiskyApp.swift | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/Whisky/Views/WhiskyApp.swift b/Whisky/Views/WhiskyApp.swift index bb16bc6ba..bfe460075 100644 --- a/Whisky/Views/WhiskyApp.swift +++ b/Whisky/Views/WhiskyApp.swift @@ -40,6 +40,10 @@ struct WhiskyApp: App { .environmentObject(BottleVM.shared) .onAppear { NSWindow.allowsAutomaticWindowTabbing = false + + Task.detached { + await WhiskyApp.deleteOldLogs() + } } } // Don't ask me how this works, it just does @@ -129,6 +133,38 @@ struct WhiskyApp: App { NSWorkspace.shared.selectFile(nil, inFileViewerRootedAtPath: Wine.logsFolder.path) } + static func deleteOldLogs() { + let pastDate = Date().addingTimeInterval(-7 * 24 * 60 * 60) + + guard let urls = try? FileManager.default.contentsOfDirectory( + at: Wine.logsFolder, + includingPropertiesForKeys: [.creationDateKey]) else { + return + } + + let logs = urls.filter { url in + url.pathExtension == "log" + } + + let oldLogs = logs.filter { url in + do { + let resourceValues = try url.resourceValues(forKeys: [.creationDateKey]) + + return resourceValues.creationDate ?? Date() < pastDate + } catch { + return false + } + } + + for log in oldLogs { + do { + try FileManager.default.removeItem(at: log) + } catch { + print("Failed to delete log: \(error)") + } + } + } + static func wipeShaderCaches() { let getconf = Process() getconf.executableURL = URL(fileURLWithPath: "/usr/bin/getconf") From 5c6ecca7d8da06856c67e1588940750eb29ae7c0 Mon Sep 17 00:00:00 2001 From: Isaac Marovitz Date: Wed, 6 Mar 2024 12:33:25 +0000 Subject: [PATCH 07/19] WhiskyCmd: Correctly use stderr and non-0 exit code on error --- WhiskyCmd/Main.swift | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/WhiskyCmd/Main.swift b/WhiskyCmd/Main.swift index bdab84509..c76ad83d4 100644 --- a/WhiskyCmd/Main.swift +++ b/WhiskyCmd/Main.swift @@ -84,7 +84,7 @@ extension Whisky { bottlesList.paths.append(bottleURL) print("Created new bottle \"\(name)\".") } catch { - print(error) + throw ValidationError("\(error)") } } } @@ -132,7 +132,7 @@ extension Whisky { print(error) } } else { - print("No bottle called \"\(name)\" found.") + throw ValidationError("No bottle called \"\(name)\" found.") } } } @@ -152,7 +152,7 @@ extension Whisky { bottlesList.paths.removeAll(where: { $0 == bottleToRemove.url }) print("Removed \"\(name)\".") } else { - print("No bottle called \"\(name)\" found.") + throw ValidationError("No bottle called \"\(name)\" found.") } } } @@ -169,8 +169,7 @@ extension Whisky { let bottles = bottlesList.loadBottles() guard let bottle = bottles.first(where: { $0.settings.name == bottleName }) else { - print("A bottle with that name doesn't exist.") - return + throw ValidationError("A bottle with that name doesn't exist.") } let url = URL(fileURLWithPath: path) From 977ff34d79f6ccb886c5e9744d4af5413a2f580f Mon Sep 17 00:00:00 2001 From: Isaac Marovitz Date: Wed, 6 Mar 2024 12:36:47 +0000 Subject: [PATCH 08/19] Fix EXEs opening directly if only 1 bottle exists Co-authored-by: nastys --- Whisky/Views/FileOpenView.swift | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/Whisky/Views/FileOpenView.swift b/Whisky/Views/FileOpenView.swift index 2e87af283..a9f5f8253 100644 --- a/Whisky/Views/FileOpenView.swift +++ b/Whisky/Views/FileOpenView.swift @@ -57,14 +57,19 @@ struct FileOpenView: View { } .frame(minWidth: 400, minHeight: 115) .onAppear { - if bottles.count <= 1 { + // Makes sure there are more than 0 bottles. + // Otherwise, it will crash on the nil cascade + if bottles.count <= 0 { + dismiss() + return + } + + selection = bottles.first(where: { $0.url == currentBottle })?.url ?? bottles[0].url + + if bottles.count == 1 { // If the user only has one bottle // there's nothing for them to select run() - } else if bottles.count > 0 { - // Makes sure there are more than 0 bottles. - // Otherwise, it will crash on the nil cascade - selection = bottles.first(where: { $0.url == currentBottle })?.url ?? bottles[0].url } } } From 90c9561cf329540927cf411e90c430d37c803c01 Mon Sep 17 00:00:00 2001 From: iivusly Date: Thu, 28 Mar 2024 09:22:01 -0700 Subject: [PATCH 09/19] fix terminal command generation (#889) * fix the terminal command generation to run the executable instead of a directory * fix swiftlint violations Signed-off-by: iivusly --------- Signed-off-by: iivusly --- .../Sources/WhiskyKit/Extensions/Program+Extensions.swift | 4 +++- WhiskyKit/Sources/WhiskyKit/Wine/Wine.swift | 6 ++++-- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/WhiskyKit/Sources/WhiskyKit/Extensions/Program+Extensions.swift b/WhiskyKit/Sources/WhiskyKit/Extensions/Program+Extensions.swift index 055b372fd..8d589187f 100644 --- a/WhiskyKit/Sources/WhiskyKit/Extensions/Program+Extensions.swift +++ b/WhiskyKit/Sources/WhiskyKit/Extensions/Program+Extensions.swift @@ -47,7 +47,9 @@ extension Program { } public func generateTerminalCommand() -> String { - return Wine.generateRunCommand(bottle: bottle, args: settings.arguments, environment: generateEnvironment()) + return Wine.generateRunCommand( + at: self.url, bottle: bottle, args: settings.arguments, environment: generateEnvironment() + ) } public func runInTerminal() { diff --git a/WhiskyKit/Sources/WhiskyKit/Wine/Wine.swift b/WhiskyKit/Sources/WhiskyKit/Wine/Wine.swift index 1a3976f28..ecb01736f 100644 --- a/WhiskyKit/Sources/WhiskyKit/Wine/Wine.swift +++ b/WhiskyKit/Sources/WhiskyKit/Wine/Wine.swift @@ -111,8 +111,10 @@ public class Wine { ) { } } - public static func generateRunCommand(bottle: Bottle, args: String, environment: [String: String]) -> String { - var wineCmd = "\(wineBinary.esc) start /unix \(bottle.url.esc) \(args)" + public static func generateRunCommand( + at url: URL, bottle: Bottle, args: String, environment: [String: String] + ) -> String { + var wineCmd = "\(wineBinary.esc) start /unix \(url.path(percentEncoded: false)) \(args)" let env = constructWineEnvironment(for: bottle, environment: environment) for environment in env { wineCmd = "\(environment.key)=\(environment.value) " + wineCmd From 5c5ac7b34276336fa11e3f405f90e6c6548610ff Mon Sep 17 00:00:00 2001 From: Isaac Marovitz Date: Sun, 31 Mar 2024 22:11:37 -0400 Subject: [PATCH 10/19] Temporarily disable Process Management --- Whisky/Views/Bottle/BottleView.swift | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Whisky/Views/Bottle/BottleView.swift b/Whisky/Views/Bottle/BottleView.swift index 243d15319..24b10ff9b 100644 --- a/Whisky/Views/Bottle/BottleView.swift +++ b/Whisky/Views/Bottle/BottleView.swift @@ -53,9 +53,9 @@ struct BottleView: View { NavigationLink(value: BottleStage.config) { Label("tab.config", systemImage: "gearshape") } - NavigationLink(value: BottleStage.processes) { - Label("tab.processes", systemImage: "hockey.puck.circle") - } +// NavigationLink(value: BottleStage.processes) { +// Label("tab.processes", systemImage: "hockey.puck.circle") +// } } .formStyle(.grouped) .scrollDisabled(true) From 277dca23c43b1fca1ab3363557839c4a3cc4cf7f Mon Sep 17 00:00:00 2001 From: Isaac Marovitz Date: Sun, 31 Mar 2024 22:12:37 -0400 Subject: [PATCH 11/19] Bump build version --- .github/ISSUE_TEMPLATE/bug.yml | 4 ++-- Whisky.xcodeproj/project.pbxproj | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/ISSUE_TEMPLATE/bug.yml b/.github/ISSUE_TEMPLATE/bug.yml index 347144c36..811fe7530 100644 --- a/.github/ISSUE_TEMPLATE/bug.yml +++ b/.github/ISSUE_TEMPLATE/bug.yml @@ -37,8 +37,8 @@ body: attributes: label: What version of Whisky are you using? options: - - "2.2.3" - - "<2.2.3" + - "2.2.4" + - "<2.2.4" validations: required: true - type: dropdown diff --git a/Whisky.xcodeproj/project.pbxproj b/Whisky.xcodeproj/project.pbxproj index a786023fb..dc9e76801 100644 --- a/Whisky.xcodeproj/project.pbxproj +++ b/Whisky.xcodeproj/project.pbxproj @@ -789,7 +789,7 @@ "@executable_path/../Frameworks", ); MACOSX_DEPLOYMENT_TARGET = 14.0; - MARKETING_VERSION = 2.2.3; + MARKETING_VERSION = 2.2.4; PRODUCT_BUNDLE_IDENTIFIER = com.isaacmarovitz.Whisky; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE_SPECIFIER = ""; @@ -827,7 +827,7 @@ "@executable_path/../Frameworks", ); MACOSX_DEPLOYMENT_TARGET = 14.0; - MARKETING_VERSION = 2.2.3; + MARKETING_VERSION = 2.2.4; PRODUCT_BUNDLE_IDENTIFIER = com.isaacmarovitz.Whisky; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE_SPECIFIER = ""; @@ -909,7 +909,7 @@ "@executable_path/../../../../Frameworks", ); LOCALIZATION_PREFERS_STRING_CATALOGS = YES; - MARKETING_VERSION = 2.2.3; + MARKETING_VERSION = 2.2.4; PRODUCT_BUNDLE_IDENTIFIER = com.isaacmarovitz.Whisky.WhiskyThumbnail; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE_SPECIFIER = ""; @@ -943,7 +943,7 @@ "@executable_path/../../../../Frameworks", ); LOCALIZATION_PREFERS_STRING_CATALOGS = YES; - MARKETING_VERSION = 2.2.3; + MARKETING_VERSION = 2.2.4; PRODUCT_BUNDLE_IDENTIFIER = com.isaacmarovitz.Whisky.WhiskyThumbnail; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE_SPECIFIER = ""; From e6160dd277cebcd1ffc692e18e16185fa385d53c Mon Sep 17 00:00:00 2001 From: Isaac Marovitz Date: Sun, 31 Mar 2024 22:13:48 -0400 Subject: [PATCH 12/19] Bump build version --- Whisky.xcodeproj/project.pbxproj | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Whisky.xcodeproj/project.pbxproj b/Whisky.xcodeproj/project.pbxproj index dc9e76801..c5ba77bd0 100644 --- a/Whisky.xcodeproj/project.pbxproj +++ b/Whisky.xcodeproj/project.pbxproj @@ -771,7 +771,7 @@ "CODE_SIGN_IDENTITY[sdk=macosx*]" = "Developer ID Application"; CODE_SIGN_STYLE = Manual; COMBINE_HIDPI_IMAGES = YES; - CURRENT_PROJECT_VERSION = 36; + CURRENT_PROJECT_VERSION = 37; DEVELOPMENT_ASSET_PATHS = "\"Whisky/Preview Content\""; DEVELOPMENT_TEAM = ""; "DEVELOPMENT_TEAM[sdk=macosx*]" = 92S3SG4PTH; @@ -809,7 +809,7 @@ "CODE_SIGN_IDENTITY[sdk=macosx*]" = "Developer ID Application"; CODE_SIGN_STYLE = Manual; COMBINE_HIDPI_IMAGES = YES; - CURRENT_PROJECT_VERSION = 36; + CURRENT_PROJECT_VERSION = 37; DEVELOPMENT_ASSET_PATHS = "\"Whisky/Preview Content\""; DEVELOPMENT_TEAM = ""; "DEVELOPMENT_TEAM[sdk=macosx*]" = 92S3SG4PTH; @@ -893,7 +893,7 @@ CODE_SIGN_ENTITLEMENTS = WhiskyThumbnail/WhiskyThumbnail.entitlements; "CODE_SIGN_IDENTITY[sdk=macosx*]" = "Developer ID Application"; CODE_SIGN_STYLE = Manual; - CURRENT_PROJECT_VERSION = 36; + CURRENT_PROJECT_VERSION = 37; DEVELOPMENT_TEAM = ""; "DEVELOPMENT_TEAM[sdk=macosx*]" = 92S3SG4PTH; ENABLE_HARDENED_RUNTIME = YES; @@ -927,7 +927,7 @@ CODE_SIGN_ENTITLEMENTS = WhiskyThumbnail/WhiskyThumbnail.entitlements; "CODE_SIGN_IDENTITY[sdk=macosx*]" = "Developer ID Application"; CODE_SIGN_STYLE = Manual; - CURRENT_PROJECT_VERSION = 36; + CURRENT_PROJECT_VERSION = 37; DEVELOPMENT_TEAM = ""; "DEVELOPMENT_TEAM[sdk=macosx*]" = 92S3SG4PTH; ENABLE_HARDENED_RUNTIME = YES; From 19c8f1cf78a58bd46aa04b30e2e0da72116d1fc3 Mon Sep 17 00:00:00 2001 From: Isaac Marovitz Date: Mon, 1 Apr 2024 08:37:55 -0400 Subject: [PATCH 13/19] Properly escape in terminal cmd gen --- WhiskyKit/Sources/WhiskyKit/Wine/Wine.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/WhiskyKit/Sources/WhiskyKit/Wine/Wine.swift b/WhiskyKit/Sources/WhiskyKit/Wine/Wine.swift index ecb01736f..6e0b8c731 100644 --- a/WhiskyKit/Sources/WhiskyKit/Wine/Wine.swift +++ b/WhiskyKit/Sources/WhiskyKit/Wine/Wine.swift @@ -114,7 +114,7 @@ public class Wine { public static func generateRunCommand( at url: URL, bottle: Bottle, args: String, environment: [String: String] ) -> String { - var wineCmd = "\(wineBinary.esc) start /unix \(url.path(percentEncoded: false)) \(args)" + var wineCmd = "\(wineBinary.esc) start /unix \(url.esc) \(args)" let env = constructWineEnvironment(for: bottle, environment: environment) for environment in env { wineCmd = "\(environment.key)=\(environment.value) " + wineCmd From 732cc46fd262689a193fda8fe9276bee553c677d Mon Sep 17 00:00:00 2001 From: Isaac Marovitz Date: Sun, 7 Apr 2024 23:37:26 -0400 Subject: [PATCH 14/19] Enable GStreamer Error Logs --- WhiskyKit/Sources/WhiskyKit/Wine/Wine.swift | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/WhiskyKit/Sources/WhiskyKit/Wine/Wine.swift b/WhiskyKit/Sources/WhiskyKit/Wine/Wine.swift index 6e0b8c731..cbd262675 100644 --- a/WhiskyKit/Sources/WhiskyKit/Wine/Wine.swift +++ b/WhiskyKit/Sources/WhiskyKit/Wine/Wine.swift @@ -205,7 +205,11 @@ public class Wine { private static func constructWineEnvironment( for bottle: Bottle, environment: [String: String] = [:] ) -> [String: String] { - var result: [String: String] = ["WINEPREFIX": bottle.url.path, "WINEDEBUG": "fixme-all"] + var result: [String: String] = [ + "WINEPREFIX": bottle.url.path, + "WINEDEBUG": "fixme-all", + "GST_DEBUG": "1" + ] bottle.settings.environmentVariables(wineEnv: &result) guard !environment.isEmpty else { return result } result.merge(environment, uniquingKeysWith: { $1 }) @@ -216,7 +220,11 @@ public class Wine { private static func constructWineServerEnvironment( for bottle: Bottle, environment: [String: String] = [:] ) -> [String: String] { - var result: [String: String] = ["WINEPREFIX": bottle.url.path, "WINEDEBUG": "fixme-all"] + var result: [String: String] = [ + "WINEPREFIX": bottle.url.path, + "WINEDEBUG": "fixme-all", + "GST_DEBUG": "1" + ] guard !environment.isEmpty else { return result } result.merge(environment, uniquingKeysWith: { $1 }) return result From da89e1977638b950d065ebbfd1cd4c95da8b5982 Mon Sep 17 00:00:00 2001 From: Isaac Marovitz Date: Mon, 8 Apr 2024 10:20:39 -0400 Subject: [PATCH 15/19] GPTK -> WhiskyWine --- Whisky/Utils/Winetricks.swift | 6 +-- Whisky/Views/ContentView.swift | 8 ++-- Whisky/Views/Setup/RosettaView.swift | 4 +- Whisky/Views/Setup/SetupView.swift | 12 +++--- Whisky/Views/Setup/WelcomeView.swift | 22 +++++------ ...iew.swift => WhiskyWineDownloadView.swift} | 8 ++-- ...View.swift => WhiskyWineInstallView.swift} | 6 +-- .../WhiskyWineInstaller.swift} | 37 ++++++++----------- WhiskyKit/Sources/WhiskyKit/Wine/Wine.swift | 6 +-- 9 files changed, 52 insertions(+), 57 deletions(-) rename Whisky/Views/Setup/{GPTKDownloadView.swift => WhiskyWineDownloadView.swift} (97%) rename Whisky/Views/Setup/{GPTKInstallView.swift => WhiskyWineInstallView.swift} (93%) rename WhiskyKit/Sources/WhiskyKit/{GPTK/GPTKInstaller.swift => WhiskyWine/WhiskyWineInstaller.swift} (78%) diff --git a/Whisky/Utils/Winetricks.swift b/Whisky/Utils/Winetricks.swift index b00586fb7..b218f12db 100644 --- a/Whisky/Utils/Winetricks.swift +++ b/Whisky/Utils/Winetricks.swift @@ -42,14 +42,14 @@ struct WinetricksCategory { } class Winetricks { - static let winetricksURL: URL = GPTKInstaller.libraryFolder + static let winetricksURL: URL = WhiskyWineInstaller.libraryFolder .appending(path: "winetricks") static func runCommand(command: String, bottle: Bottle) async { guard let resourcesURL = Bundle.main.url(forResource: "cabextract", withExtension: nil)? .deletingLastPathComponent() else { return } // swiftlint:disable:next line_length - let winetricksCmd = #"PATH=\"\#(GPTKInstaller.binFolder.path):\#(resourcesURL.path(percentEncoded: false)):$PATH\" WINE=wine64 WINEPREFIX=\"\#(bottle.url.path)\" \"\#(winetricksURL.path(percentEncoded: false))\" \#(command)"# + let winetricksCmd = #"PATH=\"\#(WhiskyWineInstaller.binFolder.path):\#(resourcesURL.path(percentEncoded: false)):$PATH\" WINE=wine64 WINEPREFIX=\"\#(bottle.url.path)\" \"\#(winetricksURL.path(percentEncoded: false))\" \#(command)"# let script = """ tell application "Terminal" @@ -83,7 +83,7 @@ class Winetricks { static func parseVerbs() async -> [WinetricksCategory] { var verbs: String? // Grab the verbs file - let verbsURL = GPTKInstaller.libraryFolder.appending(path: "verbs.txt") + let verbsURL = WhiskyWineInstaller.libraryFolder.appending(path: "verbs.txt") do { let (data, _) = try await URLSession.shared.data(from: verbsURL) diff --git a/Whisky/Views/ContentView.swift b/Whisky/Views/ContentView.swift index 616fb790c..a7154e780 100644 --- a/Whisky/Views/ContentView.swift +++ b/Whisky/Views/ContentView.swift @@ -101,18 +101,18 @@ struct ContentView: View { } } - if !GPTKInstaller.isGPTKInstalled() { + if !WhiskyWineInstaller.isWhiskyWineInstalled() { showSetup = true } let task = Task.detached { - return await GPTKInstaller.shouldUpdateGPTK() + return await WhiskyWineInstaller.shouldUpdateWhiskyWine() } let updateInfo = await task.value if updateInfo.0 { let alert = NSAlert() alert.messageText = String(localized: "update.gptk.title") alert.informativeText = String(format: String(localized: "update.gptk.description"), - String(GPTKInstaller.gptkVersion() ?? SemanticVersion(0, 0, 0)), + String(WhiskyWineInstaller.whiskyWineVersion() ?? SemanticVersion(0, 0, 0)), String(updateInfo.1)) alert.alertStyle = .warning alert.addButton(withTitle: String(localized: "update.gptk.update")) @@ -121,7 +121,7 @@ struct ContentView: View { let response = alert.runModal() if response == .alertFirstButtonReturn { - GPTKInstaller.uninstall() + WhiskyWineInstaller.uninstall() showSetup = true } } diff --git a/Whisky/Views/Setup/RosettaView.swift b/Whisky/Views/Setup/RosettaView.swift index 70bf16d5d..d7cca7606 100644 --- a/Whisky/Views/Setup/RosettaView.swift +++ b/Whisky/Views/Setup/RosettaView.swift @@ -105,8 +105,8 @@ struct RosettaView: View { @MainActor func proceed() { - if !GPTKInstaller.isGPTKInstalled() { - path.append(.gptkDownload) + if !WhiskyWineInstaller.isWhiskyWineInstalled() { + path.append(.whiskyWineDownload) return } diff --git a/Whisky/Views/Setup/SetupView.swift b/Whisky/Views/Setup/SetupView.swift index 082ef5fe9..213854fc5 100644 --- a/Whisky/Views/Setup/SetupView.swift +++ b/Whisky/Views/Setup/SetupView.swift @@ -20,8 +20,8 @@ import SwiftUI enum SetupStage { case rosetta - case gptkDownload - case gptkInstall + case whiskyWineDownload + case whiskyWineInstall } struct SetupView: View { @@ -39,10 +39,10 @@ struct SetupView: View { switch stage { case .rosetta: RosettaView(path: $path, showSetup: $showSetup) - case .gptkDownload: - GPTKDownloadView(tarLocation: $tarLocation, path: $path) - case .gptkInstall: - GPTKInstallView(tarLocation: $tarLocation, path: $path, showSetup: $showSetup) + case .whiskyWineDownload: + WhiskyWineDownloadView(tarLocation: $tarLocation, path: $path) + case .whiskyWineInstall: + WhiskyWineInstallView(tarLocation: $tarLocation, path: $path, showSetup: $showSetup) } } } diff --git a/Whisky/Views/Setup/WelcomeView.swift b/Whisky/Views/Setup/WelcomeView.swift index d30e96b86..f6cd64f22 100644 --- a/Whisky/Views/Setup/WelcomeView.swift +++ b/Whisky/Views/Setup/WelcomeView.swift @@ -21,7 +21,7 @@ import WhiskyKit struct WelcomeView: View { @State var rosettaInstalled: Bool? - @State var gptkInstalled: Bool? + @State var whiskyWineInstalled: Bool? @State var shouldCheckInstallStatus: Bool = false @Binding var path: [SetupStage] @Binding var showSetup: Bool @@ -52,10 +52,10 @@ struct WelcomeView: View { InstallStatusView(isInstalled: $rosettaInstalled, shouldCheckInstallStatus: $shouldCheckInstallStatus, name: "Rosetta") - InstallStatusView(isInstalled: $gptkInstalled, + InstallStatusView(isInstalled: $whiskyWineInstalled, shouldCheckInstallStatus: $shouldCheckInstallStatus, showUninstall: true, - name: "GPTK") + name: "WhiskyWine") } .formStyle(.grouped) .scrollDisabled(true) @@ -68,22 +68,22 @@ struct WelcomeView: View { Spacer() HStack { if let rosettaInstalled = rosettaInstalled, - let gptkInstalled = gptkInstalled { - if !rosettaInstalled || !gptkInstalled { + let whiskyWineInstalled = whiskyWineInstalled { + if !rosettaInstalled || !whiskyWineInstalled { Button("setup.quit") { exit(0) } .keyboardShortcut(.cancelAction) } Spacer() - Button(rosettaInstalled && gptkInstalled ? "setup.done" : "setup.next") { + Button(rosettaInstalled && whiskyWineInstalled ? "setup.done" : "setup.next") { if !rosettaInstalled { path.append(.rosetta) return } - if !gptkInstalled { - path.append(.gptkDownload) + if !whiskyWineInstalled { + path.append(.whiskyWineDownload) return } @@ -98,7 +98,7 @@ struct WelcomeView: View { func checkInstallStatus() { rosettaInstalled = Rosetta2.isRosettaInstalled - gptkInstalled = GPTKInstaller.isGPTKInstalled() + whiskyWineInstalled = WhiskyWineInstaller.isWhiskyWineInstalled() } } @@ -145,8 +145,8 @@ struct InstallStatusView: View { } func uninstall() { - if name == "GPTK" { - GPTKInstaller.uninstall() + if name == "WhiskyWine" { + WhiskyWineInstaller.uninstall() } shouldCheckInstallStatus.toggle() diff --git a/Whisky/Views/Setup/GPTKDownloadView.swift b/Whisky/Views/Setup/WhiskyWineDownloadView.swift similarity index 97% rename from Whisky/Views/Setup/GPTKDownloadView.swift rename to Whisky/Views/Setup/WhiskyWineDownloadView.swift index bfa84fb0c..af55bfedf 100644 --- a/Whisky/Views/Setup/GPTKDownloadView.swift +++ b/Whisky/Views/Setup/WhiskyWineDownloadView.swift @@ -1,5 +1,5 @@ // -// GPTKDownloadView.swift +// WhiskyWineDownloadView.swift // Whisky // // This file is part of Whisky. @@ -19,7 +19,7 @@ import SwiftUI import WhiskyKit -struct GPTKDownloadView: View { +struct WhiskyWineDownloadView: View { @State private var fractionProgress: Double = 0 @State private var completedBytes: Int64 = 0 @State private var totalBytes: Int64 = 0 @@ -65,7 +65,7 @@ struct GPTKDownloadView: View { .frame(width: 400, height: 200) .onAppear { Task { - if let url: URL = URL(string: "https://data.getwhisky.app/Libraries.zip") { + if let url: URL = URL(string: "https://data.getwhisky.app/Wine/Libraries.tar.gz") { downloadTask = URLSession.shared.downloadTask(with: url) { url, _, _ in if let url = url { tarLocation = url @@ -119,6 +119,6 @@ struct GPTKDownloadView: View { } func proceed() { - path.append(.gptkInstall) + path.append(.whiskyWineInstall) } } diff --git a/Whisky/Views/Setup/GPTKInstallView.swift b/Whisky/Views/Setup/WhiskyWineInstallView.swift similarity index 93% rename from Whisky/Views/Setup/GPTKInstallView.swift rename to Whisky/Views/Setup/WhiskyWineInstallView.swift index a76a61361..a02b508ad 100644 --- a/Whisky/Views/Setup/GPTKInstallView.swift +++ b/Whisky/Views/Setup/WhiskyWineInstallView.swift @@ -1,5 +1,5 @@ // -// GPTKInstallView.swift +// WhiskyWineInstallView.swift // Whisky // // This file is part of Whisky. @@ -19,7 +19,7 @@ import SwiftUI import WhiskyKit -struct GPTKInstallView: View { +struct WhiskyWineInstallView: View { @State var installing: Bool = true @Binding var tarLocation: URL @Binding var path: [SetupStage] @@ -52,7 +52,7 @@ struct GPTKInstallView: View { .frame(width: 400, height: 200) .onAppear { Task.detached { - GPTKInstaller.install(from: tarLocation) + WhiskyWineInstaller.install(from: tarLocation) await MainActor.run { installing = false } diff --git a/WhiskyKit/Sources/WhiskyKit/GPTK/GPTKInstaller.swift b/WhiskyKit/Sources/WhiskyKit/WhiskyWine/WhiskyWineInstaller.swift similarity index 78% rename from WhiskyKit/Sources/WhiskyKit/GPTK/GPTKInstaller.swift rename to WhiskyKit/Sources/WhiskyKit/WhiskyWine/WhiskyWineInstaller.swift index 65d76dd38..1a4f44f64 100644 --- a/WhiskyKit/Sources/WhiskyKit/GPTK/GPTKInstaller.swift +++ b/WhiskyKit/Sources/WhiskyKit/WhiskyWine/WhiskyWineInstaller.swift @@ -1,5 +1,5 @@ // -// GPTKInstaller.swift +// WhiskyWineInstaller.swift // WhiskyKit // // This file is part of Whisky. @@ -19,8 +19,8 @@ import Foundation import SemanticVersion -public class GPTKInstaller { - /// The whisky application folder +public class WhiskyWineInstaller { + /// The Whisky application folder public static let applicationFolder = FileManager.default.urls( for: .applicationSupportDirectory, in: .userDomainMask )[0].appending(path: Bundle.whiskyBundleIdentifier) @@ -31,7 +31,7 @@ public class GPTKInstaller { /// URL to the installed `wine` `bin` directory public static let binFolder: URL = libraryFolder.appending(path: "Wine").appending(path: "bin") - public static func isGPTKInstalled() -> Bool { + public static func isWhiskyWineInstalled() -> Bool { return FileManager.default.fileExists(atPath: libraryFolder.path) } @@ -46,15 +46,9 @@ public class GPTKInstaller { } try Tar.untar(tarBall: from, toURL: applicationFolder) - - let tarFile = applicationFolder - .appending(path: "Libraries") - .appendingPathExtension("tar") - .appendingPathExtension("gz") - try Tar.untar(tarBall: tarFile, toURL: applicationFolder) - try FileManager.default.removeItem(at: tarFile) + try FileManager.default.removeItem(at: from) } catch { - print("Failed to install GPTK: \(error)") + print("Failed to install WhiskyWine: \(error)") } } @@ -62,13 +56,13 @@ public class GPTKInstaller { do { try FileManager.default.removeItem(at: libraryFolder) } catch { - print("Failed to uninstall GPTK: \(error)") + print("Failed to uninstall WhiskyWine: \(error)") } } - public static func shouldUpdateGPTK() async -> (Bool, SemanticVersion) { - if let localVersion = gptkVersion() { - let versionPlistURL = "https://data.getwhisky.app/GPTKVersion.plist" + public static func shouldUpdateWhiskyWine() async -> (Bool, SemanticVersion) { + if let localVersion = whiskyWineVersion() { + let versionPlistURL = "https://data.getwhisky.app/Wine/WhiskyWineVersion.plist" if let remoteUrl = URL(string: versionPlistURL) { return await withCheckedContinuation { continuation in @@ -76,10 +70,11 @@ public class GPTKInstaller { do { if error == nil, let data = data { let decoder = PropertyListDecoder() - let remoteInfo = try decoder.decode(GPTKVersion.self, from: data) + let remoteInfo = try decoder.decode(WhiskyWineVersion.self, from: data) let remoteVersion = remoteInfo.version let isRemoteNewer = remoteVersion > localVersion + print(isRemoteNewer) continuation.resume(returning: (isRemoteNewer, remoteVersion)) return } @@ -98,15 +93,15 @@ public class GPTKInstaller { return (false, SemanticVersion(0, 0, 0)) } - public static func gptkVersion() -> SemanticVersion? { + public static func whiskyWineVersion() -> SemanticVersion? { do { let versionPlist = libraryFolder - .appending(path: "GPTKVersion") + .appending(path: "WhiskyWineVersion") .appendingPathExtension("plist") let decoder = PropertyListDecoder() let data = try Data(contentsOf: versionPlist) - let info = try decoder.decode(GPTKVersion.self, from: data) + let info = try decoder.decode(WhiskyWineVersion.self, from: data) return info.version } catch { print(error) @@ -115,6 +110,6 @@ public class GPTKInstaller { } } -struct GPTKVersion: Codable { +struct WhiskyWineVersion: Codable { var version: SemanticVersion = SemanticVersion(1, 0, 0) } diff --git a/WhiskyKit/Sources/WhiskyKit/Wine/Wine.swift b/WhiskyKit/Sources/WhiskyKit/Wine/Wine.swift index cbd262675..092e4cd57 100644 --- a/WhiskyKit/Sources/WhiskyKit/Wine/Wine.swift +++ b/WhiskyKit/Sources/WhiskyKit/Wine/Wine.swift @@ -21,11 +21,11 @@ import os.log public class Wine { /// URL to the installed `DXVK` folder - private static let dxvkFolder: URL = GPTKInstaller.libraryFolder.appending(path: "DXVK") + private static let dxvkFolder: URL = WhiskyWineInstaller.libraryFolder.appending(path: "DXVK") /// Path to the `wine64` binary - public static let wineBinary: URL = GPTKInstaller.binFolder.appending(path: "wine64") + public static let wineBinary: URL = WhiskyWineInstaller.binFolder.appending(path: "wine64") /// Parth to the `wineserver` binary - private static let wineserverBinary: URL = GPTKInstaller.binFolder.appending(path: "wineserver") + private static let wineserverBinary: URL = WhiskyWineInstaller.binFolder.appending(path: "wineserver") /// Run a process on a executable file given by the `executableURL` private static func runProcess( From 53c70206414142ea4262ab63e67bcff8ded4adb7 Mon Sep 17 00:00:00 2001 From: Isaac Marovitz Date: Mon, 8 Apr 2024 10:29:08 -0400 Subject: [PATCH 16/19] SwiftLint --- Whisky.xcodeproj/project.pbxproj | 19 ++++++++++--------- Whisky/Views/ContentView.swift | 3 ++- 2 files changed, 12 insertions(+), 10 deletions(-) diff --git a/Whisky.xcodeproj/project.pbxproj b/Whisky.xcodeproj/project.pbxproj index c5ba77bd0..5461071da 100644 --- a/Whisky.xcodeproj/project.pbxproj +++ b/Whisky.xcodeproj/project.pbxproj @@ -35,8 +35,8 @@ 6E621CEF2A5F631300C9AAB3 /* Winetricks.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6E621CEE2A5F631200C9AAB3 /* Winetricks.swift */; }; 6E6C0CF22A419A6800356232 /* WelcomeView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6E6C0CF12A419A6800356232 /* WelcomeView.swift */; }; 6E6C0CF42A419A7600356232 /* RosettaView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6E6C0CF32A419A7600356232 /* RosettaView.swift */; }; - 6E6C0CF62A419A8300356232 /* GPTKDownloadView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6E6C0CF52A419A8300356232 /* GPTKDownloadView.swift */; }; - 6E6C0CF82A419A8C00356232 /* GPTKInstallView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6E6C0CF72A419A8C00356232 /* GPTKInstallView.swift */; }; + 6E6C0CF62A419A8300356232 /* WhiskyWineDownloadView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6E6C0CF52A419A8300356232 /* WhiskyWineDownloadView.swift */; }; + 6E6C0CF82A419A8C00356232 /* WhiskyWineInstallView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6E6C0CF72A419A8C00356232 /* WhiskyWineInstallView.swift */; }; 6E70A49B2A9A2197007799E9 /* Main.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6E70A49A2A9A2197007799E9 /* Main.swift */; }; 6E70A4A12A9A280C007799E9 /* WhiskyCmd.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6E70A4A02A9A280C007799E9 /* WhiskyCmd.swift */; }; 6E7C07BE2AAE7B0100F6E66B /* ProgramShortcut.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6E7C07BD2AAE7B0100F6E66B /* ProgramShortcut.swift */; }; @@ -135,8 +135,8 @@ 6E621CEE2A5F631200C9AAB3 /* Winetricks.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Winetricks.swift; sourceTree = ""; }; 6E6C0CF12A419A6800356232 /* WelcomeView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WelcomeView.swift; sourceTree = ""; }; 6E6C0CF32A419A7600356232 /* RosettaView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RosettaView.swift; sourceTree = ""; }; - 6E6C0CF52A419A8300356232 /* GPTKDownloadView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GPTKDownloadView.swift; sourceTree = ""; }; - 6E6C0CF72A419A8C00356232 /* GPTKInstallView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GPTKInstallView.swift; sourceTree = ""; }; + 6E6C0CF52A419A8300356232 /* WhiskyWineDownloadView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WhiskyWineDownloadView.swift; sourceTree = ""; }; + 6E6C0CF72A419A8C00356232 /* WhiskyWineInstallView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WhiskyWineInstallView.swift; sourceTree = ""; }; 6E70A4982A9A2197007799E9 /* WhiskyCmd */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = WhiskyCmd; sourceTree = BUILT_PRODUCTS_DIR; }; 6E70A49A2A9A2197007799E9 /* Main.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Main.swift; sourceTree = ""; }; 6E70A4A02A9A280C007799E9 /* WhiskyCmd.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WhiskyCmd.swift; sourceTree = ""; }; @@ -363,8 +363,8 @@ 6EF557972A410599001A4F09 /* SetupView.swift */, 6E6C0CF12A419A6800356232 /* WelcomeView.swift */, 6E6C0CF32A419A7600356232 /* RosettaView.swift */, - 6E6C0CF52A419A8300356232 /* GPTKDownloadView.swift */, - 6E6C0CF72A419A8C00356232 /* GPTKInstallView.swift */, + 6E6C0CF52A419A8300356232 /* WhiskyWineDownloadView.swift */, + 6E6C0CF72A419A8C00356232 /* WhiskyWineInstallView.swift */, ); path = Setup; sourceTree = ""; @@ -570,7 +570,7 @@ ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "if [[ -z \"$FASTLANE\" ]]; then\n export PATH=\"$PATH:/opt/homebrew/bin\"\n if which swiftlint > /dev/null; then\n swiftlint --autocorrect\n else\n echo \"error: SwiftLint not installed, download from https://github.com/realm/SwiftLint\"\n exit -1\n fi\nfi\n"; + shellScript = "export PATH=\"$PATH:/opt/homebrew/bin\"\nif which swiftlint > /dev/null; then\n echo \"Running SwiftLint\"\n swiftlint --strict\nelse\n echo \"error: SwiftLint not installed, download from https://github.com/realm/SwiftLint\"\n exit -1\nfi\n"; }; /* End PBXShellScriptBuildPhase section */ @@ -588,7 +588,7 @@ 6E7C07BE2AAE7B0100F6E66B /* ProgramShortcut.swift in Sources */, 6E355E5829D78249002D83BE /* ConfigView.swift in Sources */, 63FFDE862ADF0C7700178665 /* BottomBar.swift in Sources */, - 6E6C0CF62A419A8300356232 /* GPTKDownloadView.swift in Sources */, + 6E6C0CF62A419A8300356232 /* WhiskyWineDownloadView.swift in Sources */, 6365C4C32B1AA8CD00AAE1FD /* BottleListEntry.swift in Sources */, 6E50D98529CDF25B008C39F6 /* BottleCreationView.swift in Sources */, 6E182FCA2B0BF64E00AADE81 /* WinetricksView.swift in Sources */, @@ -596,7 +596,8 @@ AB0BCABD2B61036E00E21C31 /* RunningProcessesView.swift in Sources */, 6E17B6492AF4118F00831173 /* EnvironmentArgView.swift in Sources */, 6E6C0CF42A419A7600356232 /* RosettaView.swift in Sources */, - 6E6C0CF82A419A8C00356232 /* GPTKInstallView.swift in Sources */, + 6E6C0CF82A419A8C00356232 /* WhiskyWineInstallView.swift in Sources */, + 6E08FC3B2BBAE42800FA622A /* BottleDuplicationView.swift in Sources */, 6365C4C12B1AA69D00AAE1FD /* Animation+Extensions.swift in Sources */, 6E40498329CCA91B006E3F1B /* Bottle+Extensions.swift in Sources */, 6E621CEF2A5F631300C9AAB3 /* Winetricks.swift in Sources */, diff --git a/Whisky/Views/ContentView.swift b/Whisky/Views/ContentView.swift index a7154e780..cfdc60779 100644 --- a/Whisky/Views/ContentView.swift +++ b/Whisky/Views/ContentView.swift @@ -112,7 +112,8 @@ struct ContentView: View { let alert = NSAlert() alert.messageText = String(localized: "update.gptk.title") alert.informativeText = String(format: String(localized: "update.gptk.description"), - String(WhiskyWineInstaller.whiskyWineVersion() ?? SemanticVersion(0, 0, 0)), + String(WhiskyWineInstaller.whiskyWineVersion() + ?? SemanticVersion(0, 0, 0)), String(updateInfo.1)) alert.alertStyle = .warning alert.addButton(withTitle: String(localized: "update.gptk.update")) From 3f1b491fa465754e676d153e080e2d4749ca811d Mon Sep 17 00:00:00 2001 From: Ivan Zorin <6960799+zorikon@users.noreply.github.com> Date: Tue, 9 Apr 2024 05:55:40 +0400 Subject: [PATCH 17/19] Fix size of pin creation view (#907) * fix view size * Revert unrelated changes --- Whisky/Views/Bottle/Pins/PinCreationView.swift | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Whisky/Views/Bottle/Pins/PinCreationView.swift b/Whisky/Views/Bottle/Pins/PinCreationView.swift index 81c1e9dfa..eada6be91 100644 --- a/Whisky/Views/Bottle/Pins/PinCreationView.swift +++ b/Whisky/Views/Bottle/Pins/PinCreationView.swift @@ -105,7 +105,8 @@ struct PinCreationView: View { submit() } } - .frame(minWidth: 400, minHeight: 170) + .fixedSize(horizontal: false, vertical: true) + .frame(minWidth: 400) } func submit() { From 6a781a5aedda846796fe1ff50e62c2ac65904808 Mon Sep 17 00:00:00 2001 From: nastys <7950891+nastys@users.noreply.github.com> Date: Tue, 9 Apr 2024 03:59:38 +0200 Subject: [PATCH 18/19] Bottle Terminal button (#843) * Bottle Terminal button * Use WhiskyCmd to fetch bottle shellenv * Fix opening exe files with one bottle --------- Co-authored-by: nastys --- Whisky/Extensions/Bottle+Extensions.swift | 39 +++++++++++++++++++++ Whisky/Localizable.xcstrings | 13 ++++++- Whisky/Views/Bottle/BottleView.swift | 3 ++ WhiskyCmd/Main.swift | 22 +++++++++++- WhiskyKit/Sources/WhiskyKit/Wine/Wine.swift | 26 +++++++++++++- 5 files changed, 100 insertions(+), 3 deletions(-) diff --git a/Whisky/Extensions/Bottle+Extensions.swift b/Whisky/Extensions/Bottle+Extensions.swift index e50d614d8..06bb41fba 100644 --- a/Whisky/Extensions/Bottle+Extensions.swift +++ b/Whisky/Extensions/Bottle+Extensions.swift @@ -19,12 +19,40 @@ import Foundation import AppKit import WhiskyKit +import os.log extension Bottle { func openCDrive() { NSWorkspace.shared.open(url.appending(path: "drive_c")) } + func openTerminal() { + let whiskyCmdURL = Bundle.main.url(forResource: "WhiskyCmd", withExtension: nil) + if let whiskyCmdURL = whiskyCmdURL { + let whiskyCmd = whiskyCmdURL.path(percentEncoded: false) + let cmd = "eval \\\"$(\\\"\(whiskyCmd)\\\" shellenv \\\"\(settings.name)\\\")\\\"" + + let script = """ + tell application "Terminal" + activate + do script "\(cmd)" + end tell + """ + + Task.detached(priority: .userInitiated) { + var error: NSDictionary? + guard let appleScript = NSAppleScript(source: script) else { return } + appleScript.executeAndReturnError(&error) + + if let error = error { + Logger.wineKit.error("Failed to run terminal script \(error)") + guard let description = error["NSAppleScriptErrorMessage"] as? String else { return } + await self.showRunError(message: String(describing: description)) + } + } + } + } + @discardableResult func getStartMenuPrograms() -> [Program] { let globalStartMenu = url @@ -174,4 +202,15 @@ extension Bottle { func rename(newName: String) { settings.name = newName } + + @MainActor private func showRunError(message: String) { + let alert = NSAlert() + alert.messageText = String(localized: "alert.message") + alert.informativeText = String(localized: "alert.info") + + " \(self.url.lastPathComponent): " + + message + alert.alertStyle = .critical + alert.addButton(withTitle: String(localized: "button.ok")) + alert.runModal() + } } diff --git a/Whisky/Localizable.xcstrings b/Whisky/Localizable.xcstrings index 62cfd582e..0f21fd8a4 100644 --- a/Whisky/Localizable.xcstrings +++ b/Whisky/Localizable.xcstrings @@ -2327,6 +2327,17 @@ } } }, + "button.terminal" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Terminal" + } + } + } + }, "button.unpin" : { "localizations" : { "da" : { @@ -16655,4 +16666,4 @@ } }, "version" : "1.0" -} +} \ No newline at end of file diff --git a/Whisky/Views/Bottle/BottleView.swift b/Whisky/Views/Bottle/BottleView.swift index 24b10ff9b..25e34f40f 100644 --- a/Whisky/Views/Bottle/BottleView.swift +++ b/Whisky/Views/Bottle/BottleView.swift @@ -66,6 +66,9 @@ struct BottleView: View { Button("button.cDrive") { bottle.openCDrive() } + Button("button.terminal") { + bottle.openTerminal() + } Button("button.winetricks") { showWinetricksSheet.toggle() } diff --git a/WhiskyCmd/Main.swift b/WhiskyCmd/Main.swift index c76ad83d4..718eef983 100644 --- a/WhiskyCmd/Main.swift +++ b/WhiskyCmd/Main.swift @@ -33,7 +33,8 @@ struct Whisky: ParsableCommand { // Export.self, Delete.self, Remove.self, - Run.self + Run.self, + Shellenv.self /*Install.self, Uninstall.self*/]) } @@ -178,6 +179,25 @@ extension Whisky { } } + struct Shellenv: ParsableCommand { + static var configuration = CommandConfiguration(abstract: "Prints export statements for a Bottle for eval.") + + @Argument var bottleName: String + + mutating func run() throws { + var bottlesList = BottleData() + let bottles = bottlesList.loadBottles() + + guard let bottle = bottles.first(where: { $0.settings.name == bottleName }) else { + throw ValidationError("A bottle with that name doesn't exist.") + } + + let envCmd = Wine.generateTerminalEnvironmentCommand(bottle: bottle) + print(envCmd) + + } + } + struct Install: ParsableCommand { static var configuration = CommandConfiguration(abstract: "Install Whisky dependencies.") diff --git a/WhiskyKit/Sources/WhiskyKit/Wine/Wine.swift b/WhiskyKit/Sources/WhiskyKit/Wine/Wine.swift index 092e4cd57..c7617f214 100644 --- a/WhiskyKit/Sources/WhiskyKit/Wine/Wine.swift +++ b/WhiskyKit/Sources/WhiskyKit/Wine/Wine.swift @@ -117,12 +117,36 @@ public class Wine { var wineCmd = "\(wineBinary.esc) start /unix \(url.esc) \(args)" let env = constructWineEnvironment(for: bottle, environment: environment) for environment in env { - wineCmd = "\(environment.key)=\(environment.value) " + wineCmd + wineCmd = "\(environment.key)=\"\(environment.value)\" " + wineCmd } return wineCmd } + public static func generateTerminalEnvironmentCommand(bottle: Bottle) -> String { + var cmd = """ + export PATH=\"\(GPTKInstaller.binFolder.path):$PATH\" + export WINE=\"wine64\" + alias wine=\"wine64\" + alias winecfg=\"wine64 winecfg\" + alias msiexec=\"wine64 msiexec\" + alias regedit=\"wine64 regedit\" + alias regsvr32=\"wine64 regsvr32\" + alias wineboot=\"wine64 wineboot\" + alias wineconsole=\"wine64 wineconsole\" + alias winedbg=\"wine64 winedbg\" + alias winefile=\"wine64 winefile\" + alias winepath=\"wine64 winepath\" + """ + + let env = constructWineEnvironment(for: bottle, environment: constructWineEnvironment(for: bottle)) + for environment in env { + cmd += "\nexport \(environment.key)=\"\(environment.value)\"" + } + + return cmd + } + /// Run a `wineserver` command with the given arguments and return the output result private static func runWineserver(_ args: [String], bottle: Bottle) async throws -> String { var result: [ProcessOutput] = [] From d98a8147f1e25bffc9501020a45423f217e6a4cc Mon Sep 17 00:00:00 2001 From: Isaac Marovitz Date: Mon, 8 Apr 2024 22:01:51 -0400 Subject: [PATCH 19/19] Cleanup + Fix --- Whisky/Localizable.xcstrings | 2 +- WhiskyKit/Sources/WhiskyKit/Wine/Wine.swift | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Whisky/Localizable.xcstrings b/Whisky/Localizable.xcstrings index 0f21fd8a4..1a21e0eff 100644 --- a/Whisky/Localizable.xcstrings +++ b/Whisky/Localizable.xcstrings @@ -2333,7 +2333,7 @@ "en" : { "stringUnit" : { "state" : "translated", - "value" : "Terminal" + "value" : "Terminal..." } } } diff --git a/WhiskyKit/Sources/WhiskyKit/Wine/Wine.swift b/WhiskyKit/Sources/WhiskyKit/Wine/Wine.swift index c7617f214..c485d0712 100644 --- a/WhiskyKit/Sources/WhiskyKit/Wine/Wine.swift +++ b/WhiskyKit/Sources/WhiskyKit/Wine/Wine.swift @@ -125,7 +125,7 @@ public class Wine { public static func generateTerminalEnvironmentCommand(bottle: Bottle) -> String { var cmd = """ - export PATH=\"\(GPTKInstaller.binFolder.path):$PATH\" + export PATH=\"\(WhiskyWineInstaller.binFolder.path):$PATH\" export WINE=\"wine64\" alias wine=\"wine64\" alias winecfg=\"wine64 winecfg\"