mirror of https://github.com/cirruslabs/tart.git
Option to run in recovery mode (#91)
* Option to run in recovery mode * Fixed typo * Use Dynamic package to call private APIs * Improved comment * Move options closer to invocation
This commit is contained in:
parent
60c15e3e49
commit
0a257a1547
|
|
@ -1,5 +1,14 @@
|
|||
{
|
||||
"pins" : [
|
||||
{
|
||||
"identity" : "dynamic",
|
||||
"kind" : "remoteSourceControl",
|
||||
"location" : "https://github.com/mhdhejazi/Dynamic",
|
||||
"state" : {
|
||||
"branch" : "master",
|
||||
"revision" : "772883073d044bc754d401cabb6574624eb3778f"
|
||||
}
|
||||
},
|
||||
{
|
||||
"identity" : "swift-argument-parser",
|
||||
"kind" : "remoteSourceControl",
|
||||
|
|
|
|||
|
|
@ -13,10 +13,12 @@ let package = Package(
|
|||
dependencies: [
|
||||
.package(url: "https://github.com/apple/swift-argument-parser", from: "1.1.2"),
|
||||
.package(url: "https://github.com/pointfreeco/swift-parsing", from: "0.9.2"),
|
||||
.package(url: "https://github.com/mhdhejazi/Dynamic", branch: "master"),
|
||||
],
|
||||
targets: [
|
||||
.executableTarget(name: "tart", dependencies: [
|
||||
.product(name: "ArgumentParser", package: "swift-argument-parser"),
|
||||
.product(name: "Dynamic", package: "Dynamic"),
|
||||
.product(name: "Parsing", package: "swift-parsing"),
|
||||
]),
|
||||
.testTarget(name: "TartTests", dependencies: ["tart"])
|
||||
|
|
|
|||
|
|
@ -13,6 +13,8 @@ struct Run: AsyncParsableCommand {
|
|||
|
||||
@Flag var noGraphics: Bool = false
|
||||
|
||||
@Flag var recovery: Bool = false
|
||||
|
||||
@MainActor
|
||||
func run() async throws {
|
||||
let vmDir = try VMStorageLocal().open(name)
|
||||
|
|
@ -21,7 +23,7 @@ struct Run: AsyncParsableCommand {
|
|||
await withThrowingTaskGroup(of: Void.self) { group in
|
||||
group.addTask {
|
||||
do {
|
||||
try await vm!.run()
|
||||
try await vm!.run(recovery)
|
||||
|
||||
Foundation.exit(0)
|
||||
} catch {
|
||||
|
|
|
|||
|
|
@ -0,0 +1,37 @@
|
|||
import Foundation
|
||||
import Virtualization
|
||||
import Dynamic
|
||||
|
||||
// Kudos to @saagarjha's VirtualApple for finding about _VZVirtualMachineStartOptions
|
||||
|
||||
extension VZVirtualMachine {
|
||||
func start(_ recovery: Bool) async throws {
|
||||
if !recovery {
|
||||
// just use the regular API
|
||||
return try await withCheckedThrowingContinuation { continuation in
|
||||
DispatchQueue.main.async {
|
||||
self.start(completionHandler: { result in
|
||||
continuation.resume(with: result)
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// use some private stuff only for recovery
|
||||
return try await withCheckedThrowingContinuation { (continuation: CheckedContinuation<Void, Error>) in
|
||||
DispatchQueue.main.async {
|
||||
let handler: @convention(block) (_ result: Any?) -> Void = { result in
|
||||
if let error = result as? Error {
|
||||
continuation.resume(throwing: error)
|
||||
} else {
|
||||
continuation.resume(returning: ())
|
||||
}
|
||||
}
|
||||
// dynamic magic
|
||||
let options = Dynamic._VZVirtualMachineStartOptions()
|
||||
options.bootMacOSRecovery = recovery
|
||||
Dynamic(self)._start(withOptions: options, completionHandler: handler)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -133,14 +133,8 @@ class VM: NSObject, VZVirtualMachineDelegate, ObservableObject {
|
|||
}
|
||||
}
|
||||
|
||||
func run() async throws {
|
||||
try await withCheckedThrowingContinuation { continuation in
|
||||
DispatchQueue.main.async {
|
||||
self.virtualMachine.start(completionHandler: { result in
|
||||
continuation.resume(with: result)
|
||||
})
|
||||
}
|
||||
}
|
||||
func run(_ recovery: Bool) async throws {
|
||||
try await virtualMachine.start(recovery)
|
||||
|
||||
await withTaskCancellationHandler(operation: {
|
||||
sema.wait()
|
||||
|
|
|
|||
Loading…
Reference in New Issue