mirror of
https://github.com/XcodesOrg/XcodesApp.git
synced 2025-12-25 12:14:17 +01:00
62 lines
2.5 KiB
Swift
62 lines
2.5 KiB
Swift
import Foundation
|
|
import Version
|
|
import Path
|
|
|
|
/// A version of Xcode that's already installed
|
|
public struct InstalledXcode: Equatable {
|
|
public let path: Path
|
|
/// Composed of the bundle short version from Info.plist and the product build version from version.plist
|
|
public let version: Version
|
|
|
|
public init?(path: Path) {
|
|
self.path = path
|
|
|
|
let infoPlistPath = path.join("Contents").join("Info.plist")
|
|
let versionPlistPath = path.join("Contents").join("version.plist")
|
|
guard
|
|
let infoPlistData = Current.files.contents(atPath: infoPlistPath.string),
|
|
let infoPlist = try? PropertyListDecoder().decode(InfoPlist.self, from: infoPlistData),
|
|
let bundleShortVersion = infoPlist.bundleShortVersion,
|
|
let bundleVersion = Version(tolerant: bundleShortVersion),
|
|
|
|
let versionPlistData = Current.files.contents(atPath: versionPlistPath.string),
|
|
let versionPlist = try? PropertyListDecoder().decode(VersionPlist.self, from: versionPlistData)
|
|
else { return nil }
|
|
|
|
// Installed betas don't include the beta number anywhere, so try to parse it from the filename or fall back to simply "beta"
|
|
var prereleaseIdentifiers = bundleVersion.prereleaseIdentifiers
|
|
if let filenameVersion = Version(path.basename(dropExtension: true).replacingOccurrences(of: "Xcode-", with: "")) {
|
|
prereleaseIdentifiers = filenameVersion.prereleaseIdentifiers
|
|
}
|
|
else if infoPlist.bundleIconName == "XcodeBeta", !prereleaseIdentifiers.contains("beta") {
|
|
prereleaseIdentifiers = ["beta"]
|
|
}
|
|
|
|
self.version = Version(major: bundleVersion.major,
|
|
minor: bundleVersion.minor,
|
|
patch: bundleVersion.patch,
|
|
prereleaseIdentifiers: prereleaseIdentifiers,
|
|
buildMetadataIdentifiers: [versionPlist.productBuildVersion].compactMap { $0 })
|
|
}
|
|
}
|
|
|
|
public struct InfoPlist: Decodable {
|
|
public let bundleID: String?
|
|
public let bundleShortVersion: String?
|
|
public let bundleIconName: String?
|
|
|
|
public enum CodingKeys: String, CodingKey {
|
|
case bundleID = "CFBundleIdentifier"
|
|
case bundleShortVersion = "CFBundleShortVersionString"
|
|
case bundleIconName = "CFBundleIconName"
|
|
}
|
|
}
|
|
|
|
public struct VersionPlist: Decodable {
|
|
public let productBuildVersion: String
|
|
|
|
public enum CodingKeys: String, CodingKey {
|
|
case productBuildVersion = "ProductBuildVersion"
|
|
}
|
|
}
|