Properly report deleted metadatas in recursive directory delete in FileProviderEnumerator
authorClaudio Cambra <claudio.cambra@nextcloud.com>
Sat, 18 Mar 2023 12:24:37 +0000 (13:24 +0100)
committerClaudio Cambra <claudio.cambra@nextcloud.com>
Fri, 12 May 2023 05:29:55 +0000 (13:29 +0800)
Signed-off-by: Claudio Cambra <claudio.cambra@nextcloud.com>
shell_integration/MacOSX/NextcloudIntegration/FileProviderExt/Database/NextcloudFilesDatabaseManager.swift
shell_integration/MacOSX/NextcloudIntegration/FileProviderExt/FileProviderEnumerator.swift

index bdd0a6b73a04108ffc9fdb3f0735f40b74e42016..a36f1b766d36e31aae9e0d68833f08743c60b209 100644 (file)
@@ -361,29 +361,38 @@ class NextcloudFilesDatabaseManager : NSObject {
     }
 
     // Deletes all metadatas related to the info of the directory provided
-    func deleteDirectoryAndSubdirectoriesMetadata(ocId: String) {
+    func deleteDirectoryAndSubdirectoriesMetadata(ocId: String) -> [NextcloudItemMetadataTable]? {
         let database = ncDatabase()
         guard let directoryMetadata = database.objects(NextcloudItemMetadataTable.self).filter("ocId == %@ AND directory == true", ocId).first else {
             Logger.ncFilesDatabase.error("Could not find directory metadata for ocId \(ocId, privacy: .public). Not proceeding with deletion")
-            return
+            return nil
         }
 
+        var deletedMetadatas: [NextcloudItemMetadataTable] = []
+
         let directoryUrlPath = directoryMetadata.serverUrl + "/" + directoryMetadata.fileName
         let results = database.objects(NextcloudItemMetadataTable.self).filter("account == %@ AND serverUrl BEGINSWITH %@", directoryMetadata.account, directoryUrlPath)
 
         for result in results {
             deleteItemMetadata(ocId: result.ocId)
             deleteLocalFileMetadata(ocId: result.ocId)
+
+            deletedMetadatas.append(NextcloudItemMetadataTable(value: result))
         }
 
         do {
             try database.write {
                 Logger.ncFilesDatabase.debug("Deleting root directory metadata in recursive delete. ocID: \(directoryMetadata.ocId, privacy: .public), etag: \(directoryMetadata.etag, privacy: .public), serverUrl: \(directoryUrlPath)")
+
                 database.delete(results)
+
+                return deletedMetadatas
             }
         } catch let error {
             Logger.ncFilesDatabase.error("Could not delete root directory metadata in recursive delete. ocID: \(directoryMetadata.ocId, privacy: .public), etag: \(directoryMetadata.etag, privacy: .public), serverUrl: \(directoryUrlPath), received error: \(error.localizedDescription, privacy: .public)")
         }
+
+        return nil
     }
 
     func renameDirectoryAndPropagateToChildren(ocId: String, newServerUrl: String, newFileName: String) -> [NextcloudItemMetadataTable]? {
index ec28fb0e87fea7e3d064d3367c6f516f33688916..49b83c07998a99f00b450a1d5336d61be07a96c6 100644 (file)
@@ -281,6 +281,13 @@ class FileProviderEnumerator: NSObject, NSFileProviderEnumerator {
         // No matter what happens here we finish enumeration in some way, either from the error
         // handling below or from the completeChangesObserver
         FileProviderEnumerator.readServerUrl(serverUrl, ncAccount: ncAccount, ncKit: ncKit, stopAtMatchingEtags: true) { _, newMetadatas, updatedMetadatas, deletedMetadatas, readError in
+
+            // If we get a 404 we might add more deleted metadatas
+            var currentDeletedMetadatas: [NextcloudItemMetadataTable] = []
+            if let notNilDeletedMetadatas = deletedMetadatas {
+                currentDeletedMetadatas = notNilDeletedMetadatas
+            }
+
             guard readError == nil else {
                 Logger.enumeration.error("Finishing enumeration of changes for user: \(self.ncAccount.ncKitAccount, privacy: OSLogPrivacy.auto(mask: .hash)) with serverUrl: \(self.serverUrl, privacy: OSLogPrivacy.auto(mask: .hash)) with error: \(readError!.localizedDescription, privacy: .public)")
 
@@ -298,7 +305,11 @@ class FileProviderEnumerator: NSObject, NSFileProviderEnumerator {
 
                     let dbManager = NextcloudFilesDatabaseManager.shared
                     if itemMetadata.directory {
-                        dbManager.deleteDirectoryAndSubdirectoriesMetadata(ocId: itemMetadata.ocId)
+                        if let deletedDirectoryMetadatas = dbManager.deleteDirectoryAndSubdirectoriesMetadata(ocId: itemMetadata.ocId) {
+                            currentDeletedMetadatas += deletedDirectoryMetadatas
+                        } else {
+                            Logger.enumeration.error("Something went wrong when recursively deleting directory not found.")
+                        }
                     } else {
                         dbManager.deleteItemMetadata(ocId: itemMetadata.ocId)
                     }
@@ -469,14 +480,11 @@ class FileProviderEnumerator: NSObject, NSFileProviderEnumerator {
                     if nkReadError.isNotFoundError {
                         Logger.enumeration.info("404 error means item no longer exists. Deleting metadata and reporting as deletion without error")
 
-                        guard let directoryItemMetadata = dbManager.itemMetadataFromOcId(directoryMetadata.ocId) else {
-                            Logger.enumeration.error("Can't delete directory properly as item metadata not found...")
-                            dispatchGroup.leave()
-                            return
+                        if let deletedMetadatas = dbManager.deleteDirectoryAndSubdirectoriesMetadata(ocId: directoryMetadata.ocId) {
+                            allDeletedMetadatas += deletedMetadatas
+                        } else {
+                            Logger.enumeration.error("An error occurred while trying to delete directory and children not found in recursive scan")
                         }
-
-                        dbManager.deleteDirectoryAndSubdirectoriesMetadata(ocId: directoryMetadata.ocId)
-                        allDeletedMetadatas.append(directoryItemMetadata)
                     } else if nkReadError.isNoChangesError { // All is well, just no changed etags
                         Logger.enumeration.info("Error was to say no changed files -- not bad error. No need to check children.")
                     }