mirror of
https://github.com/SideStore/SideStore.git
synced 2026-02-09 06:43:25 +01:00
Verifies source’s identifier doesn’t match existing sources when adding
This commit is contained in:
@@ -365,8 +365,12 @@ extension AppManager
|
|||||||
let action = await UIAlertAction(title: NSLocalizedString("Add Source", comment: ""), style: .default)
|
let action = await UIAlertAction(title: NSLocalizedString("Add Source", comment: ""), style: .default)
|
||||||
try await presentingViewController.presentConfirmationAlert(title: title, message: message, primaryAction: action)
|
try await presentingViewController.presentConfirmationAlert(title: title, message: message, primaryAction: action)
|
||||||
|
|
||||||
// Wait for fetch to finish before saving context.
|
// Wait for fetch to finish before saving context to make
|
||||||
_ = try await fetchedSource
|
// sure there isn't already a source with this identifier.
|
||||||
|
let sourceExists = try await fetchedSource.isAdded
|
||||||
|
|
||||||
|
// This is just a sanity check, so pass nil for previousSourceName to keep code simple.
|
||||||
|
guard !sourceExists else { throw SourceError.duplicate(source, previousSourceName: nil) }
|
||||||
|
|
||||||
try await context.performAsync {
|
try await context.performAsync {
|
||||||
try context.save()
|
try context.save()
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ extension SourceError
|
|||||||
case duplicateVersion
|
case duplicateVersion
|
||||||
|
|
||||||
case changedID
|
case changedID
|
||||||
|
case duplicate
|
||||||
}
|
}
|
||||||
|
|
||||||
static func unsupported(_ source: Source) -> SourceError { SourceError(code: .unsupported, source: source) }
|
static func unsupported(_ source: Source) -> SourceError { SourceError(code: .unsupported, source: source) }
|
||||||
@@ -30,6 +31,7 @@ extension SourceError
|
|||||||
static func duplicateVersion(_ version: String, for app: StoreApp, source: Source) -> SourceError { SourceError(code: .duplicateVersion, source: source, app: app, version: version) }
|
static func duplicateVersion(_ version: String, for app: StoreApp, source: Source) -> SourceError { SourceError(code: .duplicateVersion, source: source, app: app, version: version) }
|
||||||
|
|
||||||
static func changedID(_ identifier: String, previousID: String, source: Source) -> SourceError { SourceError(code: .changedID, source: source, sourceID: identifier, previousSourceID: previousID) }
|
static func changedID(_ identifier: String, previousID: String, source: Source) -> SourceError { SourceError(code: .changedID, source: source, sourceID: identifier, previousSourceID: previousID) }
|
||||||
|
static func duplicate(_ source: Source, previousSourceName: String?) -> SourceError { SourceError(code: .duplicate, source: source, previousSourceName: previousSourceName) }
|
||||||
}
|
}
|
||||||
|
|
||||||
struct SourceError: ALTLocalizedError
|
struct SourceError: ALTLocalizedError
|
||||||
@@ -43,6 +45,8 @@ struct SourceError: ALTLocalizedError
|
|||||||
var bundleID: String?
|
var bundleID: String?
|
||||||
var version: String?
|
var version: String?
|
||||||
|
|
||||||
|
@UserInfoValue var previousSourceName: String?
|
||||||
|
|
||||||
// Store in userInfo so they can be viewed from Error Log.
|
// Store in userInfo so they can be viewed from Error Log.
|
||||||
@UserInfoValue var sourceID: String?
|
@UserInfoValue var sourceID: String?
|
||||||
@UserInfoValue var previousSourceID: String?
|
@UserInfoValue var previousSourceID: String?
|
||||||
@@ -79,6 +83,13 @@ struct SourceError: ALTLocalizedError
|
|||||||
case .changedID:
|
case .changedID:
|
||||||
let failureReason = String(format: NSLocalizedString("The identifier of the source “%@” has changed.", comment: ""), self.$source.name)
|
let failureReason = String(format: NSLocalizedString("The identifier of the source “%@” has changed.", comment: ""), self.$source.name)
|
||||||
return failureReason
|
return failureReason
|
||||||
|
|
||||||
|
case .duplicate:
|
||||||
|
let baseMessage = String(format: NSLocalizedString("A source with the identifier '%@' already exists", comment: ""), self.$source.identifier)
|
||||||
|
guard let previousSourceName else { return baseMessage + "." }
|
||||||
|
|
||||||
|
let failureReason = baseMessage + " (“\(previousSourceName)”)."
|
||||||
|
return failureReason
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -86,6 +97,10 @@ struct SourceError: ALTLocalizedError
|
|||||||
switch self.code
|
switch self.code
|
||||||
{
|
{
|
||||||
case .changedID: return NSLocalizedString("A source cannot change its identifier once added. This source can no longer be updated.", comment: "")
|
case .changedID: return NSLocalizedString("A source cannot change its identifier once added. This source can no longer be updated.", comment: "")
|
||||||
|
case .duplicate:
|
||||||
|
let failureReason = NSLocalizedString("Please remove the existing source in order to add this one.", comment: "")
|
||||||
|
return failureReason
|
||||||
|
|
||||||
default: return nil
|
default: return nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -283,13 +283,31 @@ private extension SourcesViewController
|
|||||||
AppManager.shared.fetchSource(sourceURL: url, dependencies: dependencies) { (result) in
|
AppManager.shared.fetchSource(sourceURL: url, dependencies: dependencies) { (result) in
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
|
// Use @Managed before calling perform() to keep
|
||||||
|
// strong reference to source.managedObjectContext.
|
||||||
@Managed var source = try result.get()
|
@Managed var source = try result.get()
|
||||||
|
|
||||||
DispatchQueue.main.async {
|
let backgroundContext = DatabaseManager.shared.persistentContainer.newBackgroundContext()
|
||||||
self.showSourceDetails(for: source)
|
backgroundContext.perform {
|
||||||
|
do
|
||||||
|
{
|
||||||
|
let predicate = NSPredicate(format: "%K == %@", #keyPath(Source.identifier), $source.identifier)
|
||||||
|
if let existingSource = Source.first(satisfying: predicate, in: backgroundContext)
|
||||||
|
{
|
||||||
|
throw SourceError.duplicate(source, previousSourceName: existingSource.name)
|
||||||
|
}
|
||||||
|
|
||||||
|
DispatchQueue.main.async {
|
||||||
|
self.showSourceDetails(for: source)
|
||||||
|
}
|
||||||
|
|
||||||
|
finish(.success(()))
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
finish(.failure(error))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
finish(.success(()))
|
|
||||||
}
|
}
|
||||||
catch
|
catch
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in New Issue
Block a user