Skip to content

Commit

Permalink
mangerlahn#327 Fix crash when loading repository
Browse files Browse the repository at this point in the history
  • Loading branch information
mangerlahn committed Dec 18, 2023
1 parent 69eb0c4 commit e60f4c7
Showing 1 changed file with 21 additions and 11 deletions.
32 changes: 21 additions & 11 deletions Latest/Model/Update Repository/UpdateRepository.swift
Original file line number Diff line number Diff line change
Expand Up @@ -57,48 +57,58 @@ class UpdateRepository {
}

/// Entries are still being fetched, add the request to the queue.
queue.async {
if self.entries == nil {
self.pendingRequests.append(checkApp)
queue.async { [weak self] in
guard let self else { return }

if self.pendingRequests != nil {
self.pendingRequests?.append(checkApp)
} else {
checkApp()
}
}
}

/// List of entries stored within the repository.
private var entries: [Entry]?
private var entries: [Entry]!

/// A list of requests being performed while the repository was still fetching data.
private var pendingRequests: [() -> Void] = []
///
/// It also acts as a flag for whether initialization finished. The array is initialized when the repository is created. It will be set to nil once `finalize()` is being called.
private var pendingRequests: [() -> Void]? = []

/// A set of bundle identifiers for which update checking is currently not supported.
private var unsupportedBundleIdentifiers: Set<String>!

/// Sets the given entries and performs pending requests.
private func finalize() {
queue.async {
queue.async { [weak self] in
guard let self else { return }
guard let pendingRequests else {
fatalError("Finalize must only be called once!")
}

// Perform any pending requests
self.pendingRequests.forEach { request in
pendingRequests.forEach { request in
request()
}
self.pendingRequests.removeAll()

// Mark repository as loaded.
self.pendingRequests = nil
}
}

/// Returns a repository entry for the given name, if available.
private func entry(for bundle: App.Bundle) -> Entry? {
let name = bundle.fileURL.lastPathComponent

// Don't return an entry for unsupported apps
guard let entries, !unsupportedBundleIdentifiers.contains(bundle.bundleIdentifier) else { return nil }
guard !unsupportedBundleIdentifiers.contains(bundle.bundleIdentifier) else { return nil }

// Finding the correct entry is not trivial as there is no bundle identifier stored in an entry. We have a list of app names (could be ambiguous) and a list of bundle identifier guesses.
// However, both app names and bundle identifiers may occur in more than one entry:
// - App Names: Might occur multiple times for similar apps (Telegram.app for Desktop vs. Telegram.app for Mac)
// - Bundle Identifiers: Might occur multiple times for apps in bundles (com.microsoft.word in Word.app and Office bundle)
//
// Strategy: Find all entries that point to the given app name. If only one entry comes up, return that. Otherwise, try to match bundle identifiers to narrow it down.
let name = bundle.fileURL.lastPathComponent
var possibleEntries = entries.filter { entry in
return entry.names.contains { n in
return n.caseInsensitiveCompare(name) == .orderedSame
Expand Down

0 comments on commit e60f4c7

Please sign in to comment.