From 7b9ab2488e2f52c4b759b62b55b5158fae03b073 Mon Sep 17 00:00:00 2001 From: Riley Testut Date: Tue, 2 May 2023 14:21:55 -0500 Subject: [PATCH] Fixes accidentally deleting Games directory during sync in rare circumstances MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit If a Game with empty filename happens to be deleted (e.g. during sync merge), it will accidentally delete the *entire* Games folder due to its fileURL being “Games/[empty]”. To prevent this, we now explicitly check that a Game’s identifier isn’t empty AND that that Game.fileURL doesn’t point to a directory before deleting local files. --- Delta/Database/Model/Human/Game.swift | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/Delta/Database/Model/Human/Game.swift b/Delta/Database/Model/Human/Game.swift index 18987cd..42ab887 100644 --- a/Delta/Database/Model/Human/Game.swift +++ b/Delta/Database/Model/Human/Game.swift @@ -101,12 +101,18 @@ extension Game super.prepareForDeletion() guard let managedObjectContext = self.managedObjectContext else { return } + + // If filename == empty string (e.g. during merge), ignore this deletion. + // Otherwise, we may accidentally delete the entire Games directory! + guard !self.filename.isEmpty else { return } // If a game with the same identifier is also currently being inserted, Core Data is more than likely resolving a conflict by deleting the previous instance // In this case, we make sure we DON'T delete the game file + misc other Core Data relationships, or else we'll just lose all that data guard !managedObjectContext.insertedObjects.contains(where: { ($0 as? Game)?.identifier == self.identifier }) else { return } - guard FileManager.default.fileExists(atPath: self.fileURL.path) else { return } + // Double-check fileURL is NOT actually a directory, which we should never delete. + var isDirectory: ObjCBool = false + guard FileManager.default.fileExists(atPath: self.fileURL.path, isDirectory: &isDirectory), !isDirectory.boolValue else { return } do {