--- /dev/null
+/*
+ * Copyright (C) 2023 by Claudio Cambra <claudio.cambra@nextcloud.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+import FileProvider
+import NextcloudKit
+import OSLog
+
+extension FileProviderEnumerator {
+ static func fullRecursiveScan(ncAccount: NextcloudAccount, ncKit: NextcloudKit, scanChangesOnly: Bool, completionHandler: @escaping(_ newMetadatas: [NextcloudItemMetadataTable], _ updatedMetadatas: [NextcloudItemMetadataTable], _ deletedMetadatas: [NextcloudItemMetadataTable]) -> Void) {
+
+ let rootContainerDirectoryMetadata = NextcloudItemMetadataTable()
+ rootContainerDirectoryMetadata.directory = true
+ rootContainerDirectoryMetadata.ocId = NSFileProviderItemIdentifier.rootContainer.rawValue
+
+ // Create a serial dispatch queue
+ let dispatchQueue = DispatchQueue(label: "recursiveChangeEnumerationQueue", qos: .background)
+
+ dispatchQueue.async {
+ let results = scanRecursively(rootContainerDirectoryMetadata, ncAccount: ncAccount, ncKit: ncKit, scanChangesOnly: scanChangesOnly)
+
+ DispatchQueue.main.async {
+ completionHandler(results.newMetadatas, results.updatedMetadatas, results.deletedMetadatas)
+ }
+ }
+ }
+
+ static func scanRecursively(_ directoryMetadata: NextcloudItemMetadataTable, ncAccount: NextcloudAccount, ncKit: NextcloudKit, scanChangesOnly: Bool) -> (metadatas: [NextcloudItemMetadataTable], newMetadatas: [NextcloudItemMetadataTable], updatedMetadatas: [NextcloudItemMetadataTable], deletedMetadatas: [NextcloudItemMetadataTable]) {
+
+ assert(directoryMetadata.directory, "Can only recursively scan a directory.")
+
+ var allMetadatas: [NextcloudItemMetadataTable] = []
+ var allNewMetadatas: [NextcloudItemMetadataTable] = []
+ var allUpdatedMetadatas: [NextcloudItemMetadataTable] = []
+ var allDeletedMetadatas: [NextcloudItemMetadataTable] = []
+
+ let dbManager = NextcloudFilesDatabaseManager.shared
+ let dispatchGroup = DispatchGroup() // TODO: Maybe own thread?
+
+ dispatchGroup.enter()
+
+ let itemServerUrl = directoryMetadata.ocId == NSFileProviderItemIdentifier.rootContainer.rawValue ?
+ ncAccount.davFilesUrl : directoryMetadata.serverUrl + "/" + directoryMetadata.fileName
+
+ Logger.enumeration.debug("About to read: \(itemServerUrl, privacy: OSLogPrivacy.auto(mask: .hash))")
+
+ FileProviderEnumerator.readServerUrl(itemServerUrl, ncAccount: ncAccount, ncKit: ncKit, stopAtMatchingEtags: scanChangesOnly) { metadatas, newMetadatas, updatedMetadatas, deletedMetadatas, readError in
+
+ if readError != nil {
+ let nkReadError = NKError(error: readError!)
+
+ // Is the error is that we have found matching etags on this item, then ignore it
+ // if we are doing a full rescan
+ guard nkReadError.isNoChangesError && scanChangesOnly else {
+ Logger.enumeration.error("Finishing enumeration of changes at \(itemServerUrl, privacy: OSLogPrivacy.auto(mask: .hash)) with \(readError!.localizedDescription, privacy: .public)")
+
+ if nkReadError.isNotFoundError {
+ Logger.enumeration.info("404 error means item no longer exists. Deleting metadata and reporting as deletion without error")
+
+ 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")
+ }
+ } 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.")
+ }
+
+ dispatchGroup.leave()
+ return
+ }
+ }
+
+ Logger.enumeration.info("Finished reading serverUrl: \(itemServerUrl, privacy: OSLogPrivacy.auto(mask: .hash)) for user: \(ncAccount.ncKitAccount, privacy: OSLogPrivacy.auto(mask: .hash))")
+
+ if let metadatas = metadatas {
+ allMetadatas += metadatas
+ } else {
+ Logger.enumeration.warning("WARNING: Nil metadatas received for reading of changes at \(itemServerUrl, privacy: OSLogPrivacy.auto(mask: .hash)) for user: \(ncAccount.ncKitAccount, privacy: OSLogPrivacy.auto(mask: .hash))")
+ }
+
+ if let newMetadatas = newMetadatas {
+ allNewMetadatas += newMetadatas
+ } else {
+ Logger.enumeration.warning("WARNING: Nil new metadatas received for reading of changes at \(itemServerUrl, privacy: OSLogPrivacy.auto(mask: .hash)) for user: \(ncAccount.ncKitAccount, privacy: OSLogPrivacy.auto(mask: .hash))")
+ }
+
+ if let updatedMetadatas = updatedMetadatas {
+ allUpdatedMetadatas += updatedMetadatas
+ } else {
+ Logger.enumeration.warning("WARNING: Nil updated metadatas received for reading of changes at \(itemServerUrl, privacy: OSLogPrivacy.auto(mask: .hash)) for user: \(ncAccount.ncKitAccount, privacy: OSLogPrivacy.auto(mask: .hash))")
+ }
+
+ if let deletedMetadatas = deletedMetadatas {
+ allDeletedMetadatas += deletedMetadatas
+ } else {
+ Logger.enumeration.warning("WARNING: Nil deleted metadatas received for reading of changes at \(itemServerUrl, privacy: OSLogPrivacy.auto(mask: .hash)) for user: \(ncAccount.ncKitAccount, privacy: OSLogPrivacy.auto(mask: .hash))")
+ }
+
+ dispatchGroup.leave()
+ }
+
+ dispatchGroup.wait()
+
+ var updatedDirectories: [NextcloudItemMetadataTable] = []
+ for updatedMetadata in allUpdatedMetadatas {
+ if updatedMetadata.directory {
+ updatedDirectories.append(updatedMetadata)
+ }
+ }
+
+ if updatedDirectories.isEmpty {
+ return (metadatas: allMetadatas, newMetadatas: allNewMetadatas, updatedMetadatas: allUpdatedMetadatas, deletedMetadatas: allDeletedMetadatas)
+ }
+
+ for childDirectory in updatedDirectories {
+ let childScanResult = scanRecursively(childDirectory, ncAccount: ncAccount, ncKit: ncKit, scanChangesOnly: scanChangesOnly)
+
+ allMetadatas += childScanResult.metadatas
+ allNewMetadatas += childScanResult.newMetadatas
+ allUpdatedMetadatas += childScanResult.updatedMetadatas
+ allDeletedMetadatas += childScanResult.deletedMetadatas
+ }
+
+ return (metadatas: allMetadatas, newMetadatas: allNewMetadatas, updatedMetadatas: allUpdatedMetadatas, deletedMetadatas: allDeletedMetadatas)
+ }
+
+ static func readServerUrl(_ serverUrl: String, ncAccount: NextcloudAccount, ncKit: NextcloudKit, stopAtMatchingEtags: Bool = false, completionHandler: @escaping (_ metadatas: [NextcloudItemMetadataTable]?, _ newMetadatas: [NextcloudItemMetadataTable]?, _ updatedMetadatas: [NextcloudItemMetadataTable]?, _ deletedMetadatas: [NextcloudItemMetadataTable]?, _ readError: Error?) -> Void) {
+ let dbManager = NextcloudFilesDatabaseManager.shared
+ let ncKitAccount = ncAccount.ncKitAccount
+
+ Logger.enumeration.debug("Starting to read serverUrl: \(serverUrl, privacy: OSLogPrivacy.auto(mask: .hash)) for user: \(ncAccount.ncKitAccount, privacy: OSLogPrivacy.auto(mask: .hash)) at depth 0. NCKit info: userId: \(ncKit.nkCommonInstance.user), password: \(ncKit.nkCommonInstance.password == "" ? "EMPTY PASSWORD" : "NOT EMPTY PASSWORD"), urlBase: \(ncKit.nkCommonInstance.urlBase), ncVersion: \(ncKit.nkCommonInstance.nextcloudVersion)")
+
+ ncKit.readFileOrFolder(serverUrlFileName: serverUrl, depth: "0", showHiddenFiles: true) { account, files, _, error in
+ guard error == .success else {
+ Logger.enumeration.error("0 depth readFileOrFolder of url: \(serverUrl, privacy: OSLogPrivacy.auto(mask: .hash)) did not complete successfully, received error: \(error.errorDescription, privacy: .public)")
+ completionHandler(nil, nil, nil, nil, error.error)
+ return
+ }
+
+ guard let receivedItem = files.first else {
+ Logger.enumeration.error("Received no items from readFileOrFolder of \(serverUrl, privacy: OSLogPrivacy.auto(mask: .hash)), not much we can do...")
+ completionHandler(nil, nil, nil, nil, error.error)
+ return
+ }
+
+ guard receivedItem.directory else {
+ Logger.enumeration.debug("Read item is a file. Converting NKfile for serverUrl: \(serverUrl, privacy: OSLogPrivacy.auto(mask: .hash)) for user: \(ncAccount.ncKitAccount, privacy: OSLogPrivacy.auto(mask: .hash))")
+ let itemMetadata = dbManager.convertNKFileToItemMetadata(receivedItem, account: ncKitAccount)
+ dbManager.addItemMetadata(itemMetadata) // TODO: Return some value when it is an update
+ completionHandler([itemMetadata], nil, nil, nil, error.error)
+ return
+ }
+
+ if stopAtMatchingEtags,
+ let directoryMetadata = dbManager.directoryMetadata(account: ncKitAccount, serverUrl: serverUrl) {
+
+ let directoryEtag = directoryMetadata.etag
+
+ guard directoryEtag == "" || directoryEtag != receivedItem.etag else {
+ Logger.enumeration.debug("Read server url called with flag to stop enumerating at matching etags. Returning and providing soft error.")
+
+ let description = "Fetched directory etag is same as that stored locally. Not fetching child items."
+ let nkError = NKError(errorCode: NKError.noChangesErrorCode, errorDescription: description)
+
+ let metadatas = dbManager.itemMetadatas(account: account, serverUrl: serverUrl)
+
+ completionHandler(metadatas, nil, nil, nil, nkError.error)
+ return
+ }
+ }
+
+ Logger.enumeration.debug("Starting to read serverUrl: \(serverUrl, privacy: OSLogPrivacy.auto(mask: .hash)) for user: \(ncAccount.ncKitAccount, privacy: OSLogPrivacy.auto(mask: .hash)) at depth 1")
+
+ ncKit.readFileOrFolder(serverUrlFileName: serverUrl, depth: "1", showHiddenFiles: true) { account, files, _, error in
+ guard error == .success else {
+ Logger.enumeration.error("1 depth readFileOrFolder of url: \(serverUrl, privacy: OSLogPrivacy.auto(mask: .hash)) did not complete successfully, received error: \(error.errorDescription, privacy: .public)")
+ completionHandler(nil, nil, nil, nil, error.error)
+ return
+ }
+
+ Logger.enumeration.debug("Starting async conversion of NKFiles for serverUrl: \(serverUrl, privacy: OSLogPrivacy.auto(mask: .hash)) for user: \(ncAccount.ncKitAccount, privacy: OSLogPrivacy.auto(mask: .hash))")
+ DispatchQueue.main.async {
+ dbManager.convertNKFilesFromDirectoryReadToItemMetadatas(files, account: ncKitAccount) { directoryMetadata, childDirectoriesMetadata, metadatas in
+
+ // STORE DATA FOR CURRENTLY SCANNED DIRECTORY
+ // We have now scanned this directory's contents, so update with etag in order to not check again if not needed
+ // unless it's the root container
+ if serverUrl != ncAccount.davFilesUrl {
+ dbManager.addItemMetadata(directoryMetadata)
+ }
+
+ // Don't update the etags for folders as we haven't checked their contents.
+ // When we do a recursive check, if we update the etags now, we will think
+ // that our local copies are up to date -- instead, leave them as the old.
+ // They will get updated when they are the subject of a readServerUrl call.
+ // (See above)
+ let changedMetadatas = dbManager.updateItemMetadatas(account: ncKitAccount, serverUrl: serverUrl, updatedMetadatas: metadatas, updateDirectoryEtags: false)
+
+ completionHandler(metadatas, changedMetadatas.newMetadatas, changedMetadatas.updatedMetadatas, changedMetadatas.deletedMetadatas, nil)
+ }
+ }
+ }
+ }
+ }
+}
Logger.enumeration.info("Processed \(allUpdatedMetadatas.count) new or updated metadatas, \(allDeletedMetadatas.count) deleted metadatas.")
observer.finishEnumeratingChanges(upTo: anchor, moreComing: false)
}
-
- private static func fullRecursiveScan(ncAccount: NextcloudAccount, ncKit: NextcloudKit, scanChangesOnly: Bool, completionHandler: @escaping(_ newMetadatas: [NextcloudItemMetadataTable], _ updatedMetadatas: [NextcloudItemMetadataTable], _ deletedMetadatas: [NextcloudItemMetadataTable]) -> Void) {
-
- let rootContainerDirectoryMetadata = NextcloudItemMetadataTable()
- rootContainerDirectoryMetadata.directory = true
- rootContainerDirectoryMetadata.ocId = NSFileProviderItemIdentifier.rootContainer.rawValue
-
- // Create a serial dispatch queue
- let dispatchQueue = DispatchQueue(label: "recursiveChangeEnumerationQueue", qos: .background)
-
- dispatchQueue.async {
- let results = scanRecursively(rootContainerDirectoryMetadata, ncAccount: ncAccount, ncKit: ncKit, scanChangesOnly: scanChangesOnly)
-
- DispatchQueue.main.async {
- completionHandler(results.newMetadatas, results.updatedMetadatas, results.deletedMetadatas)
- }
- }
- }
-
- private static func scanRecursively(_ directoryMetadata: NextcloudItemMetadataTable, ncAccount: NextcloudAccount, ncKit: NextcloudKit, scanChangesOnly: Bool) -> (metadatas: [NextcloudItemMetadataTable], newMetadatas: [NextcloudItemMetadataTable], updatedMetadatas: [NextcloudItemMetadataTable], deletedMetadatas: [NextcloudItemMetadataTable]) {
-
- assert(directoryMetadata.directory, "Can only recursively scan a directory.")
-
- var allMetadatas: [NextcloudItemMetadataTable] = []
- var allNewMetadatas: [NextcloudItemMetadataTable] = []
- var allUpdatedMetadatas: [NextcloudItemMetadataTable] = []
- var allDeletedMetadatas: [NextcloudItemMetadataTable] = []
-
- let dbManager = NextcloudFilesDatabaseManager.shared
- let dispatchGroup = DispatchGroup() // TODO: Maybe own thread?
-
- dispatchGroup.enter()
-
- let itemServerUrl = directoryMetadata.ocId == NSFileProviderItemIdentifier.rootContainer.rawValue ?
- ncAccount.davFilesUrl : directoryMetadata.serverUrl + "/" + directoryMetadata.fileName
-
- Logger.enumeration.debug("About to read: \(itemServerUrl, privacy: OSLogPrivacy.auto(mask: .hash))")
-
- FileProviderEnumerator.readServerUrl(itemServerUrl, ncAccount: ncAccount, ncKit: ncKit, stopAtMatchingEtags: scanChangesOnly) { metadatas, newMetadatas, updatedMetadatas, deletedMetadatas, readError in
-
- if readError != nil {
- let nkReadError = NKError(error: readError!)
-
- // Is the error is that we have found matching etags on this item, then ignore it
- // if we are doing a full rescan
- guard nkReadError.isNoChangesError && scanChangesOnly else {
- Logger.enumeration.error("Finishing enumeration of changes at \(itemServerUrl, privacy: OSLogPrivacy.auto(mask: .hash)) with \(readError!.localizedDescription, privacy: .public)")
-
- if nkReadError.isNotFoundError {
- Logger.enumeration.info("404 error means item no longer exists. Deleting metadata and reporting as deletion without error")
-
- 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")
- }
- } 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.")
- }
-
- dispatchGroup.leave()
- return
- }
- }
-
- Logger.enumeration.info("Finished reading serverUrl: \(itemServerUrl, privacy: OSLogPrivacy.auto(mask: .hash)) for user: \(ncAccount.ncKitAccount, privacy: OSLogPrivacy.auto(mask: .hash))")
-
- if let metadatas = metadatas {
- allMetadatas += metadatas
- } else {
- Logger.enumeration.warning("WARNING: Nil metadatas received for reading of changes at \(itemServerUrl, privacy: OSLogPrivacy.auto(mask: .hash)) for user: \(ncAccount.ncKitAccount, privacy: OSLogPrivacy.auto(mask: .hash))")
- }
-
- if let newMetadatas = newMetadatas {
- allNewMetadatas += newMetadatas
- } else {
- Logger.enumeration.warning("WARNING: Nil new metadatas received for reading of changes at \(itemServerUrl, privacy: OSLogPrivacy.auto(mask: .hash)) for user: \(ncAccount.ncKitAccount, privacy: OSLogPrivacy.auto(mask: .hash))")
- }
-
- if let updatedMetadatas = updatedMetadatas {
- allUpdatedMetadatas += updatedMetadatas
- } else {
- Logger.enumeration.warning("WARNING: Nil updated metadatas received for reading of changes at \(itemServerUrl, privacy: OSLogPrivacy.auto(mask: .hash)) for user: \(ncAccount.ncKitAccount, privacy: OSLogPrivacy.auto(mask: .hash))")
- }
-
- if let deletedMetadatas = deletedMetadatas {
- allDeletedMetadatas += deletedMetadatas
- } else {
- Logger.enumeration.warning("WARNING: Nil deleted metadatas received for reading of changes at \(itemServerUrl, privacy: OSLogPrivacy.auto(mask: .hash)) for user: \(ncAccount.ncKitAccount, privacy: OSLogPrivacy.auto(mask: .hash))")
- }
-
- dispatchGroup.leave()
- }
-
- dispatchGroup.wait()
-
- var updatedDirectories: [NextcloudItemMetadataTable] = []
- for updatedMetadata in allUpdatedMetadatas {
- if updatedMetadata.directory {
- updatedDirectories.append(updatedMetadata)
- }
- }
-
- if updatedDirectories.isEmpty {
- return (metadatas: allMetadatas, newMetadatas: allNewMetadatas, updatedMetadatas: allUpdatedMetadatas, deletedMetadatas: allDeletedMetadatas)
- }
-
- for childDirectory in updatedDirectories {
- let childScanResult = scanRecursively(childDirectory, ncAccount: ncAccount, ncKit: ncKit, scanChangesOnly: scanChangesOnly)
-
- allMetadatas += childScanResult.metadatas
- allNewMetadatas += childScanResult.newMetadatas
- allUpdatedMetadatas += childScanResult.updatedMetadatas
- allDeletedMetadatas += childScanResult.deletedMetadatas
- }
-
- return (metadatas: allMetadatas, newMetadatas: allNewMetadatas, updatedMetadatas: allUpdatedMetadatas, deletedMetadatas: allDeletedMetadatas)
- }
-
- private static func readServerUrl(_ serverUrl: String, ncAccount: NextcloudAccount, ncKit: NextcloudKit, stopAtMatchingEtags: Bool = false, completionHandler: @escaping (_ metadatas: [NextcloudItemMetadataTable]?, _ newMetadatas: [NextcloudItemMetadataTable]?, _ updatedMetadatas: [NextcloudItemMetadataTable]?, _ deletedMetadatas: [NextcloudItemMetadataTable]?, _ readError: Error?) -> Void) {
- let dbManager = NextcloudFilesDatabaseManager.shared
- let ncKitAccount = ncAccount.ncKitAccount
-
- Logger.enumeration.debug("Starting to read serverUrl: \(serverUrl, privacy: OSLogPrivacy.auto(mask: .hash)) for user: \(ncAccount.ncKitAccount, privacy: OSLogPrivacy.auto(mask: .hash)) at depth 0. NCKit info: userId: \(ncKit.nkCommonInstance.user), password: \(ncKit.nkCommonInstance.password == "" ? "EMPTY PASSWORD" : "NOT EMPTY PASSWORD"), urlBase: \(ncKit.nkCommonInstance.urlBase), ncVersion: \(ncKit.nkCommonInstance.nextcloudVersion)")
-
- ncKit.readFileOrFolder(serverUrlFileName: serverUrl, depth: "0", showHiddenFiles: true) { account, files, _, error in
- guard error == .success else {
- Logger.enumeration.error("0 depth readFileOrFolder of url: \(serverUrl, privacy: OSLogPrivacy.auto(mask: .hash)) did not complete successfully, received error: \(error.errorDescription, privacy: .public)")
- completionHandler(nil, nil, nil, nil, error.error)
- return
- }
-
- guard let receivedItem = files.first else {
- Logger.enumeration.error("Received no items from readFileOrFolder of \(serverUrl, privacy: OSLogPrivacy.auto(mask: .hash)), not much we can do...")
- completionHandler(nil, nil, nil, nil, error.error)
- return
- }
-
- guard receivedItem.directory else {
- Logger.enumeration.debug("Read item is a file. Converting NKfile for serverUrl: \(serverUrl, privacy: OSLogPrivacy.auto(mask: .hash)) for user: \(ncAccount.ncKitAccount, privacy: OSLogPrivacy.auto(mask: .hash))")
- let itemMetadata = dbManager.convertNKFileToItemMetadata(receivedItem, account: ncKitAccount)
- dbManager.addItemMetadata(itemMetadata) // TODO: Return some value when it is an update
- completionHandler([itemMetadata], nil, nil, nil, error.error)
- return
- }
-
- if stopAtMatchingEtags,
- let directoryMetadata = dbManager.directoryMetadata(account: ncKitAccount, serverUrl: serverUrl) {
-
- let directoryEtag = directoryMetadata.etag
-
- guard directoryEtag == "" || directoryEtag != receivedItem.etag else {
- Logger.enumeration.debug("Read server url called with flag to stop enumerating at matching etags. Returning and providing soft error.")
-
- let description = "Fetched directory etag is same as that stored locally. Not fetching child items."
- let nkError = NKError(errorCode: NKError.noChangesErrorCode, errorDescription: description)
-
- let metadatas = dbManager.itemMetadatas(account: account, serverUrl: serverUrl)
-
- completionHandler(metadatas, nil, nil, nil, nkError.error)
- return
- }
- }
-
- Logger.enumeration.debug("Starting to read serverUrl: \(serverUrl, privacy: OSLogPrivacy.auto(mask: .hash)) for user: \(ncAccount.ncKitAccount, privacy: OSLogPrivacy.auto(mask: .hash)) at depth 1")
-
- ncKit.readFileOrFolder(serverUrlFileName: serverUrl, depth: "1", showHiddenFiles: true) { account, files, _, error in
- guard error == .success else {
- Logger.enumeration.error("1 depth readFileOrFolder of url: \(serverUrl, privacy: OSLogPrivacy.auto(mask: .hash)) did not complete successfully, received error: \(error.errorDescription, privacy: .public)")
- completionHandler(nil, nil, nil, nil, error.error)
- return
- }
-
- Logger.enumeration.debug("Starting async conversion of NKFiles for serverUrl: \(serverUrl, privacy: OSLogPrivacy.auto(mask: .hash)) for user: \(ncAccount.ncKitAccount, privacy: OSLogPrivacy.auto(mask: .hash))")
- DispatchQueue.main.async {
- dbManager.convertNKFilesFromDirectoryReadToItemMetadatas(files, account: ncKitAccount) { directoryMetadata, childDirectoriesMetadata, metadatas in
-
- // STORE DATA FOR CURRENTLY SCANNED DIRECTORY
- // We have now scanned this directory's contents, so update with etag in order to not check again if not needed
- // unless it's the root container
- if serverUrl != ncAccount.davFilesUrl {
- dbManager.addItemMetadata(directoryMetadata)
- }
-
- // Don't update the etags for folders as we haven't checked their contents.
- // When we do a recursive check, if we update the etags now, we will think
- // that our local copies are up to date -- instead, leave them as the old.
- // They will get updated when they are the subject of a readServerUrl call.
- // (See above)
- let changedMetadatas = dbManager.updateItemMetadatas(account: ncKitAccount, serverUrl: serverUrl, updatedMetadatas: metadatas, updateDirectoryEtags: false)
-
- completionHandler(metadatas, changedMetadatas.newMetadatas, changedMetadatas.updatedMetadatas, changedMetadatas.deletedMetadatas, nil)
- }
- }
- }
- }
- }
}
53903D37295618A400D0B308 /* LineProcessor.h in Headers */ = {isa = PBXBuildFile; fileRef = 53903D36295618A400D0B308 /* LineProcessor.h */; settings = {ATTRIBUTES = (Public, ); }; };
539158AC27BE71A900816F56 /* FinderSyncSocketLineProcessor.m in Sources */ = {isa = PBXBuildFile; fileRef = 539158AB27BE71A900816F56 /* FinderSyncSocketLineProcessor.m */; };
53D056312970594F00988392 /* LocalFilesUtils.swift in Sources */ = {isa = PBXBuildFile; fileRef = 53D056302970594F00988392 /* LocalFilesUtils.swift */; };
+ 53ED472029C5E64200795DB1 /* FileProviderEnumerator+RemoteSync.swift in Sources */ = {isa = PBXBuildFile; fileRef = 53ED471F29C5E64200795DB1 /* FileProviderEnumerator+RemoteSync.swift */; };
C2B573BA1B1CD91E00303B36 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = C2B573B91B1CD91E00303B36 /* main.m */; };
C2B573D21B1CD94B00303B36 /* main.m in Resources */ = {isa = PBXBuildFile; fileRef = C2B573B91B1CD91E00303B36 /* main.m */; };
C2B573DE1B1CD9CE00303B36 /* FinderSync.m in Sources */ = {isa = PBXBuildFile; fileRef = C2B573DD1B1CD9CE00303B36 /* FinderSync.m */; };
539158B127BE891500816F56 /* LocalSocketClient.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = LocalSocketClient.h; sourceTree = "<group>"; };
539158B227BEC98A00816F56 /* LocalSocketClient.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = LocalSocketClient.m; sourceTree = "<group>"; };
53D056302970594F00988392 /* LocalFilesUtils.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LocalFilesUtils.swift; sourceTree = "<group>"; };
+ 53ED471F29C5E64200795DB1 /* FileProviderEnumerator+RemoteSync.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "FileProviderEnumerator+RemoteSync.swift"; sourceTree = "<group>"; };
C2B573B11B1CD91E00303B36 /* desktopclient.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = desktopclient.app; sourceTree = BUILT_PRODUCTS_DIR; };
C2B573B51B1CD91E00303B36 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
C2B573B91B1CD91E00303B36 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = "<group>"; };
5318AD8F29BF406500CBB71C /* Database */,
5352E85929B7BFB4002CE85C /* Extensions */,
538E397027F4765000FA63D5 /* FileProviderEnumerator.swift */,
+ 53ED471F29C5E64200795DB1 /* FileProviderEnumerator+RemoteSync.swift */,
538E396C27F4765000FA63D5 /* FileProviderExtension.swift */,
538E396E27F4765000FA63D5 /* FileProviderItem.swift */,
5318AD9629BF493600CBB71C /* FileProviderMaterialisedEnumerationObserver.swift */,
536EFC36295E3C1100F4CB13 /* NextcloudAccount.swift in Sources */,
538E396D27F4765000FA63D5 /* FileProviderExtension.swift in Sources */,
536EFBF7295CF58100F4CB13 /* FileProviderSocketLineProcessor.swift in Sources */,
+ 53ED472029C5E64200795DB1 /* FileProviderEnumerator+RemoteSync.swift in Sources */,
5318AD9929BF58D000CBB71C /* NKError+Extensions.swift in Sources */,
5318AD9529BF438F00CBB71C /* NextcloudLocalFileMetadataTable.swift in Sources */,
535AE30E29C0A2CC0042A9BA /* Logger+Extensions.swift in Sources */,