Skip to content

Commit 4f25905

Browse files
committed
start moving over to XcodesKit package. Runtimes searching
1 parent d8e1069 commit 4f25905

31 files changed

Lines changed: 749 additions & 54 deletions

Xcodes.xcodeproj/project.pbxproj

Lines changed: 51 additions & 21 deletions
Large diffs are not rendered by default.

Xcodes.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved

Lines changed: 11 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Xcodes/Backend/AppState+Install.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import AppleAPI
55
import Version
66
import LegibleError
77
import os.log
8+
import XcodesKit
89

910
/// Downloads and installs Xcodes
1011
extension AppState {
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
import Foundation
2+
import XcodesKit
3+
import OSLog
4+
5+
extension AppState {
6+
func updateDownloadableRuntimes() {
7+
Task {
8+
do {
9+
let runtimes = try await self.runtimeService.downloadableRuntimes().downloadables
10+
DispatchQueue.main.async {
11+
self.downloadableRuntimes = runtimes
12+
}
13+
try? cacheDownloadableRuntimes(runtimes)
14+
} catch {
15+
Logger.appState.error("Error downloading runtimes: \(error.localizedDescription)")
16+
}
17+
}
18+
}
19+
20+
func updateInstalledRuntimes() {
21+
Task {
22+
do {
23+
let runtimes = try await self.runtimeService.localInstalledRuntimes()
24+
DispatchQueue.main.async {
25+
self.installedRuntimes = runtimes
26+
}
27+
} catch {
28+
Logger.appState.error("Error loading installed runtimes: \(error.localizedDescription)")
29+
}
30+
}
31+
}
32+
}

Xcodes/Backend/AppState+Update.swift

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import Version
55
import SwiftSoup
66
import struct XCModel.Xcode
77
import AppleAPI
8+
import XcodesKit
89

910
extension AppState {
1011

@@ -36,6 +37,8 @@ extension AppState {
3637

3738
func update() {
3839
guard !isUpdating else { return }
40+
updateDownloadableRuntimes()
41+
updateInstalledRuntimes()
3942
updatePublisher = updateSelectedXcodePath()
4043
.flatMap { _ in
4144
self.updateAvailableXcodes(from: self.dataSource)
@@ -125,6 +128,21 @@ extension AppState {
125128
withIntermediateDirectories: true)
126129
try data.write(to: Path.cacheFile.url)
127130
}
131+
132+
// MARK: Runtime Cache
133+
134+
func loadCacheDownloadableRuntimes() throws {
135+
guard let data = Current.files.contents(atPath: Path.runtimeCacheFile.string) else { return }
136+
let runtimes = try JSONDecoder().decode([DownloadableRuntime].self, from: data)
137+
self.downloadableRuntimes = runtimes
138+
}
139+
140+
func cacheDownloadableRuntimes(_ runtimes: [DownloadableRuntime]) throws {
141+
let data = try JSONEncoder().encode(runtimes)
142+
try FileManager.default.createDirectory(at: Path.runtimeCacheFile.url.deletingLastPathComponent(),
143+
withIntermediateDirectories: true)
144+
try data.write(to: Path.runtimeCacheFile.url)
145+
}
128146
}
129147

130148
extension AppState {

Xcodes/Backend/AppState.swift

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,11 @@ import KeychainAccess
77
import Path
88
import Version
99
import os.log
10+
import XcodesKit
1011

1112
class AppState: ObservableObject {
1213
private let client = AppleAPI.Client()
14+
internal let runtimeService = RuntimeService()
1315

1416
// MARK: - Published Properties
1517

@@ -99,6 +101,12 @@ class AppState: ObservableObject {
99101
Current.defaults.set(showOpenInRosettaOption, forKey: "showOpenInRosettaOption")
100102
}
101103
}
104+
105+
// MARK: - Runtimes
106+
107+
@Published var downloadableRuntimes: [DownloadableRuntime] = []
108+
@Published var installedRuntimes: [CoreSimulatorRuntimeInfo] = []
109+
102110
// MARK: - Publisher Cancellables
103111

104112
var cancellables = Set<AnyCancellable>()
@@ -136,6 +144,7 @@ class AppState: ObservableObject {
136144
init() {
137145
guard !isTesting else { return }
138146
try? loadCachedAvailableXcodes()
147+
try? loadCacheDownloadableRuntimes()
139148
checkIfHelperIsInstalled()
140149
setupAutoInstallTimer()
141150
setupDefaults()
@@ -783,6 +792,21 @@ class AppState: ObservableObject {
783792
self.allXcodes = newAllXcodes.sorted { $0.version > $1.version }
784793
}
785794

795+
// MARK: Runtimes
796+
func getRunTimes(xcode: Xcode) -> [DownloadableRuntime] {
797+
798+
let builds = xcode.sdks?.allBuilds()
799+
800+
let runtime = builds?.flatMap { sdkBuild in
801+
downloadableRuntimes.filter {
802+
$0.simulatorVersion.buildUpdate == sdkBuild
803+
}
804+
}
805+
// appState.installedRuntimes has a list of builds that user has installed.
806+
807+
return runtime ?? []
808+
}
809+
786810
// MARK: - Private
787811

788812
private func uninstallXcode(path: Path) -> AnyPublisher<Void, Error> {

Xcodes/Backend/Entry+.swift

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
import Foundation
22
import Path
33

4-
extension Entry {
5-
static func isAppBundle(kind: Kind, path: Path) -> Bool {
6-
kind == .directory &&
4+
extension Path {
5+
static func isAppBundle(path: Path) -> Bool {
6+
path.isDirectory &&
77
path.extension == "app" &&
88
!path.isSymlink
99
}
10-
static func infoPlist(kind: Kind, path: Path) -> InfoPlist? {
10+
static func infoPlist(path: Path) -> InfoPlist? {
1111
let infoPlistPath = path.join("Contents").join("Info.plist")
1212
guard
1313
let infoPlistData = try? Data(contentsOf: infoPlistPath.url),
@@ -18,10 +18,10 @@ extension Entry {
1818
}
1919

2020
var isAppBundle: Bool {
21-
Entry.isAppBundle(kind: kind, path: path)
21+
Path.isAppBundle(path: self)
2222
}
2323

2424
var infoPlist: InfoPlist? {
25-
Entry.infoPlist(kind: kind, path: path)
25+
Path.infoPlist(path: self)
2626
}
2727
}

Xcodes/Backend/Environment.swift

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import Foundation
33
import Path
44
import AppleAPI
55
import KeychainAccess
6-
6+
import XcodesKit
77
/**
88
Lightweight dependency injection using global mutable state :P
99

@@ -166,7 +166,7 @@ public struct Files {
166166
public var installedXcodes = _installedXcodes
167167

168168
public func installedXcode(destination: Path) -> InstalledXcode? {
169-
if Entry.isAppBundle(kind: destination.isDirectory ? .directory : .file, path: destination) && Entry.infoPlist(kind: destination.isDirectory ? .directory : .file, path: destination)?.bundleID == "com.apple.dt.Xcode" {
169+
if Path.isAppBundle(path: destination) && Path.infoPlist(path: destination)?.bundleID == "com.apple.dt.Xcode" {
170170
return InstalledXcode.init(path: destination)
171171
} else {
172172
return nil
@@ -175,9 +175,9 @@ public struct Files {
175175
}
176176

177177
private func _installedXcodes(destination: Path) -> [InstalledXcode] {
178-
((try? destination.ls()) ?? [])
178+
destination.ls()
179179
.filter { $0.isAppBundle && $0.infoPlist?.bundleID == "com.apple.dt.Xcode" }
180-
.map { $0.path }
180+
.map { $0 }
181181
.compactMap(InstalledXcode.init)
182182
}
183183

Xcodes/Backend/Logger.swift

Lines changed: 0 additions & 10 deletions
This file was deleted.

Xcodes/Backend/Path+.swift

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,4 +28,8 @@ extension Path {
2828
}
2929
return path
3030
}
31+
32+
static var runtimeCacheFile: Path {
33+
return xcodesApplicationSupport/"downloadable-runtimes.json"
34+
}
3135
}

0 commit comments

Comments
 (0)