mirror of
https://github.com/XcodesOrg/XcodesApp.git
synced 2026-03-25 08:55:46 +00:00
Simplify Version comparison
This commit is contained in:
parent
faad4c2ab7
commit
ed023218b8
4 changed files with 24 additions and 44 deletions
|
|
@ -44,7 +44,7 @@ extension AppState {
|
|||
}
|
||||
.handleEvents(receiveOutput: { installedXcode in
|
||||
DispatchQueue.main.async {
|
||||
guard let index = self.allXcodes.firstIndex(where: { $0.version == installedXcode.version || $0.version.isEquivalentForDeterminingIfInstalled(toInstalled: installedXcode.version) }) else { return }
|
||||
guard let index = self.allXcodes.firstIndex(where: { $0.version.isEquivalent(to: installedXcode.version) }) else { return }
|
||||
self.allXcodes[index].installState = .installed
|
||||
}
|
||||
})
|
||||
|
|
@ -54,7 +54,7 @@ extension AppState {
|
|||
private func getXcodeArchive(_ installationType: InstallationType, downloader: Downloader) -> AnyPublisher<(AvailableXcode, URL), Error> {
|
||||
switch installationType {
|
||||
case .version(let availableXcode):
|
||||
if let installedXcode = Current.files.installedXcodes(Path.root/"Applications").first(where: { $0.version.isEqualWithoutBuildMetadataIdentifiers(to: availableXcode.version) }) {
|
||||
if let installedXcode = Current.files.installedXcodes(Path.root/"Applications").first(where: { $0.version.isEquivalent(to: availableXcode.version) }) {
|
||||
return Fail(error: InstallationError.versionAlreadyInstalled(installedXcode))
|
||||
.eraseToAnyPublisher()
|
||||
}
|
||||
|
|
@ -344,7 +344,7 @@ extension AppState {
|
|||
|
||||
func setInstallationStep(of version: Version, to step: InstallationStep) {
|
||||
DispatchQueue.main.async {
|
||||
guard let index = self.allXcodes.firstIndex(where: { $0.version.buildMetadataIdentifiers == version.buildMetadataIdentifiers || $0.version.isEquivalentForDeterminingIfInstalled(toInstalled: version) }) else { return }
|
||||
guard let index = self.allXcodes.firstIndex(where: { $0.version.isEquivalent(to: version) }) else { return }
|
||||
self.allXcodes[index].installState = .installing(step)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -70,7 +70,7 @@ extension AppState {
|
|||
// /download/more doesn't include build numbers, so we trust that if the version number and prerelease identifiers are the same that they're the same build.
|
||||
// If an Xcode version is listed on both sites then prefer the one on /download because the build metadata is used to compare against installed Xcodes.
|
||||
let xcodes = releasedXcodes.filter { releasedXcode in
|
||||
prereleaseXcodes.contains { $0.version.isEqualWithoutBuildMetadataIdentifiers(to: releasedXcode.version) } == false
|
||||
prereleaseXcodes.contains { $0.version.isEquivalent(to: releasedXcode.version) } == false
|
||||
} + prereleaseXcodes
|
||||
return xcodes
|
||||
}
|
||||
|
|
|
|||
|
|
@ -369,14 +369,14 @@ class AppState: ObservableObject {
|
|||
// Xcode Releases should have all versions
|
||||
// Apple didn't used to keep all prerelease versions around but has started to recently
|
||||
else if !allAvailableXcodeVersions.contains(where: { version in
|
||||
version.isEquivalentForDeterminingIfInstalled(toInstalled: installedXcode.version)
|
||||
version.isEquivalent(to: installedXcode.version)
|
||||
}) {
|
||||
allAvailableXcodeVersions.append(installedXcode.version)
|
||||
}
|
||||
// If an installed version is the same as one that's listed online which doesn't have build metadata, replace it with the installed version
|
||||
// This was originally added for Apple versions
|
||||
else if let index = allAvailableXcodeVersions.firstIndex(where: { version in
|
||||
version.isEquivalentForDeterminingIfInstalled(toInstalled: installedXcode.version) &&
|
||||
version.isEquivalent(to: installedXcode.version) &&
|
||||
version.buildMetadataIdentifiers.isEmpty
|
||||
}) {
|
||||
allAvailableXcodeVersions[index] = installedXcode.version
|
||||
|
|
@ -388,10 +388,7 @@ class AppState: ObservableObject {
|
|||
.sorted(by: { $0.0 > $1.0 })
|
||||
.map { availableXcodeVersion, availableXcode in
|
||||
let installedXcode = installedXcodes.first(where: { installedXcode in
|
||||
// Checking equality for Xcode Releases version
|
||||
availableXcodeVersion == installedXcode.version ||
|
||||
// Check more carefully for Apple version
|
||||
availableXcodeVersion.isEquivalentForDeterminingIfInstalled(toInstalled: installedXcode.version)
|
||||
availableXcodeVersion.isEquivalent(to: installedXcode.version)
|
||||
})
|
||||
|
||||
// If the existing install state is "installing", keep it
|
||||
|
|
|
|||
|
|
@ -1,41 +1,24 @@
|
|||
import Version
|
||||
|
||||
public extension Version {
|
||||
func isEqualWithoutBuildMetadataIdentifiers(to other: Version) -> Bool {
|
||||
return major == other.major &&
|
||||
minor == other.minor &&
|
||||
patch == other.patch &&
|
||||
prereleaseIdentifiers == other.prereleaseIdentifiers
|
||||
}
|
||||
|
||||
/// If release versions, don't compare build metadata because that's not provided in the /downloads/more list
|
||||
/// if beta versions, compare build metadata because it's available in versions.plist
|
||||
func isEquivalentForDeterminingIfInstalled(toInstalled installed: Version) -> Bool {
|
||||
let isBeta = !prereleaseIdentifiers.isEmpty
|
||||
let otherIsBeta = !installed.prereleaseIdentifiers.isEmpty
|
||||
|
||||
if isBeta && otherIsBeta {
|
||||
if buildMetadataIdentifiers.isEmpty {
|
||||
return major == installed.major &&
|
||||
minor == installed.minor &&
|
||||
patch == installed.patch &&
|
||||
prereleaseIdentifiers.map { $0.lowercased() } == installed.prereleaseIdentifiers.map { $0.lowercased() }
|
||||
}
|
||||
else {
|
||||
return major == installed.major &&
|
||||
minor == installed.minor &&
|
||||
patch == installed.patch &&
|
||||
prereleaseIdentifiers.map { $0.lowercased() } == installed.prereleaseIdentifiers.map { $0.lowercased() } &&
|
||||
buildMetadataIdentifiers.map { $0.lowercased() } == installed.buildMetadataIdentifiers.map { $0.lowercased() }
|
||||
}
|
||||
/// Determines if two Xcode versions should be treated equivalently. This is not the same as equality.
|
||||
///
|
||||
/// We need a way to determine if two Xcode versions are the same without always having full information, and supporting different data sources.
|
||||
/// For example, the Apple data source often doesn't have build metadata identifiers.
|
||||
func isEquivalent(to other: Version) -> Bool {
|
||||
// If we don't have build metadata identifiers for both Versions, compare major, minor, patch and prerelease identifiers.
|
||||
if buildMetadataIdentifiers.isEmpty || other.buildMetadataIdentifiers.isEmpty {
|
||||
return major == other.major &&
|
||||
minor == other.minor &&
|
||||
patch == other.patch &&
|
||||
prereleaseIdentifiers.map { $0.lowercased() } == other.prereleaseIdentifiers.map { $0.lowercased() }
|
||||
// If we have build metadata identifiers for both, we can ignore the prerelease identifiers.
|
||||
} else {
|
||||
return major == other.major &&
|
||||
minor == other.minor &&
|
||||
patch == other.patch &&
|
||||
buildMetadataIdentifiers.map { $0.lowercased() } == other.buildMetadataIdentifiers.map { $0.lowercased() }
|
||||
}
|
||||
else if !isBeta && !otherIsBeta {
|
||||
return major == installed.major &&
|
||||
minor == installed.minor &&
|
||||
patch == installed.patch
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
var descriptionWithoutBuildMetadata: String {
|
||||
|
|
|
|||
Loading…
Reference in a new issue