mirror of
https://github.com/XcodesOrg/XcodesApp.git
synced 2026-03-25 08:55:46 +00:00
feat: add extraction backend preference (native/system xip)
This commit is contained in:
parent
2387d96d95
commit
a7d500ade2
3 changed files with 38 additions and 18 deletions
|
|
@ -251,7 +251,7 @@ extension AppState {
|
|||
func unarchiveAndMoveXIP(availableXcode: AvailableXcode, at source: URL, to destination: URL) -> AnyPublisher<URL, Swift.Error> {
|
||||
self.setInstallationStep(of: availableXcode.version, to: .unarchiving)
|
||||
|
||||
return unxipOrUnxipExperiment(source)
|
||||
return extractXIP(source)
|
||||
.catch { error -> AnyPublisher<ProcessOutput, Swift.Error> in
|
||||
if let executionError = error as? ProcessExecutionError {
|
||||
if executionError.standardError.contains("damaged and can’t be expanded") {
|
||||
|
|
@ -291,13 +291,14 @@ extension AppState {
|
|||
.eraseToAnyPublisher()
|
||||
}
|
||||
|
||||
func unxipOrUnxipExperiment(_ source: URL) -> AnyPublisher<ProcessOutput, Error> {
|
||||
if unxipExperiment {
|
||||
func extractXIP(_ source: URL) -> AnyPublisher<ProcessOutput, Error> {
|
||||
switch extractionBackend {
|
||||
case .nativeLibunxip:
|
||||
// Native libunxip integration - no subprocess needed
|
||||
// https://github.com/saagarjha/unxip
|
||||
let destination = source.deletingLastPathComponent()
|
||||
return Current.shell.unxipNative(source, destination)
|
||||
} else {
|
||||
case .systemXip:
|
||||
return Current.shell.unxip(source)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ import LibFido2Swift
|
|||
enum PreferenceKey: String {
|
||||
case installPath
|
||||
case localPath
|
||||
case unxipExperiment
|
||||
case extractionBackend
|
||||
case createSymLinkOnSelect
|
||||
case onSelectActionType
|
||||
case showOpenInRosettaOption
|
||||
|
|
@ -31,6 +31,23 @@ enum PreferenceKey: String {
|
|||
func isManaged() -> Bool { UserDefaults.standard.objectIsForced(forKey: self.rawValue) }
|
||||
}
|
||||
|
||||
/// Controls which backend is used for extracting .xip archives.
|
||||
enum ExtractionBackend: String, CaseIterable, Identifiable {
|
||||
/// Uses /usr/bin/xip --expand (slowest, always works)
|
||||
case systemXip = "system"
|
||||
/// Uses libunxip natively (fastest, built-in)
|
||||
case nativeLibunxip = "native"
|
||||
|
||||
var id: Self { self }
|
||||
|
||||
var displayName: String {
|
||||
switch self {
|
||||
case .systemXip: return "System xip (slowest, most compatible)"
|
||||
case .nativeLibunxip: return "Native libunxip (fastest)"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class AppState: ObservableObject {
|
||||
private let client = AppleAPI.Client()
|
||||
internal let runtimeService = RuntimeService()
|
||||
|
|
@ -97,13 +114,13 @@ class AppState: ObservableObject {
|
|||
|
||||
var disableInstallPathChange: Bool { PreferenceKey.installPath.isManaged() }
|
||||
|
||||
@Published var unxipExperiment = false {
|
||||
@Published var extractionBackend: ExtractionBackend = .nativeLibunxip {
|
||||
didSet {
|
||||
Current.defaults.set(unxipExperiment, forKey: "unxipExperiment")
|
||||
Current.defaults.set(extractionBackend.rawValue, forKey: "extractionBackend")
|
||||
}
|
||||
}
|
||||
|
||||
var disableUnxipExperiment: Bool { PreferenceKey.unxipExperiment.isManaged() }
|
||||
|
||||
var disableExtractionBackendChange: Bool { PreferenceKey.extractionBackend.isManaged() }
|
||||
|
||||
@Published var createSymLinkOnSelect = false {
|
||||
didSet {
|
||||
|
|
@ -203,7 +220,7 @@ class AppState: ObservableObject {
|
|||
|
||||
func setupDefaults() {
|
||||
localPath = Current.defaults.string(forKey: "localPath") ?? Path.defaultXcodesApplicationSupport.string
|
||||
unxipExperiment = Current.defaults.bool(forKey: "unxipExperiment") ?? false
|
||||
extractionBackend = ExtractionBackend(rawValue: Current.defaults.string(forKey: "extractionBackend") ?? "") ?? .nativeLibunxip
|
||||
createSymLinkOnSelect = Current.defaults.bool(forKey: "createSymLinkOnSelect") ?? false
|
||||
onSelectActionType = SelectedActionType(rawValue: Current.defaults.string(forKey: "onSelectActionType") ?? "none") ?? .none
|
||||
installPath = Current.defaults.string(forKey: "installPath") ?? Path.defaultInstallDirectory.string
|
||||
|
|
|
|||
|
|
@ -4,17 +4,19 @@ import SwiftUI
|
|||
|
||||
struct ExperimentsPreferencePane: View {
|
||||
@EnvironmentObject var appState: AppState
|
||||
|
||||
|
||||
var body: some View {
|
||||
VStack(alignment: .leading, spacing: 20) {
|
||||
GroupBox(label: Text("FasterUnxip")) {
|
||||
GroupBox(label: Text("ExtractionBackend")) {
|
||||
VStack(alignment: .leading) {
|
||||
Toggle(
|
||||
"UseUnxipExperiment",
|
||||
isOn: $appState.unxipExperiment
|
||||
)
|
||||
.disabled(appState.disableUnxipExperiment)
|
||||
Text("FasterUnxipDescription")
|
||||
Picker("ExtractionBackendPicker", selection: $appState.extractionBackend) {
|
||||
ForEach(ExtractionBackend.allCases) { backend in
|
||||
Text(backend.displayName).tag(backend)
|
||||
}
|
||||
}
|
||||
.pickerStyle(.radioGroup)
|
||||
.disabled(appState.disableExtractionBackendChange)
|
||||
Text("ExtractionBackendDescription")
|
||||
.font(.footnote)
|
||||
.foregroundStyle(.secondary)
|
||||
.fixedSize(horizontal: false, vertical: true)
|
||||
|
|
|
|||
Loading…
Reference in a new issue