Skip to content

Commit 2172d91

Browse files
committed
feat: strategy and logger support
Signed-off-by: Lessica <82flex@gmail.com>
1 parent f57c742 commit 2172d91

28 files changed

+945
-125
lines changed

TrollFools.xcodeproj/project.pbxproj

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@
1717
6124A07D2CD233A700C52253 /* InjectedPlugIn.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6124A07C2CD233A700C52253 /* InjectedPlugIn.swift */; };
1818
6124A07F2CD233BA00C52253 /* PlugInCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6124A07E2CD233BA00C52253 /* PlugInCell.swift */; };
1919
6124A0812CD233DA00C52253 /* EjectListModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6124A0802CD233DA00C52253 /* EjectListModel.swift */; };
20+
6168001B2D364DD400DF485F /* StripedTextTableViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 6168001A2D364DD400DF485F /* StripedTextTableViewController.m */; };
21+
6168001D2D3652B600DF485F /* LogsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6168001C2D3652B100DF485F /* LogsView.swift */; };
2022
61946B262D2FD8AB009E0AC4 /* OrderedCollections in Frameworks */ = {isa = PBXBuildFile; productRef = 61946B252D2FD8AB009E0AC4 /* OrderedCollections */; };
2123
61EFA3642D30267E00159442 /* InjectorV3.swift in Sources */ = {isa = PBXBuildFile; fileRef = 61EFA3632D30267200159442 /* InjectorV3.swift */; };
2224
61EFA3672D3026D400159442 /* CocoaLumberjack in Frameworks */ = {isa = PBXBuildFile; productRef = 61EFA3662D3026D400159442 /* CocoaLumberjack */; };
@@ -81,6 +83,9 @@
8183
6124A07C2CD233A700C52253 /* InjectedPlugIn.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InjectedPlugIn.swift; sourceTree = "<group>"; };
8284
6124A07E2CD233BA00C52253 /* PlugInCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PlugInCell.swift; sourceTree = "<group>"; };
8385
6124A0802CD233DA00C52253 /* EjectListModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EjectListModel.swift; sourceTree = "<group>"; };
86+
616800192D364DD400DF485F /* StripedTextTableViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = StripedTextTableViewController.h; sourceTree = "<group>"; };
87+
6168001A2D364DD400DF485F /* StripedTextTableViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = StripedTextTableViewController.m; sourceTree = "<group>"; };
88+
6168001C2D3652B100DF485F /* LogsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LogsView.swift; sourceTree = "<group>"; };
8489
61EFA3632D30267200159442 /* InjectorV3.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InjectorV3.swift; sourceTree = "<group>"; };
8590
61EFA36C2D3027AF00159442 /* InjectorV3+Command.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "InjectorV3+Command.swift"; sourceTree = "<group>"; };
8691
61EFA36E2D30338300159442 /* InjectorV3+Bundle.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "InjectorV3+Bundle.swift"; sourceTree = "<group>"; };
@@ -174,14 +179,15 @@
174179
children = (
175180
6124A0732CD2328600C52253 /* AppListCell.swift */,
176181
CCF4706D2C4A4BAB008D8197 /* AppListView.swift */,
182+
CC15490D2C4B80AF00A4173E /* EjectListView.swift */,
183+
CC1548D42C4A744300A4173E /* FailureView.swift */,
184+
CCB6A11A2C4A6066000D75B0 /* InjectView.swift */,
185+
6168001C2D3652B100DF485F /* LogsView.swift */,
177186
6124A0772CD232D400C52253 /* OptionCell.swift */,
178187
CCB6A1182C4A58C7000D75B0 /* OptionView.swift */,
179-
CC19E4BA2C561D7300E0F1B5 /* SettingsView.swift */,
180-
CCB6A11A2C4A6066000D75B0 /* InjectView.swift */,
181188
6124A07E2CD233BA00C52253 /* PlugInCell.swift */,
182-
CC15490D2C4B80AF00A4173E /* EjectListView.swift */,
189+
CC19E4BA2C561D7300E0F1B5 /* SettingsView.swift */,
183190
CC1548D22C4A743200A4173E /* SuccessView.swift */,
184-
CC1548D42C4A744300A4173E /* FailureView.swift */,
185191
);
186192
name = View;
187193
sourceTree = "<group>";
@@ -246,6 +252,8 @@
246252
CCF925412C4C1B6F00880D48 /* LSApplicationWorkspace.h */,
247253
CCF470712C4A4E81008D8197 /* TrollFools-Bridging-Header.h */,
248254
CCF470722C4A4E81008D8197 /* TrollFoolsStub.m */,
255+
616800192D364DD400DF485F /* StripedTextTableViewController.h */,
256+
6168001A2D364DD400DF485F /* StripedTextTableViewController.m */,
249257
);
250258
name = CExtension;
251259
sourceTree = "<group>";
@@ -423,7 +431,9 @@
423431
6124A07D2CD233A700C52253 /* InjectedPlugIn.swift in Sources */,
424432
CC1548DB2C4A7C7000A4173E /* Execute.swift in Sources */,
425433
6124A0742CD2328600C52253 /* AppListCell.swift in Sources */,
434+
6168001D2D3652B600DF485F /* LogsView.swift in Sources */,
426435
CCF5A0A42C4D45160097D48D /* AuxiliaryExecute.swift in Sources */,
436+
6168001B2D364DD400DF485F /* StripedTextTableViewController.m in Sources */,
427437
6124A0712CD2326500C52253 /* FilterOptions.swift in Sources */,
428438
61EFA3792D3108BD00159442 /* InjectorV3+Eject.swift in Sources */,
429439
6124A07B2CD2337500C52253 /* ViewControllerHost.swift in Sources */,

TrollFools/AppListCell.swift

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
// Created by 82Flex on 2024/10/30.
66
//
77

8+
import CocoaLumberjackSwift
89
import SwiftUI
910

1011
struct AppListCell: View {
@@ -60,7 +61,7 @@ struct AppListCell: View {
6061
app.reload()
6162
appList.isRebuildNeeded = true
6263
}
63-
} catch { NSLog("\(error.localizedDescription)") }
64+
} catch { DDLogError("\(error)", ddlog: InjectorV3.main.logger) }
6465
} label: {
6566
Label(NSLocalizedString("Unlock Version", comment: ""), systemImage: "lock.open")
6667
}
@@ -72,7 +73,7 @@ struct AppListCell: View {
7273
app.reload()
7374
appList.isRebuildNeeded = true
7475
}
75-
} catch { NSLog("\(error.localizedDescription)") }
76+
} catch { DDLogError("\(error)", ddlog: InjectorV3.main.logger) }
7677
} label: {
7778
Label(NSLocalizedString("Lock Version", comment: ""), systemImage: "lock")
7879
}

TrollFools/AppListView.swift

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,14 @@
55
// Created by Lessica on 2024/7/19.
66
//
77

8+
import CocoaLumberjackSwift
89
import SwiftUI
910

1011
struct AppListView: View {
1112
@EnvironmentObject var appList: AppListModel
1213

1314
@State var isErrorOccurred: Bool = false
14-
@State var errorMessage: String = ""
15+
@State var lastError: Error?
1516

1617
@State var selectorOpenedURL: URL? = nil
1718

@@ -162,8 +163,10 @@ struct AppListView: View {
162163
.navigationBarTitleDisplayMode(appList.isSelectorMode ? .inline : .automatic)
163164
.background(Group {
164165
NavigationLink(isActive: $isErrorOccurred) {
165-
FailureView(title: NSLocalizedString("Error", comment: ""),
166-
message: errorMessage)
166+
FailureView(
167+
title: NSLocalizedString("Error", comment: ""),
168+
error: lastError
169+
)
167170
} label: { }
168171
})
169172
.toolbar {
@@ -252,10 +255,10 @@ struct AppListView: View {
252255
}
253256
}
254257
} catch {
255-
NSLog("\(error.localizedDescription)")
258+
DDLogError("\(error)", ddlog: InjectorV3.main.logger)
256259

257260
DispatchQueue.main.async {
258-
errorMessage = error.localizedDescription
261+
lastError = error
259262
isErrorOccurred = true
260263
}
261264
}

TrollFools/AuxiliaryExecute+Spawn.swift

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@ public extension AuxiliaryExecute {
7777
workingDirectory: String? = nil,
7878
personaOptions: PersonaOptions? = nil,
7979
timeout: Double = 0,
80+
ddlog: DDLog = .sharedInstance,
8081
setPid: ((pid_t) -> Void)? = nil,
8182
output: ((String) -> Void)? = nil
8283
)
@@ -90,6 +91,7 @@ public extension AuxiliaryExecute {
9091
workingDirectory: workingDirectory,
9192
personaOptions: personaOptions,
9293
timeout: timeout,
94+
ddlog: ddlog,
9395
setPid: setPid
9496
) { str in
9597
outputLock.lock()
@@ -120,6 +122,7 @@ public extension AuxiliaryExecute {
120122
workingDirectory: String? = nil,
121123
personaOptions: PersonaOptions? = nil,
122124
timeout: Double = 0,
125+
ddlog: DDLog = .sharedInstance,
123126
setPid: ((pid_t) -> Void)? = nil,
124127
stdoutBlock: ((String) -> Void)? = nil,
125128
stderrBlock: ((String) -> Void)? = nil
@@ -133,6 +136,7 @@ public extension AuxiliaryExecute {
133136
workingDirectory: workingDirectory,
134137
personaOptions: personaOptions,
135138
timeout: timeout,
139+
ddlog: ddlog,
136140
setPid: setPid,
137141
stdoutBlock: stdoutBlock,
138142
stderrBlock: stderrBlock
@@ -163,6 +167,7 @@ public extension AuxiliaryExecute {
163167
workingDirectory: String? = nil,
164168
personaOptions: PersonaOptions? = nil,
165169
timeout: Double = 0,
170+
ddlog: DDLog = .sharedInstance,
166171
setPid: ((pid_t) -> Void)? = nil,
167172
stdoutBlock: ((String) -> Void)? = nil,
168173
stderrBlock: ((String) -> Void)? = nil,
@@ -259,7 +264,6 @@ public extension AuxiliaryExecute {
259264
defer { for case let arg? in argv { free(arg) } }
260265

261266
// MARK: NOW POSIX_SPAWN -
262-
DDLogInfo("Execute \(command) \(args.joined(separator: " "))")
263267

264268
var pid: pid_t = 0
265269
let spawnStatus = posix_spawn(&pid, command, &fileActions, &attrs, argv + [nil], realEnv + [nil])
@@ -269,6 +273,7 @@ public extension AuxiliaryExecute {
269273
return
270274
}
271275

276+
DDLogInfo("Spawned process \(pid) command \(args.joined(separator: " "))", ddlog: ddlog)
272277
setPid?(pid)
273278

274279
close(pipestdout[1])
@@ -366,16 +371,16 @@ public extension AuxiliaryExecute {
366371
let terminationReason: TerminationReason
367372
if WIFSIGNALED(status) {
368373
let signal = WTERMSIG(status)
369-
DDLogError("Process \(pid) terminated with uncaught signal \(signal)")
374+
DDLogError("Process \(pid) terminated with uncaught signal \(signal)", ddlog: ddlog)
370375
terminationReason = .uncaughtSignal(signal)
371376
} else {
372377
assert(WIFEXITED(status))
373378

374379
let exitCode = WEXITSTATUS(status)
375380
if exitCode == EXIT_SUCCESS {
376-
DDLogInfo("Process \(pid) exited successfully")
381+
DDLogInfo("Process \(pid) exited successfully", ddlog: ddlog)
377382
} else {
378-
DDLogWarn("Process \(pid) exited with code \(exitCode)")
383+
DDLogWarn("Process \(pid) exited with code \(exitCode)", ddlog: ddlog)
379384
}
380385

381386
terminationReason = .exit(exitCode)

TrollFools/EjectListView.swift

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
// Created by Lessica on 2024/7/20.
66
//
77

8+
import CocoaLumberjackSwift
89
import SwiftUI
910

1011
struct EjectListView: View {
@@ -15,7 +16,7 @@ struct EjectListView: View {
1516
}
1617

1718
@State var isErrorOccurred: Bool = false
18-
@State var errorMessage: String = ""
19+
@State var lastError: Error?
1920

2021
@State var isDeletingAll = false
2122
@StateObject var viewControllerHost = ViewControllerHost()
@@ -86,8 +87,10 @@ struct EjectListView: View {
8687
.animation(.easeOut, value: ejectList.filter.isSearching)
8788
.background(Group {
8889
NavigationLink(isActive: $isErrorOccurred) {
89-
FailureView(title: NSLocalizedString("Error", comment: ""),
90-
message: errorMessage)
90+
FailureView(
91+
title: NSLocalizedString("Error", comment: ""),
92+
error: lastError
93+
)
9194
} label: { }
9295
})
9396
.onViewWillAppear { viewController in
@@ -125,9 +128,9 @@ struct EjectListView: View {
125128
ejectList.app.reload()
126129
ejectList.reload()
127130
} catch {
128-
NSLog("\(error)")
131+
DDLogError("\(error)", ddlog: InjectorV3.main.logger)
129132

130-
errorMessage = error.localizedDescription
133+
lastError = error
131134
isErrorOccurred = true
132135
}
133136
}
@@ -166,15 +169,15 @@ struct EjectListView: View {
166169
isDeletingAll = false
167170
}
168171

169-
NSLog("\(error)")
172+
DDLogError("\(error)", ddlog: InjectorV3.main.logger)
170173

171-
errorMessage = error.localizedDescription
174+
lastError = error
172175
isErrorOccurred = true
173176
}
174177
}
175178
}
176179
} catch {
177-
errorMessage = error.localizedDescription
180+
lastError = error
178181
isErrorOccurred = true
179182
}
180183
}

TrollFools/Execute.swift

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -14,39 +14,43 @@ enum Execute {
1414
static func rootSpawn(
1515
binary: String,
1616
arguments: [String] = [],
17-
environment: [String: String] = [:]
17+
environment: [String: String] = [:],
18+
ddlog: DDLog = .sharedInstance
1819
) throws -> AuxiliaryExecute.TerminationReason {
1920
let receipt = AuxiliaryExecute.spawn(
2021
command: binary,
2122
args: arguments,
2223
environment: environment,
23-
personaOptions: .init(uid: 0, gid: 0)
24+
personaOptions: .init(uid: 0, gid: 0),
25+
ddlog: ddlog
2426
)
2527
if !receipt.stdout.isEmpty {
26-
DDLogVerbose("Standard output: \(receipt.stdout)")
28+
DDLogVerbose("Process \(receipt.pid) output: \(receipt.stdout)", ddlog: ddlog)
2729
}
2830
if !receipt.stderr.isEmpty {
29-
DDLogVerbose("Standard error: \(receipt.stderr)")
31+
DDLogVerbose("Process \(receipt.pid) error: \(receipt.stderr)", ddlog: ddlog)
3032
}
3133
return receipt.terminationReason
3234
}
3335

3436
static func rootSpawnWithOutputs(
3537
binary: String,
3638
arguments: [String] = [],
37-
environment: [String: String] = [:]
39+
environment: [String: String] = [:],
40+
ddlog: DDLog = .sharedInstance
3841
) throws -> AuxiliaryExecute.ExecuteReceipt {
3942
let receipt = AuxiliaryExecute.spawn(
4043
command: binary,
4144
args: arguments,
4245
environment: environment,
43-
personaOptions: .init(uid: 0, gid: 0)
46+
personaOptions: .init(uid: 0, gid: 0),
47+
ddlog: ddlog
4448
)
4549
if !receipt.stdout.isEmpty {
46-
DDLogVerbose("Standard output: \(receipt.stdout)")
50+
DDLogVerbose("Process \(receipt.pid) output: \(receipt.stdout)", ddlog: ddlog)
4751
}
4852
if !receipt.stderr.isEmpty {
49-
DDLogVerbose("Standard error: \(receipt.stderr)")
53+
DDLogVerbose("Process \(receipt.pid) error: \(receipt.stderr)", ddlog: ddlog)
5054
}
5155
return receipt
5256
}

TrollFools/FailureView.swift

Lines changed: 31 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,15 @@
88
import SwiftUI
99

1010
struct FailureView: View {
11+
1112
let title: String
12-
let message: String
13+
let error: Error?
14+
15+
var logFileURL: URL? {
16+
(error as? NSError)?.userInfo[NSURLErrorKey] as? URL
17+
}
18+
19+
@State private var isLogsPresented = false
1320

1421
var body: some View {
1522
VStack(spacing: 20) {
@@ -20,16 +27,34 @@ struct FailureView: View {
2027
Text(title)
2128
.font(.title)
2229
.bold()
23-
.multilineTextAlignment(.center)
2430

25-
Text(message)
26-
.font(.title3)
27-
.multilineTextAlignment(.center)
31+
if let error {
32+
Text(error.localizedDescription)
33+
.font(.title3)
34+
}
35+
36+
if logFileURL != nil {
37+
Button {
38+
isLogsPresented = true
39+
} label: {
40+
Label(NSLocalizedString("View Logs", comment: ""),
41+
systemImage: "note.text")
42+
}
43+
}
2844
}
2945
.padding()
46+
.multilineTextAlignment(.center)
47+
.sheet(isPresented: $isLogsPresented) {
48+
if let logFileURL {
49+
LogsView(url: logFileURL)
50+
}
51+
}
3052
}
3153
}
3254

3355
#Preview {
34-
FailureView(title: "Hello, World!", message: "This is a failure.")
56+
FailureView(
57+
title: "Hello, World!",
58+
error: nil
59+
)
3560
}

0 commit comments

Comments
 (0)