Properly handle readFileOrFolder of file vs folder
authorClaudio Cambra <claudio.cambra@nextcloud.com>
Tue, 7 Mar 2023 23:21:23 +0000 (00:21 +0100)
committerClaudio Cambra <claudio.cambra@nextcloud.com>
Fri, 12 May 2023 05:21:21 +0000 (13:21 +0800)
Signed-off-by: Claudio Cambra <claudio.cambra@nextcloud.com>
shell_integration/MacOSX/NextcloudIntegration/FileProviderExt/FileProviderEnumerator.swift
shell_integration/MacOSX/NextcloudIntegration/FileProviderExt/FileProviderExtension.swift
shell_integration/MacOSX/NextcloudIntegration/FileProviderExt/NextcloudFilesDatabaseManager.swift

index 2431d5bf031bbf6ff13791cf0dc626f7e254c766..1374d69e16e74851402bc8955e58527415c5c861 100644 (file)
@@ -185,11 +185,6 @@ class FileProviderEnumerator: NSObject, NSFileProviderEnumerator {
     private static func readServerUrl(_ serverUrl: String, ncAccount: NextcloudAccount, ncKit: NextcloudKit, completionHandler: @escaping (_ metadatas: [NextcloudItemMetadataTable]?, _ readError: Error?) -> Void) {
         let dbManager = NextcloudFilesDatabaseManager.shared
         let ncKitAccount = ncAccount.ncKitAccount
-        var directoryEtag: String?
-
-        if let directoryMetadata = dbManager.directoryMetadata(account: ncKitAccount, serverUrl: serverUrl) {
-            directoryEtag = directoryMetadata.etag
-        }
 
         NSLog("Starting to read serverUrl: %@ for user: %@ at depth 0. NCKit info: user: %@, userId: %@, password: %@, urlBase: %@, ncVersion: %d", serverUrl, ncKitAccount, ncKit.nkCommonInstance.user, ncKit.nkCommonInstance.userId, ncKit.nkCommonInstance.password, ncKit.nkCommonInstance.urlBase, ncKit.nkCommonInstance.nextcloudVersion)
 
@@ -200,13 +195,32 @@ class FileProviderEnumerator: NSObject, NSFileProviderEnumerator {
                 return
             }
 
-            // If we have already done a 0 depth scan of this folder then we might get matching etag
-            guard directoryEtag != files.first?.etag else {
-                NSLog("Fetched directory etag is same as that stored locally (serverUrl: %@ user: %@). Not fetching child items.", serverUrl, account)
-                finishReadServerUrl(serverUrl, ncKitAccount: ncKitAccount, readError: nil, completionHandler: completionHandler)
+            guard let receivedItem = files.first else {
+                NSLog("Received no items from readFileOrFolder, not much we can do...")
+                finishReadServerUrl(serverUrl, ncKitAccount: ncKitAccount, readError: NSFileProviderError(.noSuchItem), completionHandler: completionHandler)
+                return
+            }
+
+            guard receivedItem.directory else {
+                NSLog("Read item is a file. Converting NKfile for serverUrl: %@ for user: %@", serverUrl, ncKitAccount)
+                let itemMetadata = dbManager.convertNKFileToItemMetadata(receivedItem, account: ncKitAccount)
+                dbManager.addItemMetadata(itemMetadata)
+                finishReadServerUrl(serverUrl, ncKitAccount: ncKitAccount, readError: NSFileProviderError(.noSuchItem), completionHandler: completionHandler)
                 return
             }
 
+            // If we have already done a full readFileOrFolder scan of this folder then it will be in the database.
+            // We can check for matching etags and stop here if this is the case, as the state is the same.
+            if let directoryMetadata = dbManager.directoryMetadata(account: ncKitAccount, serverUrl: serverUrl) {
+                let directoryEtag = directoryMetadata.etag
+
+                guard directoryEtag == "" || directoryEtag != receivedItem.etag else {
+                    NSLog("Fetched directory etag is same as that stored locally (serverUrl: %@ user: %@). Not fetching child items.", serverUrl, account)
+                    finishReadServerUrl(serverUrl, ncKitAccount: ncKitAccount, readError: nil, completionHandler: completionHandler)
+                    return
+                }
+            }
+
             NSLog("Starting to read serverUrl: %@ for user: %@ at depth 1", serverUrl, ncKitAccount)
 
             ncKit.readFileOrFolder(serverUrlFileName: serverUrl, depth: "1", showHiddenFiles: true) { account, files, _, error in
@@ -218,7 +232,7 @@ class FileProviderEnumerator: NSObject, NSFileProviderEnumerator {
 
                 NSLog("Starting async conversion of NKFiles for serverUrl: %@ for user: %@", serverUrl, ncKitAccount)
                 DispatchQueue.global().async {
-                    dbManager.convertNKFilesToItemMetadatas(files, account: ncKitAccount) { directoryMetadata, childDirectoriesMetadata, metadatas in
+                    dbManager.convertNKFilesFromDirectoryReadToItemMetadatas(files, account: ncKitAccount) { directoryMetadata, childDirectoriesMetadata, metadatas in
 
                         // We have now scanned this directory's contents, so update with etag in order to not check again if not needed
                         dbManager.updateDirectoryMetadatasFromItemMetadatas(account: ncKitAccount, parentDirectoryServerUrl: serverUrl, updatedDirectoryItemMetadatas: [directoryMetadata], recordEtag: true)
index 076d1b7c20242d22f0c7fb269bdcf4268d32bc20..b870e8a2c71fbb0a0cf697c958aacd5da8da8607 100644 (file)
@@ -145,6 +145,7 @@ class FileProviderExtension: NSObject, NSFileProviderReplicatedExtension, NKComm
 
         var progress = Progress()
 
+        // TODO: Handle folders nicely
         do {
             let fileNameLocalPath = try localPathForNCFile(ocId: metadata.ocId, fileNameView: metadata.fileNameView)
 
@@ -269,7 +270,7 @@ class FileProviderExtension: NSObject, NSFileProviderReplicatedExtension, NKComm
                     }
 
                     DispatchQueue.global().async {
-                        dbManager.convertNKFilesToItemMetadatas(files, account: account) { directoryMetadata, childDirectoriesMetadata, metadatas in
+                        dbManager.convertNKFilesFromDirectoryReadToItemMetadatas(files, account: account) { directoryMetadata, childDirectoriesMetadata, metadatas in
 
                             let newDirectoryMetadata = dbManager.directoryMetadataFromItemMetadata(directoryItemMetadata: directoryMetadata)
                             dbManager.addDirectoryMetadata(newDirectoryMetadata)
index 983763b7cce00461b340d022684508cf21c930a0..04e582ca13598ca8fbe911e6fa2a36095b9323ae 100644 (file)
@@ -633,7 +633,7 @@ class NextcloudFilesDatabaseManager : NSObject {
         return metadata
     }
 
-    func convertNKFilesToItemMetadatas(_ files: [NKFile], account: String, completionHandler: @escaping (_ directoryMetadata: NextcloudItemMetadataTable, _ childDirectoriesMetadatas: [NextcloudItemMetadataTable], _ metadatas: [NextcloudItemMetadataTable]) -> Void) {
+    func convertNKFilesFromDirectoryReadToItemMetadatas(_ files: [NKFile], account: String, completionHandler: @escaping (_ directoryMetadata: NextcloudItemMetadataTable, _ childDirectoriesMetadatas: [NextcloudItemMetadataTable], _ metadatas: [NextcloudItemMetadataTable]) -> Void) {
 
         var directoryMetadataSet = false
         var directoryMetadata = NextcloudItemMetadataTable()