Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Option to run in recovery mode #91

Merged
merged 5 commits into from
May 19, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions Package.resolved
Original file line number Diff line number Diff line change
@@ -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",
Expand Down
2 changes: 2 additions & 0 deletions Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -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"])
Expand Down
4 changes: 3 additions & 1 deletion Sources/tart/Commands/Run.swift
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -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 {
Expand Down
37 changes: 37 additions & 0 deletions Sources/tart/VM+Recovery.swift
Original file line number Diff line number Diff line change
@@ -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)
}
}
}
}
10 changes: 2 additions & 8 deletions Sources/tart/VM.swift
Original file line number Diff line number Diff line change
Expand Up @@ -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()
Expand Down