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

Prevent keyNotFound error with unknown simulators #261

Open
wants to merge 4 commits into
base: main
Choose a base branch
from
Open
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
10 changes: 5 additions & 5 deletions Sources/XcodesKit/Models+Runtimes.swift
Original file line number Diff line number Diff line change
Expand Up @@ -108,18 +108,18 @@ extension DownloadableRuntime {
}

public struct InstalledRuntime: Decodable {
let build: String
let build: String? // does not apply for unusable runtimes
let deletable: Bool
let identifier: UUID
let kind: Kind
let lastUsedAt: Date?
let path: String
let platformIdentifier: Platform
let runtimeBundlePath: String
let runtimeIdentifier: String
let platformIdentifier: Platform?
let runtimeBundlePath: String? // does not apply for unusable runtimes
let runtimeIdentifier: String? // does not apply for unusable runtimes
let signatureState: String
let state: String
let version: String
let version: String? // does not apply for unusable runtimes
let sizeBytes: Int?
}

Expand Down
15 changes: 8 additions & 7 deletions Sources/XcodesKit/RuntimeInstaller.swift
Original file line number Diff line number Diff line change
Expand Up @@ -38,18 +38,16 @@ public class RuntimeInstaller {
}
}




let unusableCount = installed.removeAll { $0.state == "Unusable" }.count
installed.forEach { runtime in
let resolvedBetaNumber = downloadablesResponse.sdkToSeedMappings.first {
$0.buildUpdate == runtime.build
$0.buildUpdate == runtime.build!
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we refactor this section a bit?

Can we not use force unwrap. As a rule, I don't use them. Totally agree that it should never happen but it's bitten me in the past. Perhaps making an overloaded PrintableRuntime() to allow optionals?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure how best to achieve this, feel free to make any changes.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just my 2 cents here, personally I also try to avoid them if I can, but in this case, I would prefer a force unwrap to fail than hiding the error and providing an empty string as a default value, in that case, we would know that xcrun simctl runtime list printed something that we didn't account for, and there is probably a new state of a runtime that we should write code for. I see it as a assert/precondition and not a code smell.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@MattKiazyk can you please give an update on how you would like to proceed here?

}?.seedNumber

var result = PrintableRuntime(platform: runtime.platformIdentifier.asPlatformOS,
var result = PrintableRuntime(platform: runtime.platformIdentifier!.asPlatformOS,
betaNumber: resolvedBetaNumber,
version: runtime.version,
build: runtime.build,
version: runtime.version!,
build: runtime.build!,
state: runtime.kind)

mappedRuntimes.indices {
Expand Down Expand Up @@ -90,6 +88,9 @@ public class RuntimeInstaller {
}
}
Current.logging.log("\nNote: Bundled runtimes are indicated for the currently selected Xcode, more bundled runtimes may exist in other Xcode(s)")
if unusableCount > 0 {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I like this vs having the original Unknown 👍

Current.logging.log("Note: Found \(unusableCount) unknown downloaded runtime(s). For more info run `xcrun simctl runtime list -j`.")
}
}

public func downloadAndInstallRuntime(identifier: String, to destinationDirectory: Path, with downloader: Downloader, shouldDelete: Bool) async throws {
Expand Down
54 changes: 54 additions & 0 deletions Tests/XcodesKitTests/Fixtures/LogOutput-Runtimes_WithUnusable.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
-- iOS --
iOS 12.4 (Downloaded)
iOS 13.0 (Downloaded)
iOS 13.1 (Downloaded)
iOS 13.2.2
iOS 13.3
iOS 13.4
iOS 13.5
iOS 13.6
iOS 13.7
iOS 14.0.1
iOS 14.1
iOS 14.2
iOS 14.3
iOS 14.4
iOS 14.5
iOS 15.0
iOS 15.2
iOS 15.4
iOS 15.5 (Bundled with selected Xcode)
iOS 15.5 (Downloaded)
iOS 16.0
-- watchOS --
watchOS 6.0
watchOS 6.1.1
watchOS 6.2.1
watchOS 7.0
watchOS 7.1
watchOS 7.2
watchOS 7.4
watchOS 8.0
watchOS 8.3
watchOS 8.5 (Bundled with selected Xcode)
watchOS 9.0-beta4 (Downloaded)
watchOS 9.0 (20R362)
watchOS 9.0 (UnknownBuildNumber) (Downloaded)
-- tvOS --
tvOS 12.4
tvOS 13.0
tvOS 13.2
tvOS 13.3
tvOS 13.4
tvOS 14.0
tvOS 14.2
tvOS 14.3
tvOS 14.4
tvOS 14.5
tvOS 15.0
tvOS 15.2
tvOS 15.4 (Bundled with selected Xcode)
tvOS 16.0

Note: Bundled runtimes are indicated for the currently selected Xcode, more bundled runtimes may exist in other Xcode(s)
Note: Found 1 unknown downloaded runtime(s). For more info run `xcrun simctl runtime list -j`.
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
{
"2A6068A0-7FCF-4DB9-964D-21145EB98498" : {
"build" : "17A844",
"deletable" : true,
"identifier" : "2A6068A0-7FCF-4DB9-964D-21145EB98498",
"kind" : "Legacy Download",
"lastUsedAt" : "2022-09-24T02:57:33Z",
"path" : "\/Library\/Developer\/CoreSimulator\/Profiles\/Runtimes\/iOS 13.1.simruntime",
"platformIdentifier" : "com.apple.platform.iphonesimulator",
"runtimeBundlePath" : "\/Library\/Developer\/CoreSimulator\/Profiles\/Runtimes\/iOS 13.1.simruntime",
"runtimeIdentifier" : "com.apple.CoreSimulator.SimRuntime.iOS-13-1",
"signatureState" : "Unknown",
"sizeBytes" : 6355320832,
"state" : "Ready",
"version" : "13.1"
},
"6DE6B631-9439-4737-A65B-73F675EB77D1" : {
"build" : "20R5332f",
"deletable" : true,
"identifier" : "6DE6B631-9439-4737-A65B-73F675EB77D1",
"kind" : "Disk Image",
"mountPath" : "\/Library\/Developer\/CoreSimulator\/Volumes\/watchOS_20R362",
"path" : "\/Library\/Developer\/CoreSimulator\/Images\/6DE6B631-9439-4737-A65B-73F675EB77D1.dmg",
"platformIdentifier" : "com.apple.platform.watchsimulator",
"runtimeBundlePath" : "\/Library\/Developer\/CoreSimulator\/Volumes\/watchOS_20R362\/Library\/Developer\/CoreSimulator\/Profiles\/Runtimes\/watchOS 9.0.simruntime",
"runtimeIdentifier" : "com.apple.CoreSimulator.SimRuntime.watchOS-9-0",
"signatureState" : "Verified",
"sizeBytes" : 3604135917,
"state" : "Ready",
"version" : "9.0"
},
"6DE6B631-9439-4737-A65B-73F675EB77D2" : {
"build" : "UnknownBuildNumber",
"deletable" : true,
"identifier" : "6DE6B631-9439-4737-A65B-73F675EB77D2",
"kind" : "Disk Image",
"mountPath" : "\/Library\/Developer\/CoreSimulator\/Volumes\/watchOS_20R362",
"path" : "\/Library\/Developer\/CoreSimulator\/Images\/6DE6B631-9439-4737-A65B-73F675EB77D1.dmg",
"platformIdentifier" : "com.apple.platform.watchsimulator",
"runtimeBundlePath" : "\/Library\/Developer\/CoreSimulator\/Volumes\/watchOS_20R362\/Library\/Developer\/CoreSimulator\/Profiles\/Runtimes\/watchOS 9.0.simruntime",
"runtimeIdentifier" : "com.apple.CoreSimulator.SimRuntime.watchOS-9-0",
"signatureState" : "Verified",
"sizeBytes" : 3604135917,
"state" : "Ready",
"version" : "9.0"
},
"7A032D54-0D93-4E04-80B9-4CB207136C3F" : {
"build" : "16G73",
"deletable" : true,
"identifier" : "7A032D54-0D93-4E04-80B9-4CB207136C3F",
"kind" : "Legacy Download",
"path" : "\/Library\/Developer\/CoreSimulator\/Profiles\/Runtimes\/iOS 12.4.simruntime",
"platformIdentifier" : "com.apple.platform.iphonesimulator",
"runtimeBundlePath" : "\/Library\/Developer\/CoreSimulator\/Profiles\/Runtimes\/iOS 12.4.simruntime",
"runtimeIdentifier" : "com.apple.CoreSimulator.SimRuntime.iOS-12-4",
"signatureState" : "Unknown",
"sizeBytes" : 4980690944,
"state" : "Ready",
"version" : "12.4"
},
"91B92361-CD02-4AF7-8DFE-DE8764AA949F" : {
"build" : "19F70",
"deletable" : false,
"identifier" : "91B92361-CD02-4AF7-8DFE-DE8764AA949F",
"kind" : "Bundled with Xcode",
"path" : "\/Applications\/Xcode-13.4.1.app\/Contents\/Developer\/Platforms\/iPhoneOS.platform\/Library\/Developer\/CoreSimulator\/Profiles\/Runtimes\/iOS.simruntime",
"platformIdentifier" : "com.apple.platform.iphonesimulator",
"runtimeBundlePath" : "\/Applications\/Xcode-13.4.1.app\/Contents\/Developer\/Platforms\/iPhoneOS.platform\/Library\/Developer\/CoreSimulator\/Profiles\/Runtimes\/iOS.simruntime",
"runtimeIdentifier" : "com.apple.CoreSimulator.SimRuntime.iOS-15-5",
"signatureState" : "Unknown",
"sizeBytes" : 3310809088,
"state" : "Ready",
"version" : "15.5"
},
"630146EA-A027-42B1-AC25-BE4EA018DE90" : {
"build" : "17A577",
"deletable" : true,
"identifier" : "630146EA-A027-42B1-AC25-BE4EA018DE90",
"kind" : "Legacy Download",
"path" : "\/Library\/Developer\/CoreSimulator\/Profiles\/Runtimes\/iOS 13.0.simruntime",
"platformIdentifier" : "com.apple.platform.iphonesimulator",
"runtimeBundlePath" : "\/Library\/Developer\/CoreSimulator\/Profiles\/Runtimes\/iOS 13.0.simruntime",
"runtimeIdentifier" : "com.apple.CoreSimulator.SimRuntime.iOS-13-0",
"signatureState" : "Unknown",
"sizeBytes" : 6369886208,
"state" : "Ready",
"version" : "13.0"
},
"AAD753FE-A798-479C-B6D6-41259B063DD6" : {
"build" : "19F70",
"deletable" : true,
"identifier" : "AAD753FE-A798-479C-B6D6-41259B063DD6",
"kind" : "Legacy Download",
"path" : "\/Library\/Developer\/CoreSimulator\/Profiles\/Runtimes\/iOS 15.5.simruntime",
"platformIdentifier" : "com.apple.platform.iphonesimulator",
"runtimeBundlePath" : "\/Library\/Developer\/CoreSimulator\/Profiles\/Runtimes\/iOS 15.5.simruntime",
"runtimeIdentifier" : "com.apple.CoreSimulator.SimRuntime.iOS-15-5",
"signatureState" : "Unknown",
"state" : "Ready",
"version" : "15.5"
},
"BE68168B-7AC8-4A1F-A344-15DFCC375457" : {
"build" : "19L439",
"deletable" : false,
"identifier" : "BE68168B-7AC8-4A1F-A344-15DFCC375457",
"kind" : "Bundled with Xcode",
"path" : "\/Applications\/Xcode-13.4.1.app\/Contents\/Developer\/Platforms\/AppleTVOS.platform\/Library\/Developer\/CoreSimulator\/Profiles\/Runtimes\/tvOS.simruntime",
"platformIdentifier" : "com.apple.platform.appletvsimulator",
"runtimeBundlePath" : "\/Applications\/Xcode-13.4.1.app\/Contents\/Developer\/Platforms\/AppleTVOS.platform\/Library\/Developer\/CoreSimulator\/Profiles\/Runtimes\/tvOS.simruntime",
"runtimeIdentifier" : "com.apple.CoreSimulator.SimRuntime.tvOS-15-4",
"signatureState" : "Unknown",
"sizeBytes" : 1615810560,
"state" : "Ready",
"version" : "15.4"
},
"F8D81829-354C-4EB0-828D-83DC765B27E1" : {
"build" : "19T241",
"deletable" : false,
"identifier" : "F8D81829-354C-4EB0-828D-83DC765B27E1",
"kind" : "Bundled with Xcode",
"path" : "\/Applications\/Xcode-13.4.1.app\/Contents\/Developer\/Platforms\/WatchOS.platform\/Library\/Developer\/CoreSimulator\/Profiles\/Runtimes\/watchOS.simruntime",
"platformIdentifier" : "com.apple.platform.watchsimulator",
"runtimeBundlePath" : "\/Applications\/Xcode-13.4.1.app\/Contents\/Developer\/Platforms\/WatchOS.platform\/Library\/Developer\/CoreSimulator\/Profiles\/Runtimes\/watchOS.simruntime",
"runtimeIdentifier" : "com.apple.CoreSimulator.SimRuntime.watchOS-8-5",
"signatureState" : "Unknown",
"sizeBytes" : 1540558848,
"state" : "Ready",
"version" : "8.5"
},
"820783CB-C389-4006-B2D2-D063F3FD10A1" : {
"deletable" : true,
"identifier" : "820783CB-C389-4006-B2D2-D063F3FD10A1",
"kind" : "Disk Image",
"path" : "\/Library\/Developer\/CoreSimulator\/Images\/Inbox\/820783CB-C389-4006-B2D2-D063F3FD10A1.dmg",
"signatureState" : "Missing",
"sizeBytes" : 5304795932,
"state" : "Unusable",
"unusableErrorDetail" : "Error Domain=SimDiskImageErrorDomain Code=3 \"Missing Signature\" UserInfo={NSLocalizedDescription=Missing Signature, unusableErrorDetail=}",
"unusableErrorMessage" : "Missing Signature",
"unusableSubstate" : "Missing Signature"
}
}
13 changes: 13 additions & 0 deletions Tests/XcodesKitTests/RuntimeTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,19 @@ final class RuntimeTests: XCTestCase {
XCTAssertEqual(log, try String(contentsOf: outputUrl))
}

func test_printAvailableRuntimes_WithUnusable() async throws {
var log = ""
XcodesKit.Current.logging.log = { log.append($0 + "\n") }
mockDownloadables()
Current.shell.installedRuntimes = {
let url = Bundle.module.url(forResource: "ShellOutput-InstalledRuntimes_WithUnusable", withExtension: "json", subdirectory: "Fixtures")!
return Promise.value((0, try! String(contentsOf: url), ""))
}
try await runtimeInstaller.printAvailableRuntimes(includeBetas: false)
let outputUrl = Bundle.module.url(forResource: "LogOutput-Runtimes_WithUnusable", withExtension: "txt", subdirectory: "Fixtures")!
XCTAssertEqual(log, try String(contentsOf: outputUrl))
}

func test_wrongIdentifier() async throws {
mockDownloadables()
var resultError: RuntimeInstaller.Error? = nil
Expand Down