From 3928573ff4e6be0eac1daaee827a15a395ac8b22 Mon Sep 17 00:00:00 2001 From: Claudio Cambra Date: Mon, 22 Jan 2024 14:40:47 +0800 Subject: [PATCH] Run swift-format on swift code Signed-off-by: Claudio Cambra --- ...loudFilesDatabaseManager+Directories.swift | 108 ++-- ...cloudFilesDatabaseManager+LocalFiles.swift | 40 +- .../NextcloudFilesDatabaseManager.swift | 262 ++++++--- .../NextcloudItemMetadataTable+NKFile.swift | 32 +- .../Database/NextcloudItemMetadataTable.swift | 70 +-- .../Extensions/Logger+Extensions.swift | 9 +- .../Extensions/NKError+Extensions.swift | 36 +- .../Extensions/Progress+Extensions.swift | 46 +- .../FileProviderEnumerator+SyncEngine.swift | 291 ++++++---- .../FileProviderEnumerator.swift | 272 +++++++--- ...ileProviderExtension+ClientInterface.swift | 43 +- .../FileProviderExtension+Thumbnailing.swift | 41 +- .../FileProviderExtension.swift | 500 ++++++++++++------ .../FileProviderExt/FileProviderItem.swift | 90 ++-- ...viderMaterialisedEnumerationObserver.swift | 42 +- .../FileProviderSocketLineProcessor.swift | 18 +- .../FileProviderExt/LocalFilesUtils.swift | 25 +- .../FileProviderExt/NextcloudAccount.swift | 9 +- 18 files changed, 1268 insertions(+), 666 deletions(-) diff --git a/shell_integration/MacOSX/NextcloudIntegration/FileProviderExt/Database/NextcloudFilesDatabaseManager+Directories.swift b/shell_integration/MacOSX/NextcloudIntegration/FileProviderExt/Database/NextcloudFilesDatabaseManager+Directories.swift index 386791ecc..0e29754df 100644 --- a/shell_integration/MacOSX/NextcloudIntegration/FileProviderExt/Database/NextcloudFilesDatabaseManager+Directories.swift +++ b/shell_integration/MacOSX/NextcloudIntegration/FileProviderExt/Database/NextcloudFilesDatabaseManager+Directories.swift @@ -20,36 +20,51 @@ extension NextcloudFilesDatabaseManager { // We want to split by "/" (e.g. cloud.nc.com/files/a/b) but we need to be mindful of "https://c.nc.com" let problematicSeparator = "://" let placeholderSeparator = "__TEMP_REPLACE__" - let serverUrlWithoutPrefix = serverUrl.replacingOccurrences(of: problematicSeparator, with: placeholderSeparator) + let serverUrlWithoutPrefix = serverUrl.replacingOccurrences( + of: problematicSeparator, with: placeholderSeparator) var splitServerUrl = serverUrlWithoutPrefix.split(separator: "/") let directoryItemFileName = String(splitServerUrl.removeLast()) - let directoryItemServerUrl = splitServerUrl.joined(separator: "/").replacingOccurrences(of: placeholderSeparator, with: problematicSeparator) + let directoryItemServerUrl = splitServerUrl.joined(separator: "/").replacingOccurrences( + of: placeholderSeparator, with: problematicSeparator) - if let metadata = ncDatabase().objects(NextcloudItemMetadataTable.self).filter("account == %@ AND serverUrl == %@ AND fileName == %@ AND directory == true", account, directoryItemServerUrl, directoryItemFileName).first { + if let metadata = ncDatabase().objects(NextcloudItemMetadataTable.self).filter( + "account == %@ AND serverUrl == %@ AND fileName == %@ AND directory == true", account, + directoryItemServerUrl, directoryItemFileName + ).first { return NextcloudItemMetadataTable(value: metadata) } return nil } - func childItemsForDirectory(_ directoryMetadata: NextcloudItemMetadataTable) -> [NextcloudItemMetadataTable] { + func childItemsForDirectory(_ directoryMetadata: NextcloudItemMetadataTable) + -> [NextcloudItemMetadataTable] + { let directoryServerUrl = directoryMetadata.serverUrl + "/" + directoryMetadata.fileName - let metadatas = ncDatabase().objects(NextcloudItemMetadataTable.self).filter("serverUrl BEGINSWITH %@", directoryServerUrl) + let metadatas = ncDatabase().objects(NextcloudItemMetadataTable.self).filter( + "serverUrl BEGINSWITH %@", directoryServerUrl) return sortedItemMetadatas(metadatas) } - func childDirectoriesForDirectory(_ directoryMetadata: NextcloudItemMetadataTable) -> [NextcloudItemMetadataTable] { + func childDirectoriesForDirectory(_ directoryMetadata: NextcloudItemMetadataTable) + -> [NextcloudItemMetadataTable] + { let directoryServerUrl = directoryMetadata.serverUrl + "/" + directoryMetadata.fileName - let metadatas = ncDatabase().objects(NextcloudItemMetadataTable.self).filter("serverUrl BEGINSWITH %@ AND directory == true", directoryServerUrl) + let metadatas = ncDatabase().objects(NextcloudItemMetadataTable.self).filter( + "serverUrl BEGINSWITH %@ AND directory == true", directoryServerUrl) return sortedItemMetadatas(metadatas) } - func parentDirectoryMetadataForItem(_ itemMetadata: NextcloudItemMetadataTable) -> NextcloudItemMetadataTable? { - return directoryMetadata(account: itemMetadata.account, serverUrl: itemMetadata.serverUrl) + func parentDirectoryMetadataForItem(_ itemMetadata: NextcloudItemMetadataTable) + -> NextcloudItemMetadataTable? + { + directoryMetadata(account: itemMetadata.account, serverUrl: itemMetadata.serverUrl) } func directoryMetadata(ocId: String) -> NextcloudItemMetadataTable? { - if let metadata = ncDatabase().objects(NextcloudItemMetadataTable.self).filter("ocId == %@ AND directory == true", ocId).first { + if let metadata = ncDatabase().objects(NextcloudItemMetadataTable.self).filter( + "ocId == %@ AND directory == true", ocId + ).first { return NextcloudItemMetadataTable(value: metadata) } @@ -57,20 +72,31 @@ extension NextcloudFilesDatabaseManager { } func directoryMetadatas(account: String) -> [NextcloudItemMetadataTable] { - let metadatas = ncDatabase().objects(NextcloudItemMetadataTable.self).filter("account == %@ AND directory == true", account) + let metadatas = ncDatabase().objects(NextcloudItemMetadataTable.self).filter( + "account == %@ AND directory == true", account) return sortedItemMetadatas(metadatas) } - func directoryMetadatas(account: String, parentDirectoryServerUrl: String) -> [NextcloudItemMetadataTable] { - let metadatas = ncDatabase().objects(NextcloudItemMetadataTable.self).filter("account == %@ AND parentDirectoryServerUrl == %@ AND directory == true", account, parentDirectoryServerUrl) + func directoryMetadatas(account: String, parentDirectoryServerUrl: String) + -> [NextcloudItemMetadataTable] + { + let metadatas = ncDatabase().objects(NextcloudItemMetadataTable.self).filter( + "account == %@ AND parentDirectoryServerUrl == %@ AND directory == true", account, + parentDirectoryServerUrl) return sortedItemMetadatas(metadatas) } // Deletes all metadatas related to the info of the directory provided 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") + 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 nil } @@ -79,20 +105,25 @@ extension NextcloudFilesDatabaseManager { let directoryAccount = directoryMetadata.account let directoryEtag = directoryMetadata.etag - Logger.ncFilesDatabase.debug("Deleting root directory metadata in recursive delete. ocID: \(directoryMetadata.ocId, privacy: .public), etag: \(directoryEtag, privacy: .public), serverUrl: \(directoryUrlPath, privacy: .public)") + Logger.ncFilesDatabase.debug( + "Deleting root directory metadata in recursive delete. ocID: \(directoryMetadata.ocId, privacy: .public), etag: \(directoryEtag, privacy: .public), serverUrl: \(directoryUrlPath, privacy: .public)" + ) guard deleteItemMetadata(ocId: directoryMetadata.ocId) else { - Logger.ncFilesDatabase.debug("Failure to delete root directory metadata in recursive delete. ocID: \(directoryMetadata.ocId, privacy: .public), etag: \(directoryEtag, privacy: .public), serverUrl: \(directoryUrlPath, privacy: .public)") + Logger.ncFilesDatabase.debug( + "Failure to delete root directory metadata in recursive delete. ocID: \(directoryMetadata.ocId, privacy: .public), etag: \(directoryEtag, privacy: .public), serverUrl: \(directoryUrlPath, privacy: .public)" + ) return nil } var deletedMetadatas: [NextcloudItemMetadataTable] = [directoryMetadataCopy] - let results = database.objects(NextcloudItemMetadataTable.self).filter("account == %@ AND serverUrl BEGINSWITH %@", directoryAccount, directoryUrlPath) + let results = database.objects(NextcloudItemMetadataTable.self).filter( + "account == %@ AND serverUrl BEGINSWITH %@", directoryAccount, directoryUrlPath) for result in results { let successfulItemMetadataDelete = deleteItemMetadata(ocId: result.ocId) - if (successfulItemMetadataDelete) { + if successfulItemMetadataDelete { deletedMetadatas.append(NextcloudItemMetadataTable(value: result)) } @@ -101,24 +132,35 @@ extension NextcloudFilesDatabaseManager { } } - Logger.ncFilesDatabase.debug("Completed deletions in directory recursive delete. ocID: \(directoryMetadata.ocId, privacy: .public), etag: \(directoryEtag, privacy: .public), serverUrl: \(directoryUrlPath, privacy: .public)") + Logger.ncFilesDatabase.debug( + "Completed deletions in directory recursive delete. ocID: \(directoryMetadata.ocId, privacy: .public), etag: \(directoryEtag, privacy: .public), serverUrl: \(directoryUrlPath, privacy: .public)" + ) return deletedMetadatas } - func renameDirectoryAndPropagateToChildren(ocId: String, newServerUrl: String, newFileName: String) -> [NextcloudItemMetadataTable]? { - + func renameDirectoryAndPropagateToChildren( + ocId: String, newServerUrl: String, newFileName: 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 a directory with ocID \(ocId, privacy: .public), cannot proceed with recursive renaming") + guard + let directoryMetadata = database.objects(NextcloudItemMetadataTable.self).filter( + "ocId == %@ AND directory == true", ocId + ).first + else { + Logger.ncFilesDatabase.error( + "Could not find a directory with ocID \(ocId, privacy: .public), cannot proceed with recursive renaming" + ) return nil } let oldItemServerUrl = directoryMetadata.serverUrl let oldDirectoryServerUrl = oldItemServerUrl + "/" + directoryMetadata.fileName let newDirectoryServerUrl = newServerUrl + "/" + newFileName - let childItemResults = database.objects(NextcloudItemMetadataTable.self).filter("account == %@ AND serverUrl BEGINSWITH %@", directoryMetadata.account, oldDirectoryServerUrl) + let childItemResults = database.objects(NextcloudItemMetadataTable.self).filter( + "account == %@ AND serverUrl BEGINSWITH %@", directoryMetadata.account, + oldDirectoryServerUrl) renameItemMetadata(ocId: ocId, newServerUrl: newServerUrl, newFileName: newFileName) Logger.ncFilesDatabase.debug("Renamed root renaming directory") @@ -127,19 +169,25 @@ extension NextcloudFilesDatabaseManager { try database.write { for childItem in childItemResults { let oldServerUrl = childItem.serverUrl - let movedServerUrl = oldServerUrl.replacingOccurrences(of: oldDirectoryServerUrl, with: newDirectoryServerUrl) + let movedServerUrl = oldServerUrl.replacingOccurrences( + of: oldDirectoryServerUrl, with: newDirectoryServerUrl) childItem.serverUrl = movedServerUrl database.add(childItem, update: .all) - Logger.ncFilesDatabase.debug("Moved childItem at \(oldServerUrl) to \(movedServerUrl)") + Logger.ncFilesDatabase.debug( + "Moved childItem at \(oldServerUrl) to \(movedServerUrl)") } } - } catch let error { - Logger.ncFilesDatabase.error("Could not rename directory metadata with ocId: \(ocId, privacy: .public) to new serverUrl: \(newServerUrl), received error: \(error.localizedDescription, privacy: .public)") + } catch { + Logger.ncFilesDatabase.error( + "Could not rename directory metadata with ocId: \(ocId, privacy: .public) to new serverUrl: \(newServerUrl), received error: \(error.localizedDescription, privacy: .public)" + ) return nil } - let updatedChildItemResults = database.objects(NextcloudItemMetadataTable.self).filter("account == %@ AND serverUrl BEGINSWITH %@", directoryMetadata.account, newDirectoryServerUrl) + let updatedChildItemResults = database.objects(NextcloudItemMetadataTable.self).filter( + "account == %@ AND serverUrl BEGINSWITH %@", directoryMetadata.account, + newDirectoryServerUrl) return sortedItemMetadatas(updatedChildItemResults) } } diff --git a/shell_integration/MacOSX/NextcloudIntegration/FileProviderExt/Database/NextcloudFilesDatabaseManager+LocalFiles.swift b/shell_integration/MacOSX/NextcloudIntegration/FileProviderExt/Database/NextcloudFilesDatabaseManager+LocalFiles.swift index 2241d200c..3174bc491 100644 --- a/shell_integration/MacOSX/NextcloudIntegration/FileProviderExt/Database/NextcloudFilesDatabaseManager+LocalFiles.swift +++ b/shell_integration/MacOSX/NextcloudIntegration/FileProviderExt/Database/NextcloudFilesDatabaseManager+LocalFiles.swift @@ -13,12 +13,14 @@ */ import Foundation -import RealmSwift import OSLog +import RealmSwift extension NextcloudFilesDatabaseManager { func localFileMetadataFromOcId(_ ocId: String) -> NextcloudLocalFileMetadataTable? { - if let metadata = ncDatabase().objects(NextcloudLocalFileMetadataTable.self).filter("ocId == %@", ocId).first { + if let metadata = ncDatabase().objects(NextcloudLocalFileMetadataTable.self).filter( + "ocId == %@", ocId + ).first { return NextcloudLocalFileMetadataTable(value: metadata) } @@ -41,10 +43,14 @@ extension NextcloudFilesDatabaseManager { newLocalFileMetadata.exifLongitude = "-1" database.add(newLocalFileMetadata, update: .all) - Logger.ncFilesDatabase.debug("Added local file metadata from item metadata. ocID: \(itemMetadata.ocId, privacy: .public), etag: \(itemMetadata.etag, privacy: .public), fileName: \(itemMetadata.fileName, privacy: .public)") + Logger.ncFilesDatabase.debug( + "Added local file metadata from item metadata. ocID: \(itemMetadata.ocId, privacy: .public), etag: \(itemMetadata.etag, privacy: .public), fileName: \(itemMetadata.fileName, privacy: .public)" + ) } - } catch let error { - Logger.ncFilesDatabase.error("Could not add local file metadata from item metadata. ocID: \(itemMetadata.ocId, privacy: .public), etag: \(itemMetadata.etag, privacy: .public), fileName: \(itemMetadata.fileName, privacy: .public), received error: \(error.localizedDescription, privacy: .public)") + } catch { + Logger.ncFilesDatabase.error( + "Could not add local file metadata from item metadata. ocID: \(itemMetadata.ocId, privacy: .public), etag: \(itemMetadata.etag, privacy: .public), fileName: \(itemMetadata.fileName, privacy: .public), received error: \(error.localizedDescription, privacy: .public)" + ) } } @@ -53,34 +59,42 @@ extension NextcloudFilesDatabaseManager { do { try database.write { - let results = database.objects(NextcloudLocalFileMetadataTable.self).filter("ocId == %@", ocId) + let results = database.objects(NextcloudLocalFileMetadataTable.self).filter( + "ocId == %@", ocId) database.delete(results) } - } catch let error { - Logger.ncFilesDatabase.error("Could not delete local file metadata with ocId: \(ocId, privacy: .public), received error: \(error.localizedDescription, privacy: .public)") + } catch { + Logger.ncFilesDatabase.error( + "Could not delete local file metadata with ocId: \(ocId, privacy: .public), received error: \(error.localizedDescription, privacy: .public)" + ) } } - private func sortedLocalFileMetadatas(_ metadatas: Results) -> [NextcloudLocalFileMetadataTable] { + private func sortedLocalFileMetadatas(_ metadatas: Results) + -> [NextcloudLocalFileMetadataTable] + { let sortedMetadatas = metadatas.sorted(byKeyPath: "fileName", ascending: true) return Array(sortedMetadatas.map { NextcloudLocalFileMetadataTable(value: $0) }) } func localFileMetadatas(account: String) -> [NextcloudLocalFileMetadataTable] { - let results = ncDatabase().objects(NextcloudLocalFileMetadataTable.self).filter("account == %@", account) + let results = ncDatabase().objects(NextcloudLocalFileMetadataTable.self).filter( + "account == %@", account) return sortedLocalFileMetadatas(results) } func localFileItemMetadatas(account: String) -> [NextcloudItemMetadataTable] { let localFileMetadatas = localFileMetadatas(account: account) - let localFileMetadatasOcIds = Array(localFileMetadatas.map { $0.ocId }) + let localFileMetadatasOcIds = Array(localFileMetadatas.map(\.ocId)) var itemMetadatas: [NextcloudItemMetadataTable] = [] for ocId in localFileMetadatasOcIds { guard let itemMetadata = itemMetadataFromOcId(ocId) else { - Logger.ncFilesDatabase.error("Could not find matching item metadata for local file metadata with ocId: \(ocId, privacy: .public) with request from account: \(account)") - continue; + Logger.ncFilesDatabase.error( + "Could not find matching item metadata for local file metadata with ocId: \(ocId, privacy: .public) with request from account: \(account)" + ) + continue } itemMetadatas.append(NextcloudItemMetadataTable(value: itemMetadata)) diff --git a/shell_integration/MacOSX/NextcloudIntegration/FileProviderExt/Database/NextcloudFilesDatabaseManager.swift b/shell_integration/MacOSX/NextcloudIntegration/FileProviderExt/Database/NextcloudFilesDatabaseManager.swift index 158f28111..f0344f40b 100644 --- a/shell_integration/MacOSX/NextcloudIntegration/FileProviderExt/Database/NextcloudFilesDatabaseManager.swift +++ b/shell_integration/MacOSX/NextcloudIntegration/FileProviderExt/Database/NextcloudFilesDatabaseManager.swift @@ -12,16 +12,14 @@ * for more details. */ -import Foundation -import RealmSwift import FileProvider +import Foundation import NextcloudKit import OSLog +import RealmSwift -class NextcloudFilesDatabaseManager : NSObject { - static let shared = { - return NextcloudFilesDatabaseManager(); - }() +class NextcloudFilesDatabaseManager: NSObject { + static let shared = NextcloudFilesDatabaseManager() let relativeDatabaseFolderPath = "Database/" let databaseFilename = "fileproviderextdatabase.realm" @@ -31,29 +29,36 @@ class NextcloudFilesDatabaseManager : NSObject { let schemaVersion: UInt64 = 100 override init() { - self.relativeDatabaseFilePath = self.relativeDatabaseFolderPath + self.databaseFilename + relativeDatabaseFilePath = relativeDatabaseFolderPath + databaseFilename guard let fileProviderDataDirUrl = pathForFileProviderExtData() else { super.init() return } - self.databasePath = fileProviderDataDirUrl.appendingPathComponent(self.relativeDatabaseFilePath) + databasePath = fileProviderDataDirUrl.appendingPathComponent(relativeDatabaseFilePath) // Disable file protection for directory DB // https://docs.mongodb.com/realm/sdk/ios/examples/configure-and-open-a-realm/#std-label-ios-open-a-local-realm - let dbFolder = fileProviderDataDirUrl.appendingPathComponent(self.relativeDatabaseFolderPath) + let dbFolder = fileProviderDataDirUrl.appendingPathComponent(relativeDatabaseFolderPath) let dbFolderPath = dbFolder.path do { try FileManager.default.createDirectory(at: dbFolder, withIntermediateDirectories: true) - try FileManager.default.setAttributes([FileAttributeKey.protectionKey: FileProtectionType.completeUntilFirstUserAuthentication], ofItemAtPath: dbFolderPath) - } catch let error { - Logger.ncFilesDatabase.error("Could not set permission level for File Provider database folder, received error: \(error.localizedDescription, privacy: .public)") + try FileManager.default.setAttributes( + [ + FileAttributeKey.protectionKey: FileProtectionType + .completeUntilFirstUserAuthentication + ], + ofItemAtPath: dbFolderPath) + } catch { + Logger.ncFilesDatabase.error( + "Could not set permission level for File Provider database folder, received error: \(error.localizedDescription, privacy: .public)" + ) } let config = Realm.Configuration( - fileURL: self.databasePath, - schemaVersion: self.schemaVersion, + fileURL: databasePath, + schemaVersion: schemaVersion, objectTypes: [NextcloudItemMetadataTable.self, NextcloudLocalFileMetadataTable.self] ) @@ -63,7 +68,8 @@ class NextcloudFilesDatabaseManager : NSObject { _ = try Realm() Logger.ncFilesDatabase.info("Successfully started Realm db for FileProviderExt") } catch let error as NSError { - Logger.ncFilesDatabase.error("Error opening Realm db: \(error.localizedDescription, privacy: .public)") + Logger.ncFilesDatabase.error( + "Error opening Realm db: \(error.localizedDescription, privacy: .public)") } super.init() @@ -76,81 +82,106 @@ class NextcloudFilesDatabaseManager : NSObject { } func anyItemMetadatasForAccount(_ account: String) -> Bool { - return !ncDatabase().objects(NextcloudItemMetadataTable.self).filter("account == %@", account).isEmpty + !ncDatabase().objects(NextcloudItemMetadataTable.self).filter("account == %@", account) + .isEmpty } func itemMetadataFromOcId(_ ocId: String) -> NextcloudItemMetadataTable? { // Realm objects are live-fire, i.e. they will be changed and invalidated according to changes in the db // Let's therefore create a copy - if let itemMetadata = ncDatabase().objects(NextcloudItemMetadataTable.self).filter("ocId == %@", ocId).first { + if let itemMetadata = ncDatabase().objects(NextcloudItemMetadataTable.self).filter( + "ocId == %@", ocId + ).first { return NextcloudItemMetadataTable(value: itemMetadata) } return nil } - func sortedItemMetadatas(_ metadatas: Results) -> [NextcloudItemMetadataTable] { + func sortedItemMetadatas(_ metadatas: Results) + -> [NextcloudItemMetadataTable] + { let sortedMetadatas = metadatas.sorted(byKeyPath: "fileName", ascending: true) return Array(sortedMetadatas.map { NextcloudItemMetadataTable(value: $0) }) } func itemMetadatas(account: String) -> [NextcloudItemMetadataTable] { - let metadatas = ncDatabase().objects(NextcloudItemMetadataTable.self).filter("account == %@", account) + let metadatas = ncDatabase().objects(NextcloudItemMetadataTable.self).filter( + "account == %@", account) return sortedItemMetadatas(metadatas) } func itemMetadatas(account: String, serverUrl: String) -> [NextcloudItemMetadataTable] { - let metadatas = ncDatabase().objects(NextcloudItemMetadataTable.self).filter("account == %@ AND serverUrl == %@", account, serverUrl) + let metadatas = ncDatabase().objects(NextcloudItemMetadataTable.self).filter( + "account == %@ AND serverUrl == %@", account, serverUrl) return sortedItemMetadatas(metadatas) } - func itemMetadatas(account: String, serverUrl: String, status: NextcloudItemMetadataTable.Status) -> [NextcloudItemMetadataTable] { - let metadatas = ncDatabase().objects(NextcloudItemMetadataTable.self).filter("account == %@ AND serverUrl == %@ AND status == %@", account, serverUrl, status.rawValue) + func itemMetadatas( + account: String, serverUrl: String, status: NextcloudItemMetadataTable.Status + ) + -> [NextcloudItemMetadataTable] + { + let metadatas = ncDatabase().objects(NextcloudItemMetadataTable.self).filter( + "account == %@ AND serverUrl == %@ AND status == %@", account, serverUrl, + status.rawValue) return sortedItemMetadatas(metadatas) } - func itemMetadataFromFileProviderItemIdentifier(_ identifier: NSFileProviderItemIdentifier) -> NextcloudItemMetadataTable? { + func itemMetadataFromFileProviderItemIdentifier(_ identifier: NSFileProviderItemIdentifier) + -> NextcloudItemMetadataTable? + { let ocId = identifier.rawValue return itemMetadataFromOcId(ocId) } - private func processItemMetadatasToDelete(existingMetadatas: Results, - updatedMetadatas: [NextcloudItemMetadataTable]) -> [NextcloudItemMetadataTable] { - + private func processItemMetadatasToDelete( + existingMetadatas: Results, + updatedMetadatas: [NextcloudItemMetadataTable] + ) -> [NextcloudItemMetadataTable] { var deletedMetadatas: [NextcloudItemMetadataTable] = [] for existingMetadata in existingMetadatas { guard !updatedMetadatas.contains(where: { $0.ocId == existingMetadata.ocId }), - let metadataToDelete = itemMetadataFromOcId(existingMetadata.ocId) else { continue } + let metadataToDelete = itemMetadataFromOcId(existingMetadata.ocId) + else { continue } deletedMetadatas.append(metadataToDelete) - Logger.ncFilesDatabase.debug("Deleting item metadata during update. ocID: \(existingMetadata.ocId, privacy: .public), etag: \(existingMetadata.etag, privacy: .public), fileName: \(existingMetadata.fileName, privacy: .public)") + Logger.ncFilesDatabase.debug( + "Deleting item metadata during update. ocID: \(existingMetadata.ocId, privacy: .public), etag: \(existingMetadata.etag, privacy: .public), fileName: \(existingMetadata.fileName, privacy: .public)" + ) } return deletedMetadatas } - private func processItemMetadatasToUpdate(existingMetadatas: Results, - updatedMetadatas: [NextcloudItemMetadataTable], - updateDirectoryEtags: Bool) -> (newMetadatas: [NextcloudItemMetadataTable], updatedMetadatas: [NextcloudItemMetadataTable], directoriesNeedingRename: [NextcloudItemMetadataTable]) { - + private func processItemMetadatasToUpdate( + existingMetadatas: Results, + updatedMetadatas: [NextcloudItemMetadataTable], + updateDirectoryEtags: Bool + ) -> ( + newMetadatas: [NextcloudItemMetadataTable], updatedMetadatas: [NextcloudItemMetadataTable], + directoriesNeedingRename: [NextcloudItemMetadataTable] + ) { var returningNewMetadatas: [NextcloudItemMetadataTable] = [] var returningUpdatedMetadatas: [NextcloudItemMetadataTable] = [] var directoriesNeedingRename: [NextcloudItemMetadataTable] = [] for updatedMetadata in updatedMetadatas { - if let existingMetadata = existingMetadatas.first(where: { $0.ocId == updatedMetadata.ocId }) { - - if existingMetadata.status == NextcloudItemMetadataTable.Status.normal.rawValue && - !existingMetadata.isInSameDatabaseStoreableRemoteState(updatedMetadata) { - + if let existingMetadata = existingMetadatas.first(where: { + $0.ocId == updatedMetadata.ocId + }) { + if existingMetadata.status == NextcloudItemMetadataTable.Status.normal.rawValue, + !existingMetadata.isInSameDatabaseStoreableRemoteState(updatedMetadata) + { if updatedMetadata.directory { - - if updatedMetadata.serverUrl != existingMetadata.serverUrl || updatedMetadata.fileName != existingMetadata.fileName { - - directoriesNeedingRename.append(NextcloudItemMetadataTable(value: updatedMetadata)) - updatedMetadata.etag = "" // Renaming doesn't change the etag so reset manually + if updatedMetadata.serverUrl != existingMetadata.serverUrl + || updatedMetadata.fileName != existingMetadata.fileName + { + directoriesNeedingRename.append( + NextcloudItemMetadataTable(value: updatedMetadata)) + updatedMetadata.etag = "" // Renaming doesn't change the etag so reset manually } else if !updateDirectoryEtags { updatedMetadata.etag = existingMetadata.etag @@ -159,49 +190,68 @@ class NextcloudFilesDatabaseManager : NSObject { returningUpdatedMetadatas.append(updatedMetadata) - - Logger.ncFilesDatabase.debug("Updated existing item metadata. ocID: \(updatedMetadata.ocId, privacy: .public), etag: \(updatedMetadata.etag, privacy: .public), fileName: \(updatedMetadata.fileName, privacy: .public)") + Logger.ncFilesDatabase.debug( + "Updated existing item metadata. ocID: \(updatedMetadata.ocId, privacy: .public), etag: \(updatedMetadata.etag, privacy: .public), fileName: \(updatedMetadata.fileName, privacy: .public)" + ) } else { - Logger.ncFilesDatabase.debug("Skipping item metadata update; same as existing, or still downloading/uploading. ocID: \(updatedMetadata.ocId, privacy: .public), etag: \(updatedMetadata.etag, privacy: .public), fileName: \(updatedMetadata.fileName, privacy: .public)") + Logger.ncFilesDatabase.debug( + "Skipping item metadata update; same as existing, or still downloading/uploading. ocID: \(updatedMetadata.ocId, privacy: .public), etag: \(updatedMetadata.etag, privacy: .public), fileName: \(updatedMetadata.fileName, privacy: .public)" + ) } - } else { // This is a new metadata - if !updateDirectoryEtags && updatedMetadata.directory { + } else { // This is a new metadata + if !updateDirectoryEtags, updatedMetadata.directory { updatedMetadata.etag = "" } - + returningNewMetadatas.append(updatedMetadata) - Logger.ncFilesDatabase.debug("Created new item metadata during update. ocID: \(updatedMetadata.ocId, privacy: .public), etag: \(updatedMetadata.etag, privacy: .public), fileName: \(updatedMetadata.fileName, privacy: .public)") + Logger.ncFilesDatabase.debug( + "Created new item metadata during update. ocID: \(updatedMetadata.ocId, privacy: .public), etag: \(updatedMetadata.etag, privacy: .public), fileName: \(updatedMetadata.fileName, privacy: .public)" + ) } } return (returningNewMetadatas, returningUpdatedMetadatas, directoriesNeedingRename) } - func updateItemMetadatas(account: String, serverUrl: String, updatedMetadatas: [NextcloudItemMetadataTable], updateDirectoryEtags: Bool) -> (newMetadatas: [NextcloudItemMetadataTable]?, updatedMetadatas: [NextcloudItemMetadataTable]?, deletedMetadatas: [NextcloudItemMetadataTable]?) { + func updateItemMetadatas( + account: String, serverUrl: String, updatedMetadatas: [NextcloudItemMetadataTable], + updateDirectoryEtags: Bool + ) -> ( + newMetadatas: [NextcloudItemMetadataTable]?, + updatedMetadatas: [NextcloudItemMetadataTable]?, + deletedMetadatas: [NextcloudItemMetadataTable]? + ) { let database = ncDatabase() do { - let existingMetadatas = database.objects(NextcloudItemMetadataTable.self).filter("account == %@ AND serverUrl == %@ AND status == %@", account, serverUrl, NextcloudItemMetadataTable.Status.normal.rawValue) + let existingMetadatas = database.objects(NextcloudItemMetadataTable.self).filter( + "account == %@ AND serverUrl == %@ AND status == %@", account, serverUrl, + NextcloudItemMetadataTable.Status.normal.rawValue) - let metadatasToDelete = processItemMetadatasToDelete(existingMetadatas: existingMetadatas, - updatedMetadatas: updatedMetadatas) + let metadatasToDelete = processItemMetadatasToDelete( + existingMetadatas: existingMetadatas, + updatedMetadatas: updatedMetadatas) - let metadatasToChange = processItemMetadatasToUpdate(existingMetadatas: existingMetadatas, - updatedMetadatas: updatedMetadatas, - updateDirectoryEtags: updateDirectoryEtags) + let metadatasToChange = processItemMetadatasToUpdate( + existingMetadatas: existingMetadatas, + updatedMetadatas: updatedMetadatas, + updateDirectoryEtags: updateDirectoryEtags) var metadatasToUpdate = metadatasToChange.updatedMetadatas let metadatasToCreate = metadatasToChange.newMetadatas let directoriesNeedingRename = metadatasToChange.directoriesNeedingRename - let metadatasToAdd = Array(metadatasToUpdate.map { NextcloudItemMetadataTable(value: $0) }) + - Array(metadatasToCreate.map { NextcloudItemMetadataTable(value: $0) }) + let metadatasToAdd = + Array(metadatasToUpdate.map { NextcloudItemMetadataTable(value: $0) }) + + Array(metadatasToCreate.map { NextcloudItemMetadataTable(value: $0) }) for metadata in directoriesNeedingRename { - - if let updatedDirectoryChildren = renameDirectoryAndPropagateToChildren(ocId: metadata.ocId, newServerUrl: metadata.serverUrl, newFileName: metadata.fileName) { + if let updatedDirectoryChildren = renameDirectoryAndPropagateToChildren( + ocId: metadata.ocId, newServerUrl: metadata.serverUrl, + newFileName: metadata.fileName) + { metadatasToUpdate += updatedDirectoryChildren } } @@ -209,40 +259,59 @@ class NextcloudFilesDatabaseManager : NSObject { try database.write { for metadata in metadatasToDelete { // Can't pass copies, we need the originals from the database - database.delete(ncDatabase().objects(NextcloudItemMetadataTable.self).filter("ocId == %@", metadata.ocId)) + database.delete( + ncDatabase().objects(NextcloudItemMetadataTable.self).filter( + "ocId == %@", metadata.ocId)) } for metadata in metadatasToAdd { database.add(metadata, update: .all) } - } - return (newMetadatas: metadatasToCreate, updatedMetadatas: metadatasToUpdate, deletedMetadatas: metadatasToDelete) - } catch let error { - Logger.ncFilesDatabase.error("Could not update any item metadatas, received error: \(error.localizedDescription, privacy: .public)") + return ( + newMetadatas: metadatasToCreate, updatedMetadatas: metadatasToUpdate, + deletedMetadatas: metadatasToDelete + ) + } catch { + Logger.ncFilesDatabase.error( + "Could not update any item metadatas, received error: \(error.localizedDescription, privacy: .public)" + ) return (nil, nil, nil) } } - func setStatusForItemMetadata(_ metadata: NextcloudItemMetadataTable, status: NextcloudItemMetadataTable.Status, completionHandler: @escaping(_ updatedMetadata: NextcloudItemMetadataTable?) -> Void) { + func setStatusForItemMetadata( + _ metadata: NextcloudItemMetadataTable, status: NextcloudItemMetadataTable.Status, + completionHandler: @escaping (_ updatedMetadata: NextcloudItemMetadataTable?) -> Void + ) { let database = ncDatabase() do { try database.write { - guard let result = database.objects(NextcloudItemMetadataTable.self).filter("ocId == %@", metadata.ocId).first else { - Logger.ncFilesDatabase.debug("Did not update status for item metadata as it was not found. ocID: \(metadata.ocId, privacy: .public)") + guard + let result = database.objects(NextcloudItemMetadataTable.self).filter( + "ocId == %@", metadata.ocId + ).first + else { + Logger.ncFilesDatabase.debug( + "Did not update status for item metadata as it was not found. ocID: \(metadata.ocId, privacy: .public)" + ) return } result.status = status.rawValue database.add(result, update: .all) - Logger.ncFilesDatabase.debug("Updated status for item metadata. ocID: \(metadata.ocId, privacy: .public), etag: \(metadata.etag, privacy: .public), fileName: \(metadata.fileName, privacy: .public)") + Logger.ncFilesDatabase.debug( + "Updated status for item metadata. ocID: \(metadata.ocId, privacy: .public), etag: \(metadata.etag, privacy: .public), fileName: \(metadata.fileName, privacy: .public)" + ) completionHandler(NextcloudItemMetadataTable(value: result)) } - } catch let error { - Logger.ncFilesDatabase.error("Could not update status for item metadata with ocID: \(metadata.ocId, privacy: .public), etag: \(metadata.etag, privacy: .public), fileName: \(metadata.fileName, privacy: .public), received error: \(error.localizedDescription, privacy: .public)") + } catch { + Logger.ncFilesDatabase.error( + "Could not update status for item metadata with ocID: \(metadata.ocId, privacy: .public), etag: \(metadata.etag, privacy: .public), fileName: \(metadata.fileName, privacy: .public), received error: \(error.localizedDescription, privacy: .public)" + ) completionHandler(nil) } } @@ -253,10 +322,14 @@ class NextcloudFilesDatabaseManager : NSObject { do { try database.write { database.add(metadata, update: .all) - Logger.ncFilesDatabase.debug("Added item metadata. ocID: \(metadata.ocId, privacy: .public), etag: \(metadata.etag, privacy: .public), fileName: \(metadata.fileName, privacy: .public)") + Logger.ncFilesDatabase.debug( + "Added item metadata. ocID: \(metadata.ocId, privacy: .public), etag: \(metadata.etag, privacy: .public), fileName: \(metadata.fileName, privacy: .public)" + ) } - } catch let error { - Logger.ncFilesDatabase.error("Could not add item metadata. ocID: \(metadata.ocId, privacy: .public), etag: \(metadata.etag, privacy: .public), fileName: \(metadata.fileName, privacy: .public), received error: \(error.localizedDescription, privacy: .public)") + } catch { + Logger.ncFilesDatabase.error( + "Could not add item metadata. ocID: \(metadata.ocId, privacy: .public), etag: \(metadata.etag, privacy: .public), fileName: \(metadata.fileName, privacy: .public), received error: \(error.localizedDescription, privacy: .public)" + ) } } @@ -265,15 +338,18 @@ class NextcloudFilesDatabaseManager : NSObject { do { try database.write { - let results = database.objects(NextcloudItemMetadataTable.self).filter("ocId == %@", ocId) + let results = database.objects(NextcloudItemMetadataTable.self).filter( + "ocId == %@", ocId) Logger.ncFilesDatabase.debug("Deleting item metadata. \(ocId, privacy: .public)") database.delete(results) } return true - } catch let error { - Logger.ncFilesDatabase.error("Could not delete item metadata with ocId: \(ocId, privacy: .public), received error: \(error.localizedDescription, privacy: .public)") + } catch { + Logger.ncFilesDatabase.error( + "Could not delete item metadata with ocId: \(ocId, privacy: .public), received error: \(error.localizedDescription, privacy: .public)" + ) return false } } @@ -283,8 +359,14 @@ class NextcloudFilesDatabaseManager : NSObject { do { try database.write { - guard let itemMetadata = database.objects(NextcloudItemMetadataTable.self).filter("ocId == %@", ocId).first else { - Logger.ncFilesDatabase.debug("Could not find an item with ocID \(ocId, privacy: .public) to rename to \(newFileName, privacy: .public)") + guard + let itemMetadata = database.objects(NextcloudItemMetadataTable.self).filter( + "ocId == %@", ocId + ).first + else { + Logger.ncFilesDatabase.debug( + "Could not find an item with ocID \(ocId, privacy: .public) to rename to \(newFileName, privacy: .public)" + ) return } @@ -297,14 +379,20 @@ class NextcloudFilesDatabaseManager : NSObject { database.add(itemMetadata, update: .all) - Logger.ncFilesDatabase.debug("Renamed item \(oldFileName, privacy: .public) to \(newFileName, privacy: .public), moved from serverUrl: \(oldServerUrl, privacy: .public) to serverUrl: \(newServerUrl, privacy: .public)") + Logger.ncFilesDatabase.debug( + "Renamed item \(oldFileName, privacy: .public) to \(newFileName, privacy: .public), moved from serverUrl: \(oldServerUrl, privacy: .public) to serverUrl: \(newServerUrl, privacy: .public)" + ) } - } catch let error { - Logger.ncFilesDatabase.error("Could not rename filename of item metadata with ocID: \(ocId, privacy: .public) to proposed name \(newFileName, privacy: .public) at proposed serverUrl \(newServerUrl, privacy: .public), received error: \(error.localizedDescription, privacy: .public)") + } catch { + Logger.ncFilesDatabase.error( + "Could not rename filename of item metadata with ocID: \(ocId, privacy: .public) to proposed name \(newFileName, privacy: .public) at proposed serverUrl \(newServerUrl, privacy: .public), received error: \(error.localizedDescription, privacy: .public)" + ) } } - func parentItemIdentifierFromMetadata(_ metadata: NextcloudItemMetadataTable) -> NSFileProviderItemIdentifier? { + func parentItemIdentifierFromMetadata(_ metadata: NextcloudItemMetadataTable) + -> NSFileProviderItemIdentifier? + { let homeServerFilesUrl = metadata.urlBase + "/remote.php/dav/files/" + metadata.userId if metadata.serverUrl == homeServerFilesUrl { @@ -312,7 +400,9 @@ class NextcloudFilesDatabaseManager : NSObject { } guard let itemParentDirectory = parentDirectoryMetadataForItem(metadata) else { - Logger.ncFilesDatabase.error("Could not get item parent directory metadata for metadata. ocID: \(metadata.ocId, privacy: .public), etag: \(metadata.etag, privacy: .public), fileName: \(metadata.fileName, privacy: .public)") + Logger.ncFilesDatabase.error( + "Could not get item parent directory metadata for metadata. ocID: \(metadata.ocId, privacy: .public), etag: \(metadata.etag, privacy: .public), fileName: \(metadata.fileName, privacy: .public)" + ) return nil } @@ -320,7 +410,9 @@ class NextcloudFilesDatabaseManager : NSObject { return NSFileProviderItemIdentifier(parentDirectoryMetadata.ocId) } - Logger.ncFilesDatabase.error("Could not get item parent directory item metadata for metadata. ocID: \(metadata.ocId, privacy: .public), etag: \(metadata.etag, privacy: .public), fileName: \(metadata.fileName, privacy: .public)") + Logger.ncFilesDatabase.error( + "Could not get item parent directory item metadata for metadata. ocID: \(metadata.ocId, privacy: .public), etag: \(metadata.etag, privacy: .public), fileName: \(metadata.fileName, privacy: .public)" + ) return nil } } diff --git a/shell_integration/MacOSX/NextcloudIntegration/FileProviderExt/Database/NextcloudItemMetadataTable+NKFile.swift b/shell_integration/MacOSX/NextcloudIntegration/FileProviderExt/Database/NextcloudItemMetadataTable+NKFile.swift index 29683e722..e64818ebc 100644 --- a/shell_integration/MacOSX/NextcloudIntegration/FileProviderExt/Database/NextcloudItemMetadataTable+NKFile.swift +++ b/shell_integration/MacOSX/NextcloudIntegration/FileProviderExt/Database/NextcloudItemMetadataTable+NKFile.swift @@ -69,8 +69,10 @@ extension NextcloudItemMetadataTable { } metadata.size = file.size metadata.classFile = file.classFile - //FIXME: iOS 12.0,* don't detect UTI text/markdown, text/x-markdown - if (metadata.contentType == "text/markdown" || metadata.contentType == "text/x-markdown") && metadata.classFile == NKCommon.TypeClassFile.unknow.rawValue { + // FIXME: iOS 12.0,* don't detect UTI text/markdown, text/x-markdown + if metadata.contentType == "text/markdown" || metadata.contentType == "text/x-markdown", + metadata.classFile == NKCommon.TypeClassFile.unknow.rawValue + { metadata.classFile = NKCommon.TypeClassFile.document.rawValue } if let date = file.uploadDate { @@ -87,26 +89,30 @@ extension NextcloudItemMetadataTable { return metadata } - static func metadatasFromDirectoryReadNKFiles(_ files: [NKFile], - account: String, - completionHandler: @escaping (_ directoryMetadata: NextcloudItemMetadataTable, - _ childDirectoriesMetadatas: [NextcloudItemMetadataTable], - _ metadatas: [NextcloudItemMetadataTable]) -> Void) { - + static func metadatasFromDirectoryReadNKFiles( + _ files: [NKFile], + account: String, + completionHandler: @escaping ( + _ directoryMetadata: NextcloudItemMetadataTable, + _ childDirectoriesMetadatas: [NextcloudItemMetadataTable], + _ metadatas: [NextcloudItemMetadataTable] + ) -> Void + ) { var directoryMetadataSet = false var directoryMetadata = NextcloudItemMetadataTable() var childDirectoriesMetadatas: [NextcloudItemMetadataTable] = [] var metadatas: [NextcloudItemMetadataTable] = [] - let conversionQueue = DispatchQueue(label: "nkFileToMetadataConversionQueue", qos: .userInitiated, attributes: .concurrent) - let appendQueue = DispatchQueue(label: "metadataAppendQueue", qos: .userInitiated) // Serial queue + let conversionQueue = DispatchQueue( + label: "nkFileToMetadataConversionQueue", qos: .userInitiated, attributes: .concurrent) + let appendQueue = DispatchQueue(label: "metadataAppendQueue", qos: .userInitiated) // Serial queue let dispatchGroup = DispatchGroup() for file in files { - if metadatas.isEmpty && !directoryMetadataSet { + if metadatas.isEmpty, !directoryMetadataSet { let metadata = NextcloudItemMetadataTable.fromNKFile(file, account: account) - directoryMetadata = metadata; - directoryMetadataSet = true; + directoryMetadata = metadata + directoryMetadataSet = true } else { conversionQueue.async(group: dispatchGroup) { let metadata = NextcloudItemMetadataTable.fromNKFile(file, account: account) diff --git a/shell_integration/MacOSX/NextcloudIntegration/FileProviderExt/Database/NextcloudItemMetadataTable.swift b/shell_integration/MacOSX/NextcloudIntegration/FileProviderExt/Database/NextcloudItemMetadataTable.swift index b2555c695..84ab23e1d 100644 --- a/shell_integration/MacOSX/NextcloudIntegration/FileProviderExt/Database/NextcloudItemMetadataTable.swift +++ b/shell_integration/MacOSX/NextcloudIntegration/FileProviderExt/Database/NextcloudItemMetadataTable.swift @@ -12,10 +12,10 @@ * for more details. */ -import Foundation -import RealmSwift import FileProvider +import Foundation import NextcloudKit +import RealmSwift class NextcloudItemMetadataTable: Object { enum Status: Int { @@ -71,7 +71,7 @@ class NextcloudItemMetadataTable: Object { @Persisted var isExtractFile: Bool = false @Persisted var livePhoto: Bool = false @Persisted var mountType = "" - @Persisted var name = "" // for unifiedSearch is the provider.id + @Persisted var name = "" // for unifiedSearch is the provider.id @Persisted var note = "" @Persisted var ownerId = "" @Persisted var ownerDisplayName = "" @@ -88,13 +88,13 @@ class NextcloudItemMetadataTable: Object { @Persisted var quotaAvailableBytes: Int64 = 0 @Persisted var resourceType = "" @Persisted var richWorkspace: String? - @Persisted var serverUrl = "" // For parent directory!! + @Persisted var serverUrl = "" // For parent directory!! @Persisted var session = "" @Persisted var sessionError = "" @Persisted var sessionSelector = "" @Persisted var sessionTaskIdentifier: Int = 0 @Persisted var sharePermissionsCollaborationServices: Int = 0 - let sharePermissionsCloudMesh = List() // TODO: Find a way to compare these in remote state check + let sharePermissionsCloudMesh = List() // TODO: Find a way to compare these in remote state check let shareType = List() @Persisted var size: Int64 = 0 @Persisted var status: Int = 0 @@ -117,22 +117,25 @@ class NextcloudItemMetadataTable: Object { } var isRenameable: Bool { - return lock + lock } var isPrintable: Bool { if isDocumentViewableOnly { return false } - if ["application/pdf", "com.adobe.pdf"].contains(contentType) || contentType.hasPrefix("text/") || classFile == NKCommon.TypeClassFile.image.rawValue { + if ["application/pdf", "com.adobe.pdf"].contains(contentType) + || contentType.hasPrefix("text/") + || classFile == NKCommon.TypeClassFile.image.rawValue + { return true } return false } var isDocumentViewableOnly: Bool { - return sharePermissionsCollaborationServices == SharePermissions.readShare.rawValue && - classFile == NKCommon.TypeClassFile.document.rawValue + sharePermissionsCollaborationServices == SharePermissions.readShare.rawValue + && classFile == NKCommon.TypeClassFile.document.rawValue } var isCopyableInPasteboard: Bool { @@ -143,22 +146,21 @@ class NextcloudItemMetadataTable: Object { if directory || isDocumentViewableOnly { return false } - return contentType == "com.adobe.pdf" || contentType == "application/pdf" || classFile == NKCommon.TypeClassFile.image.rawValue + return contentType == "com.adobe.pdf" || contentType == "application/pdf" + || classFile == NKCommon.TypeClassFile.image.rawValue } var isSettableOnOffline: Bool { - return session.isEmpty && !isDocumentViewableOnly + session.isEmpty && !isDocumentViewableOnly } var canOpenIn: Bool { - return session.isEmpty && !isDocumentViewableOnly && !directory + session.isEmpty && !isDocumentViewableOnly && !directory } var isDownloadUpload: Bool { - return status == Status.inDownload.rawValue || - status == Status.downloading.rawValue || - status == Status.inUpload.rawValue || - status == Status.uploading.rawValue + status == Status.inDownload.rawValue || status == Status.downloading.rawValue + || status == Status.inUpload.rawValue || status == Status.uploading.rawValue } var isDownload: Bool { @@ -171,30 +173,28 @@ class NextcloudItemMetadataTable: Object { override func isEqual(_ object: Any?) -> Bool { if let object = object as? NextcloudItemMetadataTable { - return self.fileId == object.fileId && - self.account == object.account && - self.path == object.path && - self.fileName == object.fileName + return fileId == object.fileId && account == object.account && path == object.path + && fileName == object.fileName } return false } - func isInSameDatabaseStoreableRemoteState(_ comparingMetadata: NextcloudItemMetadataTable) -> Bool { - return comparingMetadata.etag == self.etag && - comparingMetadata.fileNameView == self.fileNameView && - comparingMetadata.date == self.date && - comparingMetadata.permissions == self.permissions && - comparingMetadata.hasPreview == self.hasPreview && - comparingMetadata.note == self.note && - comparingMetadata.lock == self.lock && - comparingMetadata.sharePermissionsCollaborationServices == self.sharePermissionsCollaborationServices && - comparingMetadata.favorite == self.favorite + func isInSameDatabaseStoreableRemoteState(_ comparingMetadata: NextcloudItemMetadataTable) + -> Bool + { + comparingMetadata.etag == etag && comparingMetadata.fileNameView == fileNameView + && comparingMetadata.date == date && comparingMetadata.permissions == permissions + && comparingMetadata.hasPreview == hasPreview && comparingMetadata.note == note + && comparingMetadata.lock == lock + && comparingMetadata.sharePermissionsCollaborationServices + == sharePermissionsCollaborationServices + && comparingMetadata.favorite == favorite } /// Returns false if the user is lokced out of the file. I.e. The file is locked but by someone else func canUnlock(as user: String) -> Bool { - return !lock || (lockOwner == user && lockOwnerType == 0) + !lock || (lockOwner == user && lockOwnerType == 0) } func thumbnailUrl(size: CGSize) -> URL? { @@ -203,10 +203,12 @@ class NextcloudItemMetadataTable: Object { } let urlBase = urlBase.urlEncoded! - let webdavUrl = urlBase + NextcloudAccount.webDavFilesUrlSuffix + user // Leave the leading slash - let serverFileRelativeUrl = serverUrl.replacingOccurrences(of: webdavUrl, with: "") + "/" + fileName + let webdavUrl = urlBase + NextcloudAccount.webDavFilesUrlSuffix + user // Leave the leading slash + let serverFileRelativeUrl = + serverUrl.replacingOccurrences(of: webdavUrl, with: "") + "/" + fileName - let urlString = "\(urlBase)/index.php/core/preview.png?file=\(serverFileRelativeUrl)&x=\(size.width)&y=\(size.height)&a=1&mode=cover" + let urlString = + "\(urlBase)/index.php/core/preview.png?file=\(serverFileRelativeUrl)&x=\(size.width)&y=\(size.height)&a=1&mode=cover" return URL(string: urlString) } diff --git a/shell_integration/MacOSX/NextcloudIntegration/FileProviderExt/Extensions/Logger+Extensions.swift b/shell_integration/MacOSX/NextcloudIntegration/FileProviderExt/Extensions/Logger+Extensions.swift index 971194928..f58ff0e90 100644 --- a/shell_integration/MacOSX/NextcloudIntegration/FileProviderExt/Extensions/Logger+Extensions.swift +++ b/shell_integration/MacOSX/NextcloudIntegration/FileProviderExt/Extensions/Logger+Extensions.swift @@ -17,11 +17,14 @@ import OSLog extension Logger { private static var subsystem = Bundle.main.bundleIdentifier! - static let desktopClientConnection = Logger(subsystem: subsystem, category: "desktopclientconnection") + static let desktopClientConnection = Logger( + subsystem: subsystem, category: "desktopclientconnection") static let enumeration = Logger(subsystem: subsystem, category: "enumeration") - static let fileProviderExtension = Logger(subsystem: subsystem, category: "fileproviderextension") + static let fileProviderExtension = Logger( + subsystem: subsystem, category: "fileproviderextension") static let fileTransfer = Logger(subsystem: subsystem, category: "filetransfer") static let localFileOps = Logger(subsystem: subsystem, category: "localfileoperations") static let ncFilesDatabase = Logger(subsystem: subsystem, category: "nextcloudfilesdatabase") - static let materialisedFileHandling = Logger(subsystem: subsystem, category: "materialisedfilehandling") + static let materialisedFileHandling = Logger( + subsystem: subsystem, category: "materialisedfilehandling") } diff --git a/shell_integration/MacOSX/NextcloudIntegration/FileProviderExt/Extensions/NKError+Extensions.swift b/shell_integration/MacOSX/NextcloudIntegration/FileProviderExt/Extensions/NKError+Extensions.swift index f9ca6681f..b3c1be803 100644 --- a/shell_integration/MacOSX/NextcloudIntegration/FileProviderExt/Extensions/NKError+Extensions.swift +++ b/shell_integration/MacOSX/NextcloudIntegration/FileProviderExt/Extensions/NKError+Extensions.swift @@ -12,57 +12,49 @@ * for more details. */ -import Foundation import FileProvider +import Foundation import NextcloudKit extension NKError { static var noChangesErrorCode: Int { - return -200 + -200 } var isCouldntConnectError: Bool { - return errorCode == -9999 || - errorCode == -1001 || - errorCode == -1004 || - errorCode == -1005 || - errorCode == -1009 || - errorCode == -1012 || - errorCode == -1200 || - errorCode == -1202 || - errorCode == 500 || - errorCode == 503 || - errorCode == 200 + errorCode == -9999 || errorCode == -1001 || errorCode == -1004 || errorCode == -1005 + || errorCode == -1009 || errorCode == -1012 || errorCode == -1200 || errorCode == -1202 + || errorCode == 500 || errorCode == 503 || errorCode == 200 } var isUnauthenticatedError: Bool { - return errorCode == -1013 + errorCode == -1013 } var isGoingOverQuotaError: Bool { - return errorCode == 507 + errorCode == 507 } var isNotFoundError: Bool { - return errorCode == 404 + errorCode == 404 } var isNoChangesError: Bool { - return errorCode == NKError.noChangesErrorCode + errorCode == NKError.noChangesErrorCode } var fileProviderError: NSFileProviderError { if isNotFoundError { - return NSFileProviderError(.noSuchItem) + NSFileProviderError(.noSuchItem) } else if isCouldntConnectError { // Provide something the file provider can do something with - return NSFileProviderError(.serverUnreachable) + NSFileProviderError(.serverUnreachable) } else if isUnauthenticatedError { - return NSFileProviderError(.notAuthenticated) + NSFileProviderError(.notAuthenticated) } else if isGoingOverQuotaError { - return NSFileProviderError(.insufficientQuota) + NSFileProviderError(.insufficientQuota) } else { - return NSFileProviderError(.cannotSynchronize) + NSFileProviderError(.cannotSynchronize) } } } diff --git a/shell_integration/MacOSX/NextcloudIntegration/FileProviderExt/Extensions/Progress+Extensions.swift b/shell_integration/MacOSX/NextcloudIntegration/FileProviderExt/Extensions/Progress+Extensions.swift index e15e2e0ad..630a370dd 100644 --- a/shell_integration/MacOSX/NextcloudIntegration/FileProviderExt/Extensions/Progress+Extensions.swift +++ b/shell_integration/MacOSX/NextcloudIntegration/FileProviderExt/Extensions/Progress+Extensions.swift @@ -12,39 +12,39 @@ * for more details. */ -import Foundation import Alamofire +import Foundation extension Progress { func setHandlersFromAfRequest(_ request: Request) { - self.cancellationHandler = { request.cancel() } - self.pausingHandler = { request.suspend() } - self.resumingHandler = { request.resume() } + cancellationHandler = { request.cancel() } + pausingHandler = { request.suspend() } + resumingHandler = { request.resume() } } func copyCurrentStateToProgress(_ otherProgress: Progress, includeHandlers: Bool = false) { if includeHandlers { - otherProgress.cancellationHandler = self.cancellationHandler - otherProgress.pausingHandler = self.pausingHandler - otherProgress.resumingHandler = self.resumingHandler + otherProgress.cancellationHandler = cancellationHandler + otherProgress.pausingHandler = pausingHandler + otherProgress.resumingHandler = resumingHandler } - - otherProgress.totalUnitCount = self.totalUnitCount - otherProgress.completedUnitCount = self.completedUnitCount - otherProgress.estimatedTimeRemaining = self.estimatedTimeRemaining - otherProgress.localizedDescription = self.localizedAdditionalDescription - otherProgress.localizedAdditionalDescription = self.localizedAdditionalDescription - otherProgress.isCancellable = self.isCancellable - otherProgress.isPausable = self.isPausable - otherProgress.fileCompletedCount = self.fileCompletedCount - otherProgress.fileURL = self.fileURL - otherProgress.fileTotalCount = self.fileTotalCount - otherProgress.fileCompletedCount = self.fileCompletedCount - otherProgress.fileOperationKind = self.fileOperationKind - otherProgress.kind = self.kind - otherProgress.throughput = self.throughput - for (key, object) in self.userInfo { + otherProgress.totalUnitCount = totalUnitCount + otherProgress.completedUnitCount = completedUnitCount + otherProgress.estimatedTimeRemaining = estimatedTimeRemaining + otherProgress.localizedDescription = localizedAdditionalDescription + otherProgress.localizedAdditionalDescription = localizedAdditionalDescription + otherProgress.isCancellable = isCancellable + otherProgress.isPausable = isPausable + otherProgress.fileCompletedCount = fileCompletedCount + otherProgress.fileURL = fileURL + otherProgress.fileTotalCount = fileTotalCount + otherProgress.fileCompletedCount = fileCompletedCount + otherProgress.fileOperationKind = fileOperationKind + otherProgress.kind = kind + otherProgress.throughput = throughput + + for (key, object) in userInfo { otherProgress.setUserInfoObject(object, forKey: key) } } diff --git a/shell_integration/MacOSX/NextcloudIntegration/FileProviderExt/FileProviderEnumerator+SyncEngine.swift b/shell_integration/MacOSX/NextcloudIntegration/FileProviderExt/FileProviderEnumerator+SyncEngine.swift index fdd81f83f..0fed8a9a7 100644 --- a/shell_integration/MacOSX/NextcloudIntegration/FileProviderExt/FileProviderEnumerator+SyncEngine.swift +++ b/shell_integration/MacOSX/NextcloudIntegration/FileProviderExt/FileProviderEnumerator+SyncEngine.swift @@ -17,27 +17,32 @@ import NextcloudKit import OSLog extension FileProviderEnumerator { - func fullRecursiveScan(ncAccount: NextcloudAccount, - ncKit: NextcloudKit, - scanChangesOnly: Bool, - completionHandler: @escaping(_ metadatas: [NextcloudItemMetadataTable], - _ newMetadatas: [NextcloudItemMetadataTable], - _ updatedMetadatas: [NextcloudItemMetadataTable], - _ deletedMetadatas: [NextcloudItemMetadataTable], - _ error: NKError?) -> Void) { - + func fullRecursiveScan( + ncAccount: NextcloudAccount, + ncKit: NextcloudKit, + scanChangesOnly: Bool, + completionHandler: @escaping ( + _ metadatas: [NextcloudItemMetadataTable], + _ newMetadatas: [NextcloudItemMetadataTable], + _ updatedMetadatas: [NextcloudItemMetadataTable], + _ deletedMetadatas: [NextcloudItemMetadataTable], + _ error: NKError? + ) -> Void + ) { let rootContainerDirectoryMetadata = NextcloudItemMetadataTable() rootContainerDirectoryMetadata.directory = true rootContainerDirectoryMetadata.ocId = NSFileProviderItemIdentifier.rootContainer.rawValue // Create a serial dispatch queue - let dispatchQueue = DispatchQueue(label: "recursiveChangeEnumerationQueue", qos: .userInitiated) + let dispatchQueue = DispatchQueue( + label: "recursiveChangeEnumerationQueue", qos: .userInitiated) dispatchQueue.async { - let results = self.scanRecursively(rootContainerDirectoryMetadata, - ncAccount: ncAccount, - ncKit: ncKit, - scanChangesOnly: scanChangesOnly) + let results = self.scanRecursively( + rootContainerDirectoryMetadata, + ncAccount: ncAccount, + ncKit: ncKit, + scanChangesOnly: scanChangesOnly) // Run a check to ensure files deleted in one location are not updated in another (e.g. when moved) // The recursive scan provides us with updated/deleted metadatas only on a folder by folder basis; @@ -45,29 +50,38 @@ extension FileProviderEnumerator { var checkedDeletedMetadatas = results.deletedMetadatas for updatedMetadata in results.updatedMetadatas { - guard let matchingDeletedMetadataIdx = checkedDeletedMetadatas.firstIndex(where: { $0.ocId == updatedMetadata.ocId } ) else { - continue; + guard + let matchingDeletedMetadataIdx = checkedDeletedMetadatas.firstIndex(where: { + $0.ocId == updatedMetadata.ocId + }) + else { + continue } checkedDeletedMetadatas.remove(at: matchingDeletedMetadataIdx) } DispatchQueue.main.async { - completionHandler(results.metadatas, results.newMetadatas, results.updatedMetadatas, checkedDeletedMetadatas, results.error) + completionHandler( + results.metadatas, results.newMetadatas, results.updatedMetadatas, + checkedDeletedMetadatas, results.error) } } } - private func scanRecursively(_ directoryMetadata: NextcloudItemMetadataTable, - ncAccount: NextcloudAccount, - ncKit: NextcloudKit, - scanChangesOnly: Bool) -> (metadatas: [NextcloudItemMetadataTable], - newMetadatas: [NextcloudItemMetadataTable], - updatedMetadatas: [NextcloudItemMetadataTable], - deletedMetadatas: [NextcloudItemMetadataTable], - error: NKError?) { - - if self.isInvalidated { + private func scanRecursively( + _ directoryMetadata: NextcloudItemMetadataTable, + ncAccount: NextcloudAccount, + ncKit: NextcloudKit, + scanChangesOnly: Bool + ) -> ( + metadatas: [NextcloudItemMetadataTable], + newMetadatas: [NextcloudItemMetadataTable], + updatedMetadatas: [NextcloudItemMetadataTable], + deletedMetadatas: [NextcloudItemMetadataTable], + error: NKError? + ) { + if isInvalidated { return ([], [], [], [], nil) } @@ -80,43 +94,59 @@ extension FileProviderEnumerator { var allDeletedMetadatas: [NextcloudItemMetadataTable] = [] let dbManager = NextcloudFilesDatabaseManager.shared - let dispatchGroup = DispatchGroup() // TODO: Maybe own thread? + let dispatchGroup = DispatchGroup() // TODO: Maybe own thread? dispatchGroup.enter() var criticalError: NKError? - let itemServerUrl = directoryMetadata.ocId == NSFileProviderItemIdentifier.rootContainer.rawValue ? - ncAccount.davFilesUrl : directoryMetadata.serverUrl + "/" + directoryMetadata.fileName + let itemServerUrl = + directoryMetadata.ocId == NSFileProviderItemIdentifier.rootContainer.rawValue + ? ncAccount.davFilesUrl : directoryMetadata.serverUrl + "/" + directoryMetadata.fileName Logger.enumeration.debug("About to read: \(itemServerUrl, privacy: .public)") - FileProviderEnumerator.readServerUrl(itemServerUrl, ncAccount: ncAccount, ncKit: ncKit, stopAtMatchingEtags: scanChangesOnly) { metadatas, newMetadatas, updatedMetadatas, deletedMetadatas, readError in + 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: .public) with \(readError!.localizedDescription, privacy: .public)") + guard nkReadError.isNoChangesError, scanChangesOnly else { + Logger.enumeration.error( + "Finishing enumeration of changes at \(itemServerUrl, privacy: .public) 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") + 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) { + 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") + 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.") + } 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." + ) - } else if nkReadError.isUnauthenticatedError || nkReadError.isCouldntConnectError { + } else if nkReadError.isUnauthenticatedError + || nkReadError.isCouldntConnectError + { // If it is a critical error then stop, if not then continue - Logger.enumeration.error("Error will affect next enumerated items, so stopping enumeration.") + Logger.enumeration.error( + "Error will affect next enumerated items, so stopping enumeration.") criticalError = nkReadError - } dispatchGroup.leave() @@ -124,30 +154,40 @@ extension FileProviderEnumerator { } } - Logger.enumeration.info("Finished reading serverUrl: \(itemServerUrl, privacy: .public) for user: \(ncAccount.ncKitAccount, privacy: .public)") + Logger.enumeration.info( + "Finished reading serverUrl: \(itemServerUrl, privacy: .public) for user: \(ncAccount.ncKitAccount, privacy: .public)" + ) - if let metadatas = metadatas { + if let metadatas { allMetadatas += metadatas } else { - Logger.enumeration.warning("WARNING: Nil metadatas received for reading of changes at \(itemServerUrl, privacy: .public) for user: \(ncAccount.ncKitAccount, privacy: .public)") + Logger.enumeration.warning( + "WARNING: Nil metadatas received for reading of changes at \(itemServerUrl, privacy: .public) for user: \(ncAccount.ncKitAccount, privacy: .public)" + ) } - if let newMetadatas = newMetadatas { + if let newMetadatas { allNewMetadatas += newMetadatas } else { - Logger.enumeration.warning("WARNING: Nil new metadatas received for reading of changes at \(itemServerUrl, privacy: .public) for user: \(ncAccount.ncKitAccount, privacy: .public)") + Logger.enumeration.warning( + "WARNING: Nil new metadatas received for reading of changes at \(itemServerUrl, privacy: .public) for user: \(ncAccount.ncKitAccount, privacy: .public)" + ) } - if let updatedMetadatas = updatedMetadatas { + if let updatedMetadatas { allUpdatedMetadatas += updatedMetadatas } else { - Logger.enumeration.warning("WARNING: Nil updated metadatas received for reading of changes at \(itemServerUrl, privacy: .public) for user: \(ncAccount.ncKitAccount, privacy: .public)") + Logger.enumeration.warning( + "WARNING: Nil updated metadatas received for reading of changes at \(itemServerUrl, privacy: .public) for user: \(ncAccount.ncKitAccount, privacy: .public)" + ) } - if let deletedMetadatas = deletedMetadatas { + if let deletedMetadatas { allDeletedMetadatas += deletedMetadatas } else { - Logger.enumeration.warning("WARNING: Nil deleted metadatas received for reading of changes at \(itemServerUrl, privacy: .public) for user: \(ncAccount.ncKitAccount, privacy: .public)") + Logger.enumeration.warning( + "WARNING: Nil deleted metadatas received for reading of changes at \(itemServerUrl, privacy: .public) for user: \(ncAccount.ncKitAccount, privacy: .public)" + ) } dispatchGroup.leave() @@ -160,13 +200,12 @@ extension FileProviderEnumerator { } var childDirectoriesToScan: [NextcloudItemMetadataTable] = [] - var candidateMetadatas: [NextcloudItemMetadataTable] - - if scanChangesOnly { - candidateMetadatas = allUpdatedMetadatas + allNewMetadatas - } else { - candidateMetadatas = allMetadatas - } + var candidateMetadatas: [NextcloudItemMetadataTable] = + if scanChangesOnly { + allUpdatedMetadatas + allNewMetadatas + } else { + allMetadatas + } for candidateMetadata in candidateMetadatas { if candidateMetadata.directory { @@ -175,14 +214,18 @@ extension FileProviderEnumerator { } if childDirectoriesToScan.isEmpty { - return (metadatas: allMetadatas, newMetadatas: allNewMetadatas, updatedMetadatas: allUpdatedMetadatas, deletedMetadatas: allDeletedMetadatas, nil) + return ( + metadatas: allMetadatas, newMetadatas: allNewMetadatas, + updatedMetadatas: allUpdatedMetadatas, deletedMetadatas: allDeletedMetadatas, nil + ) } for childDirectory in childDirectoriesToScan { - let childScanResult = scanRecursively(childDirectory, - ncAccount: ncAccount, - ncKit: ncKit, - scanChangesOnly: scanChangesOnly) + let childScanResult = scanRecursively( + childDirectory, + ncAccount: ncAccount, + ncKit: ncKit, + scanChangesOnly: scanChangesOnly) allMetadatas += childScanResult.metadatas allNewMetadatas += childScanResult.newMetadatas @@ -190,31 +233,44 @@ extension FileProviderEnumerator { allDeletedMetadatas += childScanResult.deletedMetadatas } - return (metadatas: allMetadatas, newMetadatas: allNewMetadatas, updatedMetadatas: allUpdatedMetadatas, deletedMetadatas: allDeletedMetadatas, nil) + return ( + metadatas: allMetadatas, newMetadatas: allNewMetadatas, + updatedMetadatas: allUpdatedMetadatas, + deletedMetadatas: allDeletedMetadatas, nil + ) } - static func handleDepth1ReadFileOrFolder(serverUrl: String, - ncAccount: NextcloudAccount, - files: [NKFile], - error: NKError, - completionHandler: @escaping (_ metadatas: [NextcloudItemMetadataTable]?, - _ newMetadatas: [NextcloudItemMetadataTable]?, - _ updatedMetadatas: [NextcloudItemMetadataTable]?, - _ deletedMetadatas: [NextcloudItemMetadataTable]?, - _ readError: Error?) -> Void) { - + static func handleDepth1ReadFileOrFolder( + serverUrl: String, + ncAccount: NextcloudAccount, + files: [NKFile], + error: NKError, + completionHandler: @escaping ( + _ metadatas: [NextcloudItemMetadataTable]?, + _ newMetadatas: [NextcloudItemMetadataTable]?, + _ updatedMetadatas: [NextcloudItemMetadataTable]?, + _ deletedMetadatas: [NextcloudItemMetadataTable]?, + _ readError: Error? + ) -> Void + ) { guard error == .success else { - Logger.enumeration.error("1 depth readFileOrFolder of url: \(serverUrl, privacy: .public) did not complete successfully, received error: \(error.errorDescription, privacy: .public)") + Logger.enumeration.error( + "1 depth readFileOrFolder of url: \(serverUrl, privacy: .public) 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: .public) for user: \(ncAccount.ncKitAccount, privacy: .public)") + Logger.enumeration.debug( + "Starting async conversion of NKFiles for serverUrl: \(serverUrl, privacy: .public) for user: \(ncAccount.ncKitAccount, privacy: .public)" + ) let dbManager = NextcloudFilesDatabaseManager.shared DispatchQueue.global(qos: .userInitiated).async { - NextcloudItemMetadataTable.metadatasFromDirectoryReadNKFiles(files, account: ncAccount.ncKitAccount) { directoryMetadata, childDirectoriesMetadata, metadatas in + NextcloudItemMetadataTable.metadatasFromDirectoryReadNKFiles( + files, account: ncAccount.ncKitAccount + ) { directoryMetadata, _, 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 @@ -228,64 +284,88 @@ extension FileProviderEnumerator { // 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: ncAccount.ncKitAccount, serverUrl: serverUrl, updatedMetadatas: metadatas, updateDirectoryEtags: false) + let changedMetadatas = dbManager.updateItemMetadatas( + account: ncAccount.ncKitAccount, serverUrl: serverUrl, + updatedMetadatas: metadatas, + updateDirectoryEtags: false) DispatchQueue.main.async { - completionHandler(metadatas, changedMetadatas.newMetadatas, changedMetadatas.updatedMetadatas, changedMetadatas.deletedMetadatas, nil) + completionHandler( + metadatas, changedMetadatas.newMetadatas, changedMetadatas.updatedMetadatas, + changedMetadatas.deletedMetadatas, nil) } } } } - static func readServerUrl(_ serverUrl: String, - ncAccount: NextcloudAccount, - ncKit: NextcloudKit, - stopAtMatchingEtags: Bool = false, - depth: String = "1", - completionHandler: @escaping (_ metadatas: [NextcloudItemMetadataTable]?, - _ newMetadatas: [NextcloudItemMetadataTable]?, - _ updatedMetadatas: [NextcloudItemMetadataTable]?, - _ deletedMetadatas: [NextcloudItemMetadataTable]?, - _ readError: Error?) -> Void) { - + static func readServerUrl( + _ serverUrl: String, + ncAccount: NextcloudAccount, + ncKit: NextcloudKit, + stopAtMatchingEtags: Bool = false, + depth: String = "1", + 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: .public) for user: \(ncAccount.ncKitAccount, privacy: .public) at depth \(depth, privacy: .public). NCKit info: userId: \(ncKit.nkCommonInstance.user, privacy: .public), password is empty: \(ncKit.nkCommonInstance.password == "" ? "EMPTY PASSWORD" : "NOT EMPTY PASSWORD"), urlBase: \(ncKit.nkCommonInstance.urlBase, privacy: .public), ncVersion: \(ncKit.nkCommonInstance.nextcloudVersion, privacy: .public)") + Logger.enumeration.debug( + "Starting to read serverUrl: \(serverUrl, privacy: .public) for user: \(ncAccount.ncKitAccount, privacy: .public) at depth \(depth, privacy: .public). NCKit info: userId: \(ncKit.nkCommonInstance.user, privacy: .public), password is empty: \(ncKit.nkCommonInstance.password == "" ? "EMPTY PASSWORD" : "NOT EMPTY PASSWORD"), urlBase: \(ncKit.nkCommonInstance.urlBase, privacy: .public), ncVersion: \(ncKit.nkCommonInstance.nextcloudVersion, privacy: .public)" + ) - ncKit.readFileOrFolder(serverUrlFileName: serverUrl, depth: depth, showHiddenFiles: true) { _, files, _, error in + ncKit.readFileOrFolder(serverUrlFileName: serverUrl, depth: depth, showHiddenFiles: true) { + _, files, _, error in guard error == .success else { - Logger.enumeration.error("\(depth, privacy: .public) depth readFileOrFolder of url: \(serverUrl, privacy: .public) did not complete successfully, received error: \(error.errorDescription, privacy: .public)") + Logger.enumeration.error( + "\(depth, privacy: .public) depth readFileOrFolder of url: \(serverUrl, privacy: .public) did not complete successfully, received error: \(error.errorDescription, privacy: .public)" + ) completionHandler(nil, nil, nil, nil, error.error) return } guard let receivedFile = files.first else { - Logger.enumeration.error("Received no items from readFileOrFolder of \(serverUrl, privacy: .public), not much we can do...") + Logger.enumeration.error( + "Received no items from readFileOrFolder of \(serverUrl, privacy: .public), not much we can do..." + ) completionHandler(nil, nil, nil, nil, error.error) return } guard receivedFile.directory else { - Logger.enumeration.debug("Read item is a file. Converting NKfile for serverUrl: \(serverUrl, privacy: .public) for user: \(ncAccount.ncKitAccount, privacy: .public)") - let itemMetadata = NextcloudItemMetadataTable.fromNKFile(receivedFile, account: ncKitAccount) - dbManager.addItemMetadata(itemMetadata) // TODO: Return some value when it is an update + Logger.enumeration.debug( + "Read item is a file. Converting NKfile for serverUrl: \(serverUrl, privacy: .public) for user: \(ncAccount.ncKitAccount, privacy: .public)" + ) + let itemMetadata = NextcloudItemMetadataTable.fromNKFile( + receivedFile, 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 directoryMetadata = dbManager.directoryMetadata( + account: ncKitAccount, serverUrl: serverUrl) + { let directoryEtag = directoryMetadata.etag guard directoryEtag == "" || directoryEtag != receivedFile.etag else { - Logger.enumeration.debug("Read server url called with flag to stop enumerating at matching etags. Returning and providing soft error.") + 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 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: ncKitAccount, serverUrl: serverUrl) + let metadatas = dbManager.itemMetadatas( + account: ncKitAccount, serverUrl: serverUrl) completionHandler(metadatas, nil, nil, nil, nkError.error) return @@ -294,7 +374,8 @@ extension FileProviderEnumerator { if depth == "0" { if serverUrl != ncAccount.davFilesUrl { - let metadata = NextcloudItemMetadataTable.fromNKFile(receivedFile, account: ncKitAccount) + let metadata = NextcloudItemMetadataTable.fromNKFile( + receivedFile, account: ncKitAccount) let isNew = dbManager.itemMetadataFromOcId(metadata.ocId) == nil let updatedMetadatas = isNew ? [] : [metadata] let newMetadatas = isNew ? [metadata] : [] @@ -306,7 +387,9 @@ extension FileProviderEnumerator { } } } else { - handleDepth1ReadFileOrFolder(serverUrl: serverUrl, ncAccount: ncAccount, files: files, error: error, completionHandler: completionHandler) + handleDepth1ReadFileOrFolder( + serverUrl: serverUrl, ncAccount: ncAccount, files: files, error: error, + completionHandler: completionHandler) } } } diff --git a/shell_integration/MacOSX/NextcloudIntegration/FileProviderExt/FileProviderEnumerator.swift b/shell_integration/MacOSX/NextcloudIntegration/FileProviderExt/FileProviderEnumerator.swift index a9dfacc9f..4ef7f8e1f 100644 --- a/shell_integration/MacOSX/NextcloudIntegration/FileProviderExt/FileProviderEnumerator.swift +++ b/shell_integration/MacOSX/NextcloudIntegration/FileProviderExt/FileProviderEnumerator.swift @@ -17,13 +17,13 @@ import NextcloudKit import OSLog class FileProviderEnumerator: NSObject, NSFileProviderEnumerator { - private let enumeratedItemIdentifier: NSFileProviderItemIdentifier private var enumeratedItemMetadata: NextcloudItemMetadataTable? private var enumeratingSystemIdentifier: Bool { - return FileProviderEnumerator.isSystemIdentifier(enumeratedItemIdentifier) + FileProviderEnumerator.isSystemIdentifier(enumeratedItemIdentifier) } - private let anchor = NSFileProviderSyncAnchor(Date().description.data(using: .utf8)!) // TODO: actually use this in NCKit and server requests + + private let anchor = NSFileProviderSyncAnchor(Date().description.data(using: .utf8)!) // TODO: actually use this in NCKit and server requests private static let maxItemsPerFileProviderPage = 100 let ncAccount: NextcloudAccount let ncKit: NextcloudKit @@ -31,59 +31,78 @@ class FileProviderEnumerator: NSObject, NSFileProviderEnumerator { var isInvalidated = false private static func isSystemIdentifier(_ identifier: NSFileProviderItemIdentifier) -> Bool { - return identifier == .rootContainer || - identifier == .trashContainer || - identifier == .workingSet + identifier == .rootContainer || identifier == .trashContainer || identifier == .workingSet } - - init(enumeratedItemIdentifier: NSFileProviderItemIdentifier, ncAccount: NextcloudAccount, ncKit: NextcloudKit) { + + init( + enumeratedItemIdentifier: NSFileProviderItemIdentifier, ncAccount: NextcloudAccount, + ncKit: NextcloudKit + ) { self.enumeratedItemIdentifier = enumeratedItemIdentifier self.ncAccount = ncAccount self.ncKit = ncKit if FileProviderEnumerator.isSystemIdentifier(enumeratedItemIdentifier) { - Logger.enumeration.debug("Providing enumerator for a system defined container: \(enumeratedItemIdentifier.rawValue, privacy: .public)") - self.serverUrl = ncAccount.davFilesUrl + Logger.enumeration.debug( + "Providing enumerator for a system defined container: \(enumeratedItemIdentifier.rawValue, privacy: .public)" + ) + serverUrl = ncAccount.davFilesUrl } else { - Logger.enumeration.debug("Providing enumerator for item with identifier: \(enumeratedItemIdentifier.rawValue, privacy: .public)") + Logger.enumeration.debug( + "Providing enumerator for item with identifier: \(enumeratedItemIdentifier.rawValue, privacy: .public)" + ) let dbManager = NextcloudFilesDatabaseManager.shared - enumeratedItemMetadata = dbManager.itemMetadataFromFileProviderItemIdentifier(enumeratedItemIdentifier) + enumeratedItemMetadata = dbManager.itemMetadataFromFileProviderItemIdentifier( + enumeratedItemIdentifier) if enumeratedItemMetadata != nil { - self.serverUrl = enumeratedItemMetadata!.serverUrl + "/" + enumeratedItemMetadata!.fileName + serverUrl = + enumeratedItemMetadata!.serverUrl + "/" + enumeratedItemMetadata!.fileName } else { - Logger.enumeration.error("Could not find itemMetadata for file with identifier: \(enumeratedItemIdentifier.rawValue, privacy: .public)") + Logger.enumeration.error( + "Could not find itemMetadata for file with identifier: \(enumeratedItemIdentifier.rawValue, privacy: .public)" + ) } } - Logger.enumeration.info("Set up enumerator for user: \(self.ncAccount.ncKitAccount, privacy: .public) with serverUrl: \(self.serverUrl, privacy: .public)") + Logger.enumeration.info( + "Set up enumerator for user: \(self.ncAccount.ncKitAccount, privacy: .public) with serverUrl: \(self.serverUrl, privacy: .public)" + ) super.init() } func invalidate() { - Logger.enumeration.debug("Enumerator is being invalidated for item with identifier: \(self.enumeratedItemIdentifier.rawValue, privacy: .public)") - self.isInvalidated = true + Logger.enumeration.debug( + "Enumerator is being invalidated for item with identifier: \(self.enumeratedItemIdentifier.rawValue, privacy: .public)" + ) + isInvalidated = true } // MARK: - Protocol methods - func enumerateItems(for observer: NSFileProviderEnumerationObserver, startingAt page: NSFileProviderPage) { - Logger.enumeration.debug("Received enumerate items request for enumerator with user: \(self.ncAccount.ncKitAccount, privacy: .public) with serverUrl: \(self.serverUrl, privacy: .public)") + func enumerateItems( + for observer: NSFileProviderEnumerationObserver, startingAt page: NSFileProviderPage + ) { + Logger.enumeration.debug( + "Received enumerate items request for enumerator with user: \(self.ncAccount.ncKitAccount, privacy: .public) with serverUrl: \(self.serverUrl, privacy: .public)" + ) /* - inspect the page to determine whether this is an initial or a follow-up request (TODO) - + If this is an enumerator for a directory, the root container or all directories: - perform a server request to fetch directory contents If this is an enumerator for the working set: - perform a server request to update your local database - fetch the working set from your local database - + - inform the observer about the items returned by the server (possibly multiple times) - inform the observer that you are finished with this page */ if enumeratedItemIdentifier == .trashContainer { - Logger.enumeration.debug("Enumerating trash set for user: \(self.ncAccount.ncKitAccount, privacy: .public) with serverUrl: \(self.serverUrl, privacy: .public)") + Logger.enumeration.debug( + "Enumerating trash set for user: \(self.ncAccount.ncKitAccount, privacy: .public) with serverUrl: \(self.serverUrl, privacy: .public)" + ) // TODO! observer.finishEnumerating(upTo: nil) @@ -98,105 +117,140 @@ class FileProviderEnumerator: NSObject, NSFileProviderEnumerator { // navigate a little bit in Finder, file picker, etc guard serverUrl != "" else { - Logger.enumeration.error("Enumerator has empty serverUrl -- can't enumerate that! For identifier: \(self.enumeratedItemIdentifier.rawValue, privacy: .public)") + Logger.enumeration.error( + "Enumerator has empty serverUrl -- can't enumerate that! For identifier: \(self.enumeratedItemIdentifier.rawValue, privacy: .public)" + ) observer.finishEnumeratingWithError(NSFileProviderError(.noSuchItem)) return } // TODO: Make better use of pagination and handle paging properly - if page == NSFileProviderPage.initialPageSortedByDate as NSFileProviderPage || - page == NSFileProviderPage.initialPageSortedByName as NSFileProviderPage { + if page == NSFileProviderPage.initialPageSortedByDate as NSFileProviderPage + || page == NSFileProviderPage.initialPageSortedByName as NSFileProviderPage + { + Logger.enumeration.debug( + "Enumerating initial page for user: \(self.ncAccount.ncKitAccount, privacy: .public) with serverUrl: \(self.serverUrl, privacy: .public)" + ) - Logger.enumeration.debug("Enumerating initial page for user: \(self.ncAccount.ncKitAccount, privacy: .public) with serverUrl: \(self.serverUrl, privacy: .public)") - - FileProviderEnumerator.readServerUrl(serverUrl, ncAccount: ncAccount, ncKit: ncKit) { metadatas, _, _, _, readError in + FileProviderEnumerator.readServerUrl(serverUrl, ncAccount: ncAccount, ncKit: ncKit) { + metadatas, _, _, _, readError in guard readError == nil else { - Logger.enumeration.error("Finishing enumeration for user: \(self.ncAccount.ncKitAccount, privacy: .public) with serverUrl: \(self.serverUrl, privacy: .public) with error \(readError!.localizedDescription, privacy: .public)") + Logger.enumeration.error( + "Finishing enumeration for user: \(self.ncAccount.ncKitAccount, privacy: .public) with serverUrl: \(self.serverUrl, privacy: .public) with error \(readError!.localizedDescription, privacy: .public)" + ) let nkReadError = NKError(error: readError!) observer.finishEnumeratingWithError(nkReadError.fileProviderError) return } - guard let metadatas = metadatas else { - Logger.enumeration.error("Finishing enumeration for user: \(self.ncAccount.ncKitAccount, privacy: .public) with serverUrl: \(self.serverUrl, privacy: .public) with invalid metadatas.") + guard let metadatas else { + Logger.enumeration.error( + "Finishing enumeration for user: \(self.ncAccount.ncKitAccount, privacy: .public) with serverUrl: \(self.serverUrl, privacy: .public) with invalid metadatas." + ) observer.finishEnumeratingWithError(NSFileProviderError(.cannotSynchronize)) return } - Logger.enumeration.info("Finished reading serverUrl: \(self.serverUrl, privacy: .public) for user: \(self.ncAccount.ncKitAccount, privacy: .public). Processed \(metadatas.count) metadatas") + Logger.enumeration.info( + "Finished reading serverUrl: \(self.serverUrl, privacy: .public) for user: \(self.ncAccount.ncKitAccount, privacy: .public). Processed \(metadatas.count) metadatas" + ) - FileProviderEnumerator.completeEnumerationObserver(observer, ncKit: self.ncKit, numPage: 1, itemMetadatas: metadatas) + FileProviderEnumerator.completeEnumerationObserver( + observer, ncKit: self.ncKit, numPage: 1, itemMetadatas: metadatas) } - return; + return } let numPage = Int(String(data: page.rawValue, encoding: .utf8)!)! - Logger.enumeration.debug("Enumerating page \(numPage, privacy: .public) for user: \(self.ncAccount.ncKitAccount, privacy: .public) with serverUrl: \(self.serverUrl, privacy: .public)") + Logger.enumeration.debug( + "Enumerating page \(numPage, privacy: .public) for user: \(self.ncAccount.ncKitAccount, privacy: .public) with serverUrl: \(self.serverUrl, privacy: .public)" + ) // TODO: Handle paging properly // FileProviderEnumerator.completeObserver(observer, ncKit: ncKit, numPage: numPage, itemMetadatas: nil) observer.finishEnumerating(upTo: nil) } - - func enumerateChanges(for observer: NSFileProviderChangeObserver, from anchor: NSFileProviderSyncAnchor) { - Logger.enumeration.debug("Received enumerate changes request for enumerator for user: \(self.ncAccount.ncKitAccount, privacy: .public) with serverUrl: \(self.serverUrl, privacy: .public)") + + func enumerateChanges( + for observer: NSFileProviderChangeObserver, from anchor: NSFileProviderSyncAnchor + ) { + Logger.enumeration.debug( + "Received enumerate changes request for enumerator for user: \(self.ncAccount.ncKitAccount, privacy: .public) with serverUrl: \(self.serverUrl, privacy: .public)" + ) /* - query the server for updates since the passed-in sync anchor (TODO) - + If this is an enumerator for the working set: - note the changes in your local database - + - inform the observer about item deletions and updates (modifications + insertions) - inform the observer when you have finished enumerating up to a subsequent sync anchor */ if enumeratedItemIdentifier == .workingSet { - Logger.enumeration.debug("Enumerating changes in working set for user: \(self.ncAccount.ncKitAccount, privacy: .public)") + Logger.enumeration.debug( + "Enumerating changes in working set for user: \(self.ncAccount.ncKitAccount, privacy: .public)" + ) // Unlike when enumerating items we can't progressively enumerate items as we need to wait to resolve which items are truly deleted and which // have just been moved elsewhere. - fullRecursiveScan(ncAccount: self.ncAccount, - ncKit: self.ncKit, - scanChangesOnly: true) { _, newMetadatas, updatedMetadatas, deletedMetadatas, error in + fullRecursiveScan( + ncAccount: ncAccount, + ncKit: ncKit, + scanChangesOnly: true + ) { _, newMetadatas, updatedMetadatas, deletedMetadatas, error in if self.isInvalidated { - Logger.enumeration.info("Enumerator invalidated during working set change scan. For user: \(self.ncAccount.ncKitAccount, privacy: .public)") + Logger.enumeration.info( + "Enumerator invalidated during working set change scan. For user: \(self.ncAccount.ncKitAccount, privacy: .public)" + ) observer.finishEnumeratingWithError(NSFileProviderError(.cannotSynchronize)) return } guard error == nil else { - Logger.enumeration.info("Finished recursive change enumeration of working set for user: \(self.ncAccount.ncKitAccount, privacy: .public) with error: \(error!.errorDescription, privacy: .public)") + Logger.enumeration.info( + "Finished recursive change enumeration of working set for user: \(self.ncAccount.ncKitAccount, privacy: .public) with error: \(error!.errorDescription, privacy: .public)" + ) observer.finishEnumeratingWithError(error!.fileProviderError) return } - Logger.enumeration.info("Finished recursive change enumeration of working set for user: \(self.ncAccount.ncKitAccount, privacy: .public). Enumerating items.") + Logger.enumeration.info( + "Finished recursive change enumeration of working set for user: \(self.ncAccount.ncKitAccount, privacy: .public). Enumerating items." + ) - FileProviderEnumerator.completeChangesObserver(observer, - anchor: anchor, - ncKit: self.ncKit, - newMetadatas: newMetadatas, - updatedMetadatas: updatedMetadatas, - deletedMetadatas: deletedMetadatas) + FileProviderEnumerator.completeChangesObserver( + observer, + anchor: anchor, + ncKit: self.ncKit, + newMetadatas: newMetadatas, + updatedMetadatas: updatedMetadatas, + deletedMetadatas: deletedMetadatas) } return } else if enumeratedItemIdentifier == .trashContainer { - Logger.enumeration.debug("Enumerating changes in trash set for user: \(self.ncAccount.ncKitAccount, privacy: .public)") + Logger.enumeration.debug( + "Enumerating changes in trash set for user: \(self.ncAccount.ncKitAccount, privacy: .public)" + ) // TODO! observer.finishEnumeratingChanges(upTo: anchor, moreComing: false) return } - Logger.enumeration.info("Enumerating changes for user: \(self.ncAccount.ncKitAccount, privacy: .public) with serverUrl: \(self.serverUrl, privacy: .public)") + Logger.enumeration.info( + "Enumerating changes for user: \(self.ncAccount.ncKitAccount, privacy: .public) with serverUrl: \(self.serverUrl, privacy: .public)" + ) // No matter what happens here we finish enumeration in some way, either from the error // handling below or from the completeChangesObserver // TODO: Move to the sync engine extension - FileProviderEnumerator.readServerUrl(serverUrl, ncAccount: ncAccount, ncKit: ncKit, stopAtMatchingEtags: true) { _, newMetadatas, updatedMetadatas, deletedMetadatas, readError in + 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] = [] @@ -205,46 +259,66 @@ class FileProviderEnumerator: NSObject, NSFileProviderEnumerator { } guard readError == nil else { - Logger.enumeration.error("Finishing enumeration of changes for user: \(self.ncAccount.ncKitAccount, privacy: .public) with serverUrl: \(self.serverUrl, privacy: .public) with error: \(readError!.localizedDescription, privacy: .public)") + Logger.enumeration.error( + "Finishing enumeration of changes for user: \(self.ncAccount.ncKitAccount, privacy: .public) with serverUrl: \(self.serverUrl, privacy: .public) with error: \(readError!.localizedDescription, privacy: .public)" + ) let nkReadError = NKError(error: readError!) let fpError = nkReadError.fileProviderError if nkReadError.isNotFoundError { - Logger.enumeration.info("404 error means item no longer exists. Deleting metadata and reporting \(self.serverUrl, privacy: .public) as deletion without error") + Logger.enumeration.info( + "404 error means item no longer exists. Deleting metadata and reporting \(self.serverUrl, privacy: .public) as deletion without error" + ) guard let itemMetadata = self.enumeratedItemMetadata else { - Logger.enumeration.error("Invalid enumeratedItemMetadata, could not delete metadata nor report deletion") + Logger.enumeration.error( + "Invalid enumeratedItemMetadata, could not delete metadata nor report deletion" + ) observer.finishEnumeratingWithError(fpError) return } let dbManager = NextcloudFilesDatabaseManager.shared if itemMetadata.directory { - if let deletedDirectoryMetadatas = 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.") + Logger.enumeration.error( + "Something went wrong when recursively deleting directory not found." + ) } } else { dbManager.deleteItemMetadata(ocId: itemMetadata.ocId) } - FileProviderEnumerator.completeChangesObserver(observer, anchor: anchor, ncKit: self.ncKit, newMetadatas: nil, updatedMetadatas: nil, deletedMetadatas: [itemMetadata]) + FileProviderEnumerator.completeChangesObserver( + observer, anchor: anchor, ncKit: self.ncKit, newMetadatas: nil, + updatedMetadatas: nil, + deletedMetadatas: [itemMetadata]) return - } else if nkReadError.isNoChangesError { // All is well, just no changed etags - Logger.enumeration.info("Error was to say no changed files -- not bad error. Finishing change enumeration.") + } else if nkReadError.isNoChangesError { // All is well, just no changed etags + Logger.enumeration.info( + "Error was to say no changed files -- not bad error. Finishing change enumeration." + ) observer.finishEnumeratingChanges(upTo: anchor, moreComing: false) - return; + return } observer.finishEnumeratingWithError(fpError) return } - Logger.enumeration.info("Finished reading serverUrl: \(self.serverUrl, privacy: .public) for user: \(self.ncAccount.ncKitAccount, privacy: .public)") + Logger.enumeration.info( + "Finished reading serverUrl: \(self.serverUrl, privacy: .public) for user: \(self.ncAccount.ncKitAccount, privacy: .public)" + ) - FileProviderEnumerator.completeChangesObserver(observer, anchor: anchor, ncKit: self.ncKit, newMetadatas: newMetadatas, updatedMetadatas: updatedMetadatas, deletedMetadatas: deletedMetadatas) + FileProviderEnumerator.completeChangesObserver( + observer, anchor: anchor, ncKit: self.ncKit, newMetadatas: newMetadatas, + updatedMetadatas: updatedMetadatas, deletedMetadatas: deletedMetadatas) } } @@ -254,29 +328,43 @@ class FileProviderEnumerator: NSObject, NSFileProviderEnumerator { // MARK: - Helper methods - private static func metadatasToFileProviderItems(_ itemMetadatas: [NextcloudItemMetadataTable], ncKit: NextcloudKit, completionHandler: @escaping(_ items: [NSFileProviderItem]) -> Void) { + private static func metadatasToFileProviderItems( + _ itemMetadatas: [NextcloudItemMetadataTable], ncKit: NextcloudKit, + completionHandler: @escaping (_ items: [NSFileProviderItem]) -> Void + ) { var items: [NSFileProviderItem] = [] - let conversionQueue = DispatchQueue(label: "metadataToItemConversionQueue", qos: .userInitiated, attributes: .concurrent) - let appendQueue = DispatchQueue(label: "enumeratorItemAppendQueue", qos: .userInitiated) // Serial queue + let conversionQueue = DispatchQueue( + label: "metadataToItemConversionQueue", qos: .userInitiated, attributes: .concurrent) + let appendQueue = DispatchQueue(label: "enumeratorItemAppendQueue", qos: .userInitiated) // Serial queue let dispatchGroup = DispatchGroup() for itemMetadata in itemMetadatas { conversionQueue.async(group: dispatchGroup) { if itemMetadata.e2eEncrypted { - Logger.enumeration.info("Skipping encrypted metadata in enumeration: \(itemMetadata.ocId, privacy: .public) \(itemMetadata.fileName, privacy: .public)") + Logger.enumeration.info( + "Skipping encrypted metadata in enumeration: \(itemMetadata.ocId, privacy: .public) \(itemMetadata.fileName, privacy: .public)" + ) return } - if let parentItemIdentifier = NextcloudFilesDatabaseManager.shared.parentItemIdentifierFromMetadata(itemMetadata) { - let item = FileProviderItem(metadata: itemMetadata, parentItemIdentifier: parentItemIdentifier, ncKit: ncKit) - Logger.enumeration.debug("Will enumerate item with ocId: \(itemMetadata.ocId, privacy: .public) and name: \(itemMetadata.fileName, privacy: .public)") + if let parentItemIdentifier = NextcloudFilesDatabaseManager.shared + .parentItemIdentifierFromMetadata(itemMetadata) + { + let item = FileProviderItem( + metadata: itemMetadata, parentItemIdentifier: parentItemIdentifier, + ncKit: ncKit) + Logger.enumeration.debug( + "Will enumerate item with ocId: \(itemMetadata.ocId, privacy: .public) and name: \(itemMetadata.fileName, privacy: .public)" + ) appendQueue.async(group: dispatchGroup) { items.append(item) } } else { - Logger.enumeration.error("Could not get valid parentItemIdentifier for item with ocId: \(itemMetadata.ocId, privacy: .public) and name: \(itemMetadata.fileName, privacy: .public), skipping enumeration") + Logger.enumeration.error( + "Could not get valid parentItemIdentifier for item with ocId: \(itemMetadata.ocId, privacy: .public) and name: \(itemMetadata.fileName, privacy: .public), skipping enumeration" + ) } } } @@ -287,11 +375,13 @@ class FileProviderEnumerator: NSObject, NSFileProviderEnumerator { } private static func fileProviderPageforNumPage(_ numPage: Int) -> NSFileProviderPage { - return NSFileProviderPage("\(numPage)".data(using: .utf8)!) + NSFileProviderPage("\(numPage)".data(using: .utf8)!) } - private static func completeEnumerationObserver(_ observer: NSFileProviderEnumerationObserver, ncKit: NextcloudKit, numPage: Int, itemMetadatas: [NextcloudItemMetadataTable]) { - + private static func completeEnumerationObserver( + _ observer: NSFileProviderEnumerationObserver, ncKit: NextcloudKit, numPage: Int, + itemMetadatas: [NextcloudItemMetadataTable] + ) { metadatasToFileProviderItems(itemMetadatas, ncKit: ncKit) { items in observer.didEnumerate(items) Logger.enumeration.info("Did enumerate \(items.count) items") @@ -310,10 +400,17 @@ class FileProviderEnumerator: NSObject, NSFileProviderEnumerator { } } - private static func completeChangesObserver(_ observer: NSFileProviderChangeObserver, anchor: NSFileProviderSyncAnchor, ncKit: NextcloudKit, newMetadatas: [NextcloudItemMetadataTable]?, updatedMetadatas: [NextcloudItemMetadataTable]?, deletedMetadatas: [NextcloudItemMetadataTable]?) { - + private static func completeChangesObserver( + _ observer: NSFileProviderChangeObserver, anchor: NSFileProviderSyncAnchor, + ncKit: NextcloudKit, + newMetadatas: [NextcloudItemMetadataTable]?, + updatedMetadatas: [NextcloudItemMetadataTable]?, + deletedMetadatas: [NextcloudItemMetadataTable]? + ) { guard newMetadatas != nil || updatedMetadatas != nil || deletedMetadatas != nil else { - Logger.enumeration.error("Received invalid newMetadatas, updatedMetadatas or deletedMetadatas. Finished enumeration of changes with error.") + Logger.enumeration.error( + "Received invalid newMetadatas, updatedMetadatas or deletedMetadatas. Finished enumeration of changes with error." + ) observer.finishEnumeratingWithError(NSFileProviderError(.noSuchItem)) return } @@ -322,19 +419,20 @@ class FileProviderEnumerator: NSObject, NSFileProviderEnumerator { var allUpdatedMetadatas: [NextcloudItemMetadataTable] = [] var allDeletedMetadatas: [NextcloudItemMetadataTable] = [] - if let newMetadatas = newMetadatas { + if let newMetadatas { allUpdatedMetadatas += newMetadatas } - if let updatedMetadatas = updatedMetadatas { + if let updatedMetadatas { allUpdatedMetadatas += updatedMetadatas } - if let deletedMetadatas = deletedMetadatas { + if let deletedMetadatas { allDeletedMetadatas = deletedMetadatas } - let allFpItemDeletionsIdentifiers = Array(allDeletedMetadatas.map { NSFileProviderItemIdentifier($0.ocId) }) + let allFpItemDeletionsIdentifiers = Array( + allDeletedMetadatas.map { NSFileProviderItemIdentifier($0.ocId) }) if !allFpItemDeletionsIdentifiers.isEmpty { observer.didDeleteItems(withIdentifiers: allFpItemDeletionsIdentifiers) } @@ -345,7 +443,9 @@ class FileProviderEnumerator: NSObject, NSFileProviderEnumerator { observer.didUpdate(updatedItems) } - Logger.enumeration.info("Processed \(updatedItems.count) new or updated metadatas, \(allDeletedMetadatas.count) deleted metadatas.") + Logger.enumeration.info( + "Processed \(updatedItems.count) new or updated metadatas, \(allDeletedMetadatas.count) deleted metadatas." + ) observer.finishEnumeratingChanges(upTo: anchor, moreComing: false) } } diff --git a/shell_integration/MacOSX/NextcloudIntegration/FileProviderExt/FileProviderExtension+ClientInterface.swift b/shell_integration/MacOSX/NextcloudIntegration/FileProviderExt/FileProviderExtension+ClientInterface.swift index dd3bef8d8..26c42aca8 100644 --- a/shell_integration/MacOSX/NextcloudIntegration/FileProviderExt/FileProviderExtension+ClientInterface.swift +++ b/shell_integration/MacOSX/NextcloudIntegration/FileProviderExt/FileProviderExtension+ClientInterface.swift @@ -12,11 +12,11 @@ * for more details. */ -import Foundation import FileProvider -import OSLog +import Foundation import NCDesktopClientSocketKit import NextcloudKit +import OSLog extension FileProviderExtension { func sendFileProviderDomainIdentifier() { @@ -28,7 +28,9 @@ extension FileProviderExtension { private func signalEnumeratorAfterAccountSetup() { guard let fpManager = NSFileProviderManager(for: domain) else { - Logger.fileProviderExtension.error("Could not get file provider manager for domain \(self.domain.displayName, privacy: .public), cannot notify after account setup") + Logger.fileProviderExtension.error( + "Could not get file provider manager for domain \(self.domain.displayName, privacy: .public), cannot notify after account setup" + ) return } @@ -36,36 +38,47 @@ extension FileProviderExtension { fpManager.signalErrorResolved(NSFileProviderError(.notAuthenticated)) { error in if error != nil { - Logger.fileProviderExtension.error("Error resolving not authenticated, received error: \(error!.localizedDescription)") + Logger.fileProviderExtension.error( + "Error resolving not authenticated, received error: \(error!.localizedDescription)" + ) } } - Logger.fileProviderExtension.debug("Signalling enumerators for user \(self.ncAccount!.username) at server \(self.ncAccount!.serverUrl, privacy: .public)") + Logger.fileProviderExtension.debug( + "Signalling enumerators for user \(self.ncAccount!.username) at server \(self.ncAccount!.serverUrl, privacy: .public)" + ) fpManager.signalEnumerator(for: .workingSet) { error in if error != nil { - Logger.fileProviderExtension.error("Error signalling enumerator for working set, received error: \(error!.localizedDescription, privacy: .public)") + Logger.fileProviderExtension.error( + "Error signalling enumerator for working set, received error: \(error!.localizedDescription, privacy: .public)" + ) } } } func setupDomainAccount(user: String, serverUrl: String, password: String) { ncAccount = NextcloudAccount(user: user, serverUrl: serverUrl, password: password) - ncKit.setup(user: ncAccount!.username, - userId: ncAccount!.username, - password: ncAccount!.password, - urlBase: ncAccount!.serverUrl, - userAgent: "Nextcloud-macOS/FileProviderExt", - nextcloudVersion: 25, - delegate: nil) // TODO: add delegate methods for self + ncKit.setup( + user: ncAccount!.username, + userId: ncAccount!.username, + password: ncAccount!.password, + urlBase: ncAccount!.serverUrl, + userAgent: "Nextcloud-macOS/FileProviderExt", + nextcloudVersion: 25, + delegate: nil) // TODO: add delegate methods for self - Logger.fileProviderExtension.info("Nextcloud account set up in File Provider extension for user: \(user, privacy: .public) at server: \(serverUrl, privacy: .public)") + Logger.fileProviderExtension.info( + "Nextcloud account set up in File Provider extension for user: \(user, privacy: .public) at server: \(serverUrl, privacy: .public)" + ) signalEnumeratorAfterAccountSetup() } func removeAccountConfig() { - Logger.fileProviderExtension.info("Received instruction to remove account data for user \(self.ncAccount!.username, privacy: .public) at server \(self.ncAccount!.serverUrl, privacy: .public)") + Logger.fileProviderExtension.info( + "Received instruction to remove account data for user \(self.ncAccount!.username, privacy: .public) at server \(self.ncAccount!.serverUrl, privacy: .public)" + ) ncAccount = nil } } diff --git a/shell_integration/MacOSX/NextcloudIntegration/FileProviderExt/FileProviderExtension+Thumbnailing.swift b/shell_integration/MacOSX/NextcloudIntegration/FileProviderExt/FileProviderExtension+Thumbnailing.swift index 7abc46090..daa4a24da 100644 --- a/shell_integration/MacOSX/NextcloudIntegration/FileProviderExt/FileProviderExtension+Thumbnailing.swift +++ b/shell_integration/MacOSX/NextcloudIntegration/FileProviderExt/FileProviderExtension+Thumbnailing.swift @@ -12,19 +12,22 @@ * for more details. */ -import Foundation import FileProvider +import Foundation import NextcloudKit import OSLog extension FileProviderExtension: NSFileProviderThumbnailing { - func fetchThumbnails(for itemIdentifiers: [NSFileProviderItemIdentifier], - requestedSize size: CGSize, - perThumbnailCompletionHandler: @escaping (NSFileProviderItemIdentifier, - Data?, - Error?) -> Void, - completionHandler: @escaping (Error?) -> Void) -> Progress { - + func fetchThumbnails( + for itemIdentifiers: [NSFileProviderItemIdentifier], + requestedSize size: CGSize, + perThumbnailCompletionHandler: @escaping ( + NSFileProviderItemIdentifier, + Data?, + Error? + ) -> Void, + completionHandler: @escaping (Error?) -> Void + ) -> Progress { let progress = Progress(totalUnitCount: Int64(itemIdentifiers.count)) var progressCounter: Int64 = 0 @@ -37,21 +40,29 @@ extension FileProviderExtension: NSFileProviderThumbnailing { } for itemIdentifier in itemIdentifiers { - Logger.fileProviderExtension.debug("Fetching thumbnail for item with identifier:\(itemIdentifier.rawValue, privacy: .public)") - guard let metadata = NextcloudFilesDatabaseManager.shared.itemMetadataFromFileProviderItemIdentifier(itemIdentifier), - let thumbnailUrl = metadata.thumbnailUrl(size: size) else { + Logger.fileProviderExtension.debug( + "Fetching thumbnail for item with identifier:\(itemIdentifier.rawValue, privacy: .public)" + ) + guard + let metadata = NextcloudFilesDatabaseManager.shared + .itemMetadataFromFileProviderItemIdentifier(itemIdentifier), + let thumbnailUrl = metadata.thumbnailUrl(size: size) + else { Logger.fileProviderExtension.debug("Did not fetch thumbnail URL") finishCurrent() continue } - Logger.fileProviderExtension.debug("Fetching thumbnail for file:\(metadata.fileName) at:\(thumbnailUrl.absoluteString, privacy: .public)") + Logger.fileProviderExtension.debug( + "Fetching thumbnail for file:\(metadata.fileName) at:\(thumbnailUrl.absoluteString, privacy: .public)" + ) - self.ncKit.getPreview(url: thumbnailUrl) { _, data, error in - if error == .success && data != nil { + ncKit.getPreview(url: thumbnailUrl) { _, data, error in + if error == .success, data != nil { perThumbnailCompletionHandler(itemIdentifier, data, nil) } else { - perThumbnailCompletionHandler(itemIdentifier, nil, NSFileProviderError(.serverUnreachable)) + perThumbnailCompletionHandler( + itemIdentifier, nil, NSFileProviderError(.serverUnreachable)) } finishCurrent() } diff --git a/shell_integration/MacOSX/NextcloudIntegration/FileProviderExt/FileProviderExtension.swift b/shell_integration/MacOSX/NextcloudIntegration/FileProviderExt/FileProviderExtension.swift index e4912dbaa..31c09f227 100644 --- a/shell_integration/MacOSX/NextcloudIntegration/FileProviderExt/FileProviderExtension.swift +++ b/shell_integration/MacOSX/NextcloudIntegration/FileProviderExt/FileProviderExtension.swift @@ -13,9 +13,9 @@ */ import FileProvider -import OSLog import NCDesktopClientSocketKit import NextcloudKit +import OSLog class FileProviderExtension: NSObject, NSFileProviderReplicatedExtension, NKCommonDelegate { let domain: NSFileProviderDomain @@ -25,15 +25,19 @@ class FileProviderExtension: NSObject, NSFileProviderReplicatedExtension, NKComm return nckb }() - let appGroupIdentifier: String? = Bundle.main.object(forInfoDictionaryKey: "SocketApiPrefix") as? String + let appGroupIdentifier: String? = + Bundle.main.object(forInfoDictionaryKey: "SocketApiPrefix") as? String var ncAccount: NextcloudAccount? lazy var socketClient: LocalSocketClient? = { guard let containerUrl = pathForAppGroupContainer() else { - Logger.fileProviderExtension.critical("Could not start file provider socket client properly as could not get container url") - return nil; + Logger.fileProviderExtension.critical( + "Could not start file provider socket client properly as could not get container url" + ) + return nil } - let socketPath = containerUrl.appendingPathComponent(".fileprovidersocket", conformingTo: .archive) + let socketPath = containerUrl.appendingPathComponent( + ".fileprovidersocket", conformingTo: .archive) let lineProcessor = FileProviderSocketLineProcessor(delegate: self) return LocalSocketClient(socketPath: socketPath.path, lineProcessor: lineProcessor) @@ -50,7 +54,9 @@ class FileProviderExtension: NSObject, NSFileProviderReplicatedExtension, NKComm configuration.requestCachePolicy = NSURLRequest.CachePolicy.reloadIgnoringLocalCacheData configuration.sharedContainerIdentifier = appGroupIdentifier - let session = URLSession(configuration: configuration, delegate: ncKitBackground, delegateQueue: OperationQueue.main) + let session = URLSession( + configuration: configuration, delegate: ncKitBackground, + delegateQueue: OperationQueue.main) return session }() @@ -59,23 +65,31 @@ class FileProviderExtension: NSObject, NSFileProviderReplicatedExtension, NKComm // The containing application must create a domain using `NSFileProviderManager.add(_:, completionHandler:)`. The system will then launch the application extension process, call `FileProviderExtension.init(domain:)` to instantiate the extension for that domain, and call methods on the instance. super.init() - self.socketClient?.start() + socketClient?.start() } - + func invalidate() { // TODO: cleanup any resources - Logger.fileProviderExtension.debug("Extension for domain \(self.domain.displayName, privacy: .public) is being torn down") + Logger.fileProviderExtension.debug( + "Extension for domain \(self.domain.displayName, privacy: .public) is being torn down") } // MARK: NSFileProviderReplicatedExtension protocol methods - - func item(for identifier: NSFileProviderItemIdentifier, request: NSFileProviderRequest, completionHandler: @escaping (NSFileProviderItem?, Error?) -> Void) -> Progress { + + func item( + for identifier: NSFileProviderItemIdentifier, request _: NSFileProviderRequest, + completionHandler: @escaping (NSFileProviderItem?, Error?) -> Void + ) -> Progress { // resolve the given identifier to a record in the model - Logger.fileProviderExtension.debug("Received item request for item with identifier: \(identifier.rawValue, privacy: .public)") + Logger.fileProviderExtension.debug( + "Received item request for item with identifier: \(identifier.rawValue, privacy: .public)" + ) if identifier == .rootContainer { - guard let ncAccount = ncAccount else { - Logger.fileProviderExtension.error("Not providing item: \(identifier.rawValue, privacy: .public) as account not set up yet") + guard let ncAccount else { + Logger.fileProviderExtension.error( + "Not providing item: \(identifier.rawValue, privacy: .public) as account not set up yet" + ) completionHandler(nil, NSFileProviderError(.notAuthenticated)) return Progress() } @@ -90,35 +104,52 @@ class FileProviderExtension: NSObject, NSFileProviderReplicatedExtension, NKComm metadata.serverUrl = ncAccount.serverUrl metadata.classFile = NKCommon.TypeClassFile.directory.rawValue - completionHandler(FileProviderItem(metadata: metadata, parentItemIdentifier: NSFileProviderItemIdentifier.rootContainer, ncKit: ncKit), nil) + completionHandler( + FileProviderItem( + metadata: metadata, + parentItemIdentifier: NSFileProviderItemIdentifier.rootContainer, + ncKit: ncKit), nil) return Progress() } let dbManager = NextcloudFilesDatabaseManager.shared - + guard let metadata = dbManager.itemMetadataFromFileProviderItemIdentifier(identifier), - let parentItemIdentifier = dbManager.parentItemIdentifierFromMetadata(metadata) else { + let parentItemIdentifier = dbManager.parentItemIdentifierFromMetadata(metadata) + else { completionHandler(nil, NSFileProviderError(.noSuchItem)) return Progress() } - completionHandler(FileProviderItem(metadata: metadata, parentItemIdentifier: parentItemIdentifier, ncKit: ncKit), nil) + completionHandler( + FileProviderItem( + metadata: metadata, parentItemIdentifier: parentItemIdentifier, ncKit: ncKit), nil) return Progress() } - - func fetchContents(for itemIdentifier: NSFileProviderItemIdentifier, version requestedVersion: NSFileProviderItemVersion?, request: NSFileProviderRequest, completionHandler: @escaping (URL?, NSFileProviderItem?, Error?) -> Void) -> Progress { - Logger.fileProviderExtension.debug("Received request to fetch contents of item with identifier: \(itemIdentifier.rawValue, privacy: .public)") + func fetchContents( + for itemIdentifier: NSFileProviderItemIdentifier, + version requestedVersion: NSFileProviderItemVersion?, request: NSFileProviderRequest, + completionHandler: @escaping (URL?, NSFileProviderItem?, Error?) -> Void + ) -> Progress { + Logger.fileProviderExtension.debug( + "Received request to fetch contents of item with identifier: \(itemIdentifier.rawValue, privacy: .public)" + ) guard requestedVersion == nil else { // TODO: Add proper support for file versioning - Logger.fileProviderExtension.error("Can't return contents for specific version as this is not supported.") - completionHandler(nil, nil, NSError(domain: NSCocoaErrorDomain, code: NSFeatureUnsupportedError, userInfo:[:])) + Logger.fileProviderExtension.error( + "Can't return contents for specific version as this is not supported.") + completionHandler( + nil, nil, + NSError(domain: NSCocoaErrorDomain, code: NSFeatureUnsupportedError, userInfo: [:])) return Progress() } guard ncAccount != nil else { - Logger.fileProviderExtension.error("Not fetching contents item: \(itemIdentifier.rawValue, privacy: .public) as account not set up yet") + Logger.fileProviderExtension.error( + "Not fetching contents item: \(itemIdentifier.rawValue, privacy: .public) as account not set up yet" + ) completionHandler(nil, nil, NSFileProviderError(.notAuthenticated)) return Progress() } @@ -126,46 +157,65 @@ class FileProviderExtension: NSObject, NSFileProviderReplicatedExtension, NKComm let dbManager = NextcloudFilesDatabaseManager.shared let ocId = itemIdentifier.rawValue guard let metadata = dbManager.itemMetadataFromOcId(ocId) else { - Logger.fileProviderExtension.error("Could not acquire metadata of item with identifier: \(itemIdentifier.rawValue, privacy: .public)") + Logger.fileProviderExtension.error( + "Could not acquire metadata of item with identifier: \(itemIdentifier.rawValue, privacy: .public)" + ) completionHandler(nil, nil, NSFileProviderError(.noSuchItem)) return Progress() } guard !metadata.isDocumentViewableOnly else { - Logger.fileProviderExtension.error("Could not get contents of item as is readonly: \(itemIdentifier.rawValue, privacy: .public) \(metadata.fileName, privacy: .public)") + Logger.fileProviderExtension.error( + "Could not get contents of item as is readonly: \(itemIdentifier.rawValue, privacy: .public) \(metadata.fileName, privacy: .public)" + ) completionHandler(nil, nil, NSFileProviderError(.cannotSynchronize)) return Progress() } let serverUrlFileName = metadata.serverUrl + "/" + metadata.fileName - Logger.fileProviderExtension.debug("Fetching file with name \(metadata.fileName, privacy: .public) at URL: \(serverUrlFileName, privacy: .public)") + Logger.fileProviderExtension.debug( + "Fetching file with name \(metadata.fileName, privacy: .public) at URL: \(serverUrlFileName, privacy: .public)" + ) let progress = Progress() // TODO: Handle folders nicely do { - let fileNameLocalPath = try localPathForNCFile(ocId: metadata.ocId, fileNameView: metadata.fileNameView, domain: self.domain) + let fileNameLocalPath = try localPathForNCFile( + ocId: metadata.ocId, fileNameView: metadata.fileNameView, domain: domain) - dbManager.setStatusForItemMetadata(metadata, status: NextcloudItemMetadataTable.Status.downloading) { updatedMetadata in + dbManager.setStatusForItemMetadata( + metadata, status: NextcloudItemMetadataTable.Status.downloading + ) { updatedMetadata in - guard let updatedMetadata = updatedMetadata else { - Logger.fileProviderExtension.error("Could not acquire updated metadata of item with identifier: \(itemIdentifier.rawValue, privacy: .public), unable to update item status to downloading") + guard let updatedMetadata else { + Logger.fileProviderExtension.error( + "Could not acquire updated metadata of item with identifier: \(itemIdentifier.rawValue, privacy: .public), unable to update item status to downloading" + ) completionHandler(nil, nil, NSFileProviderError(.noSuchItem)) return } - self.ncKit.download(serverUrlFileName: serverUrlFileName, - fileNameLocalPath: fileNameLocalPath.path, - requestHandler: { request in - progress.setHandlersFromAfRequest(request) - }, taskHandler: { task in - NSFileProviderManager(for: self.domain)?.register(task, forItemWithIdentifier: itemIdentifier, completionHandler: { _ in }) - }, progressHandler: { downloadProgress in - downloadProgress.copyCurrentStateToProgress(progress) - }) { _, etag, date, _, _, _, error in + self.ncKit.download( + serverUrlFileName: serverUrlFileName, + fileNameLocalPath: fileNameLocalPath.path, + requestHandler: { request in + progress.setHandlersFromAfRequest(request) + }, + taskHandler: { task in + NSFileProviderManager(for: self.domain)?.register( + task, forItemWithIdentifier: itemIdentifier, completionHandler: { _ in } + ) + }, + progressHandler: { downloadProgress in + downloadProgress.copyCurrentStateToProgress(progress) + } + ) { _, etag, date, _, _, _, error in if error == .success { - Logger.fileTransfer.debug("Acquired contents of item with identifier: \(itemIdentifier.rawValue, privacy: .public) and filename: \(updatedMetadata.fileName, privacy: .public)") + Logger.fileTransfer.debug( + "Acquired contents of item with identifier: \(itemIdentifier.rawValue, privacy: .public) and filename: \(updatedMetadata.fileName, privacy: .public)" + ) updatedMetadata.status = NextcloudItemMetadataTable.Status.normal.rawValue updatedMetadata.sessionError = "" @@ -175,18 +225,26 @@ class FileProviderExtension: NSObject, NSFileProviderReplicatedExtension, NKComm dbManager.addLocalFileMetadataFromItemMetadata(updatedMetadata) dbManager.addItemMetadata(updatedMetadata) - guard let parentItemIdentifier = dbManager.parentItemIdentifierFromMetadata(updatedMetadata) else { + guard + let parentItemIdentifier = dbManager.parentItemIdentifierFromMetadata( + updatedMetadata) + else { completionHandler(nil, nil, NSFileProviderError(.noSuchItem)) return } - let fpItem = FileProviderItem(metadata: updatedMetadata, parentItemIdentifier: parentItemIdentifier, ncKit: self.ncKit) + let fpItem = FileProviderItem( + metadata: updatedMetadata, parentItemIdentifier: parentItemIdentifier, + ncKit: self.ncKit) completionHandler(fileNameLocalPath, fpItem, nil) } else { - Logger.fileTransfer.error("Could not acquire contents of item with identifier: \(itemIdentifier.rawValue, privacy: .public) and fileName: \(updatedMetadata.fileName, privacy: .public)") + Logger.fileTransfer.error( + "Could not acquire contents of item with identifier: \(itemIdentifier.rawValue, privacy: .public) and fileName: \(updatedMetadata.fileName, privacy: .public)" + ) - updatedMetadata.status = NextcloudItemMetadataTable.Status.downloadError.rawValue + updatedMetadata.status = + NextcloudItemMetadataTable.Status.downloadError.rawValue updatedMetadata.sessionError = error.errorDescription dbManager.addItemMetadata(updatedMetadata) @@ -195,40 +253,60 @@ class FileProviderExtension: NSObject, NSFileProviderReplicatedExtension, NKComm } } } - } catch let error { - Logger.fileProviderExtension.error("Could not find local path for file \(metadata.fileName, privacy: .public), received error: \(error.localizedDescription, privacy: .public)") + } catch { + Logger.fileProviderExtension.error( + "Could not find local path for file \(metadata.fileName, privacy: .public), received error: \(error.localizedDescription, privacy: .public)" + ) completionHandler(nil, nil, NSFileProviderError(.cannotSynchronize)) } return progress } - - func createItem(basedOn itemTemplate: NSFileProviderItem, fields: NSFileProviderItemFields, contents url: URL?, options: NSFileProviderCreateItemOptions = [], request: NSFileProviderRequest, completionHandler: @escaping (NSFileProviderItem?, NSFileProviderItemFields, Bool, Error?) -> Void) -> Progress { + + func createItem( + basedOn itemTemplate: NSFileProviderItem, fields _: NSFileProviderItemFields, + contents url: URL?, options: NSFileProviderCreateItemOptions = [], + request: NSFileProviderRequest, + completionHandler: @escaping (NSFileProviderItem?, NSFileProviderItemFields, Bool, Error?) + -> + Void + ) -> Progress { // TODO: a new item was created on disk, process the item's creation - Logger.fileProviderExtension.debug("Received create item request for item with identifier: \(itemTemplate.itemIdentifier.rawValue, privacy: .public) and filename: \(itemTemplate.filename, privacy: .public)") + Logger.fileProviderExtension.debug( + "Received create item request for item with identifier: \(itemTemplate.itemIdentifier.rawValue, privacy: .public) and filename: \(itemTemplate.filename, privacy: .public)" + ) guard itemTemplate.contentType != .symbolicLink else { Logger.fileProviderExtension.error("Cannot create item, symbolic links not supported.") - completionHandler(itemTemplate, NSFileProviderItemFields(), false, NSError(domain: NSCocoaErrorDomain, code: NSFeatureUnsupportedError, userInfo:[:])) + completionHandler( + itemTemplate, NSFileProviderItemFields(), false, + NSError(domain: NSCocoaErrorDomain, code: NSFeatureUnsupportedError, userInfo: [:])) return Progress() } - guard let ncAccount = ncAccount else { - Logger.fileProviderExtension.error("Not creating item: \(itemTemplate.itemIdentifier.rawValue, privacy: .public) as account not set up yet") - completionHandler(itemTemplate, NSFileProviderItemFields(), false, NSFileProviderError(.notAuthenticated)) + guard let ncAccount else { + Logger.fileProviderExtension.error( + "Not creating item: \(itemTemplate.itemIdentifier.rawValue, privacy: .public) as account not set up yet" + ) + completionHandler( + itemTemplate, NSFileProviderItemFields(), false, + NSFileProviderError(.notAuthenticated)) return Progress() } let dbManager = NextcloudFilesDatabaseManager.shared let parentItemIdentifier = itemTemplate.parentItemIdentifier - let itemTemplateIsFolder = itemTemplate.contentType == .folder || - itemTemplate.contentType == .directory + let itemTemplateIsFolder = + itemTemplate.contentType == .folder || itemTemplate.contentType == .directory if options.contains(.mayAlreadyExist) { // TODO: This needs to be properly handled with a check in the db - Logger.fileProviderExtension.info("Not creating item: \(itemTemplate.itemIdentifier.rawValue, privacy: .public) as it may already exist") - completionHandler(itemTemplate, NSFileProviderItemFields(), false, NSFileProviderError(.noSuchItem)) + Logger.fileProviderExtension.info( + "Not creating item: \(itemTemplate.itemIdentifier.rawValue, privacy: .public) as it may already exist" + ) + completionHandler( + itemTemplate, NSFileProviderItemFields(), false, NSFileProviderError(.noSuchItem)) return Progress() } @@ -237,9 +315,16 @@ class FileProviderExtension: NSObject, NSFileProviderReplicatedExtension, NKComm if parentItemIdentifier == .rootContainer { parentItemServerUrl = ncAccount.davFilesUrl } else { - guard let parentItemMetadata = dbManager.directoryMetadata(ocId: parentItemIdentifier.rawValue) else { - Logger.fileProviderExtension.error("Not creating item: \(itemTemplate.itemIdentifier.rawValue, privacy: .public), could not find metadata for parentItemIdentifier \(parentItemIdentifier.rawValue, privacy: .public)") - completionHandler(itemTemplate, NSFileProviderItemFields(), false, NSFileProviderError(.noSuchItem)) + guard + let parentItemMetadata = dbManager.directoryMetadata( + ocId: parentItemIdentifier.rawValue) + else { + Logger.fileProviderExtension.error( + "Not creating item: \(itemTemplate.itemIdentifier.rawValue, privacy: .public), could not find metadata for parentItemIdentifier \(parentItemIdentifier.rawValue, privacy: .public)" + ) + completionHandler( + itemTemplate, NSFileProviderItemFields(), false, + NSFileProviderError(.noSuchItem)) return Progress() } @@ -249,29 +334,43 @@ class FileProviderExtension: NSObject, NSFileProviderReplicatedExtension, NKComm let fileNameLocalPath = url?.path ?? "" let newServerUrlFileName = parentItemServerUrl + "/" + itemTemplate.filename - Logger.fileProviderExtension.debug("About to upload item with identifier: \(itemTemplate.itemIdentifier.rawValue, privacy: .public) of type: \(itemTemplate.contentType?.identifier ?? "UNKNOWN") (is folder: \(itemTemplateIsFolder ? "yes" : "no") and filename: \(itemTemplate.filename) to server url: \(newServerUrlFileName, privacy: .public) with contents located at: \(fileNameLocalPath, privacy: .public)") + Logger.fileProviderExtension.debug( + "About to upload item with identifier: \(itemTemplate.itemIdentifier.rawValue, privacy: .public) of type: \(itemTemplate.contentType?.identifier ?? "UNKNOWN") (is folder: \(itemTemplateIsFolder ? "yes" : "no") and filename: \(itemTemplate.filename) to server url: \(newServerUrlFileName, privacy: .public) with contents located at: \(fileNameLocalPath, privacy: .public)" + ) if itemTemplateIsFolder { - self.ncKit.createFolder(serverUrlFileName: newServerUrlFileName) { account, ocId, _, error in + ncKit.createFolder(serverUrlFileName: newServerUrlFileName) { account, _, _, error in guard error == .success else { - Logger.fileTransfer.error("Could not create new folder with name: \(itemTemplate.filename, privacy: .public), received error: \(error.errorDescription, privacy: .public)") + Logger.fileTransfer.error( + "Could not create new folder with name: \(itemTemplate.filename, privacy: .public), received error: \(error.errorDescription, privacy: .public)" + ) completionHandler(itemTemplate, [], false, error.fileProviderError) return } // Read contents after creation - self.ncKit.readFileOrFolder(serverUrlFileName: newServerUrlFileName, depth: "0", showHiddenFiles: true) { account, files, _, error in + self.ncKit.readFileOrFolder( + serverUrlFileName: newServerUrlFileName, depth: "0", showHiddenFiles: true + ) { account, files, _, error in guard error == .success else { - Logger.fileTransfer.error("Could not read new folder with name: \(itemTemplate.filename, privacy: .public), received error: \(error.errorDescription, privacy: .public)") + Logger.fileTransfer.error( + "Could not read new folder with name: \(itemTemplate.filename, privacy: .public), received error: \(error.errorDescription, privacy: .public)" + ) return } DispatchQueue.global().async { - NextcloudItemMetadataTable.metadatasFromDirectoryReadNKFiles(files, account: account) { directoryMetadata, childDirectoriesMetadata, metadatas in + NextcloudItemMetadataTable.metadatasFromDirectoryReadNKFiles( + files, account: account + ) { + directoryMetadata, _, _ in dbManager.addItemMetadata(directoryMetadata) - let fpItem = FileProviderItem(metadata: directoryMetadata, parentItemIdentifier: parentItemIdentifier, ncKit: self.ncKit) + let fpItem = FileProviderItem( + metadata: directoryMetadata, + parentItemIdentifier: parentItemIdentifier, + ncKit: self.ncKit) completionHandler(fpItem, [], true, nil) } @@ -284,25 +383,37 @@ class FileProviderExtension: NSObject, NSFileProviderReplicatedExtension, NKComm let progress = Progress() - self.ncKit.upload(serverUrlFileName: newServerUrlFileName, - fileNameLocalPath: fileNameLocalPath, - requestHandler: { request in - progress.setHandlersFromAfRequest(request) - }, taskHandler: { task in - NSFileProviderManager(for: self.domain)?.register(task, forItemWithIdentifier: itemTemplate.itemIdentifier, completionHandler: { _ in }) - }, progressHandler: { uploadProgress in - uploadProgress.copyCurrentStateToProgress(progress) - }) { account, ocId, etag, date, size, _, _, error in - guard error == .success, let ocId = ocId else { - Logger.fileTransfer.error("Could not upload item with filename: \(itemTemplate.filename, privacy: .public), received error: \(error.errorDescription, privacy: .public)") + ncKit.upload( + serverUrlFileName: newServerUrlFileName, + fileNameLocalPath: fileNameLocalPath, + requestHandler: { request in + progress.setHandlersFromAfRequest(request) + }, + taskHandler: { task in + NSFileProviderManager(for: self.domain)?.register( + task, forItemWithIdentifier: itemTemplate.itemIdentifier, + completionHandler: { _ in }) + }, + progressHandler: { uploadProgress in + uploadProgress.copyCurrentStateToProgress(progress) + } + ) { account, ocId, etag, date, size, _, _, error in + guard error == .success, let ocId else { + Logger.fileTransfer.error( + "Could not upload item with filename: \(itemTemplate.filename, privacy: .public), received error: \(error.errorDescription, privacy: .public)" + ) completionHandler(itemTemplate, [], false, error.fileProviderError) return } - Logger.fileTransfer.info("Successfully uploaded item with identifier: \(ocId, privacy: .public) and filename: \(itemTemplate.filename, privacy: .public)") + Logger.fileTransfer.info( + "Successfully uploaded item with identifier: \(ocId, privacy: .public) and filename: \(itemTemplate.filename, privacy: .public)" + ) if size != itemTemplate.documentSize as? Int64 { - Logger.fileTransfer.warning("Created item upload reported as successful, but there are differences between the received file size (\(size, privacy: .public)) and the original file size (\(itemTemplate.documentSize??.int64Value ?? 0))") + Logger.fileTransfer.warning( + "Created item upload reported as successful, but there are differences between the received file size (\(size, privacy: .public)) and the original file size (\(itemTemplate.documentSize??.int64Value ?? 0))" + ) } let newMetadata = NextcloudItemMetadataTable() @@ -324,34 +435,48 @@ class FileProviderExtension: NSObject, NSFileProviderReplicatedExtension, NKComm dbManager.addLocalFileMetadataFromItemMetadata(newMetadata) dbManager.addItemMetadata(newMetadata) - let fpItem = FileProviderItem(metadata: newMetadata, parentItemIdentifier: parentItemIdentifier, ncKit: self.ncKit) + let fpItem = FileProviderItem( + metadata: newMetadata, parentItemIdentifier: parentItemIdentifier, ncKit: self.ncKit + ) completionHandler(fpItem, [], false, nil) } return progress } - - func modifyItem(_ item: NSFileProviderItem, baseVersion version: NSFileProviderItemVersion, changedFields: NSFileProviderItemFields, contents newContents: URL?, options: NSFileProviderModifyItemOptions = [], request: NSFileProviderRequest, completionHandler: @escaping (NSFileProviderItem?, NSFileProviderItemFields, Bool, Error?) -> Void) -> Progress { + + func modifyItem( + _ item: NSFileProviderItem, baseVersion _: NSFileProviderItemVersion, + changedFields: NSFileProviderItemFields, contents newContents: URL?, + options: NSFileProviderModifyItemOptions = [], request: NSFileProviderRequest, + completionHandler: @escaping (NSFileProviderItem?, NSFileProviderItemFields, Bool, Error?) + -> + Void + ) -> Progress { // An item was modified on disk, process the item's modification // TODO: Handle finder things like tags, other possible item changed fields - Logger.fileProviderExtension.debug("Received modify item request for item with identifier: \(item.itemIdentifier.rawValue, privacy: .public) and filename: \(item.filename, privacy: .public)") + Logger.fileProviderExtension.debug( + "Received modify item request for item with identifier: \(item.itemIdentifier.rawValue, privacy: .public) and filename: \(item.filename, privacy: .public)" + ) - guard let ncAccount = ncAccount else { - Logger.fileProviderExtension.error("Not modifying item: \(item.itemIdentifier.rawValue, privacy: .public) as account not set up yet") + guard let ncAccount else { + Logger.fileProviderExtension.error( + "Not modifying item: \(item.itemIdentifier.rawValue, privacy: .public) as account not set up yet" + ) completionHandler(item, [], false, NSFileProviderError(.notAuthenticated)) return Progress() } let dbManager = NextcloudFilesDatabaseManager.shared let parentItemIdentifier = item.parentItemIdentifier - let itemTemplateIsFolder = item.contentType == .folder || - item.contentType == .directory + let itemTemplateIsFolder = item.contentType == .folder || item.contentType == .directory if options.contains(.mayAlreadyExist) { // TODO: This needs to be properly handled with a check in the db - Logger.fileProviderExtension.warning("Modification for item: \(item.itemIdentifier.rawValue, privacy: .public) may already exist") + Logger.fileProviderExtension.warning( + "Modification for item: \(item.itemIdentifier.rawValue, privacy: .public) may already exist" + ) } var parentItemServerUrl: String @@ -359,8 +484,13 @@ class FileProviderExtension: NSObject, NSFileProviderReplicatedExtension, NKComm if parentItemIdentifier == .rootContainer { parentItemServerUrl = ncAccount.davFilesUrl } else { - guard let parentItemMetadata = dbManager.directoryMetadata(ocId: parentItemIdentifier.rawValue) else { - Logger.fileProviderExtension.error("Not modifying item: \(item.itemIdentifier.rawValue, privacy: .public), could not find metadata for parentItemIdentifier \(parentItemIdentifier.rawValue, privacy: .public)") + guard + let parentItemMetadata = dbManager.directoryMetadata( + ocId: parentItemIdentifier.rawValue) + else { + Logger.fileProviderExtension.error( + "Not modifying item: \(item.itemIdentifier.rawValue, privacy: .public), could not find metadata for parentItemIdentifier \(parentItemIdentifier.rawValue, privacy: .public)" + ) completionHandler(item, [], false, NSFileProviderError(.noSuchItem)) return Progress() } @@ -371,7 +501,9 @@ class FileProviderExtension: NSObject, NSFileProviderReplicatedExtension, NKComm let fileNameLocalPath = newContents?.path ?? "" let newServerUrlFileName = parentItemServerUrl + "/" + item.filename - Logger.fileProviderExtension.debug("About to upload modified item with identifier: \(item.itemIdentifier.rawValue, privacy: .public) of type: \(item.contentType?.identifier ?? "UNKNOWN") (is folder: \(itemTemplateIsFolder ? "yes" : "no") and filename: \(item.filename, privacy: .public) to server url: \(newServerUrlFileName, privacy: .public) with contents located at: \(fileNameLocalPath, privacy: .public)") + Logger.fileProviderExtension.debug( + "About to upload modified item with identifier: \(item.itemIdentifier.rawValue, privacy: .public) of type: \(item.contentType?.identifier ?? "UNKNOWN") (is folder: \(itemTemplateIsFolder ? "yes" : "no") and filename: \(item.filename, privacy: .public) to server url: \(newServerUrlFileName, privacy: .public) with contents located at: \(fileNameLocalPath, privacy: .public)" + ) var modifiedItem = item @@ -384,10 +516,14 @@ class FileProviderExtension: NSObject, NSFileProviderReplicatedExtension, NKComm if changedFields.contains(.filename) || changedFields.contains(.parentItemIdentifier) { dispatchQueue.async { let ocId = item.itemIdentifier.rawValue - Logger.fileProviderExtension.debug("Changed fields for item \(ocId, privacy: .public) with filename \(item.filename, privacy: .public) includes filename or parentitemidentifier...") + Logger.fileProviderExtension.debug( + "Changed fields for item \(ocId, privacy: .public) with filename \(item.filename, privacy: .public) includes filename or parentitemidentifier..." + ) guard let metadata = dbManager.itemMetadataFromOcId(ocId) else { - Logger.fileProviderExtension.error("Could not acquire metadata of item with identifier: \(item.itemIdentifier.rawValue, privacy: .public)") + Logger.fileProviderExtension.error( + "Could not acquire metadata of item with identifier: \(item.itemIdentifier.rawValue, privacy: .public)" + ) completionHandler(item, [], false, NSFileProviderError(.noSuchItem)) return } @@ -395,14 +531,18 @@ class FileProviderExtension: NSObject, NSFileProviderReplicatedExtension, NKComm var renameError: NSFileProviderError? let oldServerUrlFileName = metadata.serverUrl + "/" + metadata.fileName - let moveFileOrFolderDispatchGroup = DispatchGroup() // Make this block wait until done + let moveFileOrFolderDispatchGroup = DispatchGroup() // Make this block wait until done moveFileOrFolderDispatchGroup.enter() - self.ncKit.moveFileOrFolder(serverUrlFileNameSource: oldServerUrlFileName, - serverUrlFileNameDestination: newServerUrlFileName, - overwrite: false) { account, error in + self.ncKit.moveFileOrFolder( + serverUrlFileNameSource: oldServerUrlFileName, + serverUrlFileNameDestination: newServerUrlFileName, + overwrite: false + ) { _, error in guard error == .success else { - Logger.fileTransfer.error("Could not move file or folder: \(oldServerUrlFileName, privacy: .public) to \(newServerUrlFileName, privacy: .public), received error: \(error.errorDescription, privacy: .public)") + Logger.fileTransfer.error( + "Could not move file or folder: \(oldServerUrlFileName, privacy: .public) to \(newServerUrlFileName, privacy: .public), received error: \(error.errorDescription, privacy: .public)" + ) renameError = error.fileProviderError moveFileOrFolderDispatchGroup.leave() return @@ -411,37 +551,49 @@ class FileProviderExtension: NSObject, NSFileProviderReplicatedExtension, NKComm // Remember that a folder metadata's serverUrl is its direct server URL, while for // an item metadata the server URL is the parent folder's URL if itemTemplateIsFolder { - _ = dbManager.renameDirectoryAndPropagateToChildren(ocId: ocId, newServerUrl: newServerUrlFileName, newFileName: item.filename) + _ = dbManager.renameDirectoryAndPropagateToChildren( + ocId: ocId, newServerUrl: newServerUrlFileName, + newFileName: item.filename) self.signalEnumerator { error in if error != nil { - Logger.fileTransfer.error("Error notifying change in moved directory: \(error)") + Logger.fileTransfer.error( + "Error notifying change in moved directory: \(error)") } } } else { - dbManager.renameItemMetadata(ocId: ocId, newServerUrl: parentItemServerUrl, newFileName: item.filename) + dbManager.renameItemMetadata( + ocId: ocId, newServerUrl: parentItemServerUrl, + newFileName: item.filename) } guard let newMetadata = dbManager.itemMetadataFromOcId(ocId) else { - Logger.fileTransfer.error("Could not acquire metadata of item with identifier: \(ocId, privacy: .public), cannot correctly inform of modification") + Logger.fileTransfer.error( + "Could not acquire metadata of item with identifier: \(ocId, privacy: .public), cannot correctly inform of modification" + ) renameError = NSFileProviderError(.noSuchItem) moveFileOrFolderDispatchGroup.leave() return } - modifiedItem = FileProviderItem(metadata: newMetadata, parentItemIdentifier: parentItemIdentifier, ncKit: self.ncKit) + modifiedItem = FileProviderItem( + metadata: newMetadata, parentItemIdentifier: parentItemIdentifier, + ncKit: self.ncKit) moveFileOrFolderDispatchGroup.leave() } moveFileOrFolderDispatchGroup.wait() guard renameError == nil else { - Logger.fileTransfer.error("Stopping rename of item with ocId \(ocId, privacy: .public) due to error: \(renameError!.localizedDescription, privacy: .public)") + Logger.fileTransfer.error( + "Stopping rename of item with ocId \(ocId, privacy: .public) due to error: \(renameError!.localizedDescription, privacy: .public)" + ) completionHandler(modifiedItem, [], false, renameError) return } guard !itemTemplateIsFolder else { - Logger.fileTransfer.debug("Only handling renaming for folders. ocId: \(ocId, privacy: .public)") + Logger.fileTransfer.debug( + "Only handling renaming for folders. ocId: \(ocId, privacy: .public)") completionHandler(modifiedItem, [], false, nil) return } @@ -454,7 +606,9 @@ class FileProviderExtension: NSObject, NSFileProviderReplicatedExtension, NKComm } guard !itemTemplateIsFolder else { - Logger.fileTransfer.debug("System requested modification for folder with ocID \(item.itemIdentifier.rawValue, privacy: .public) (\(newServerUrlFileName, privacy: .public)) of something other than folder name.") + Logger.fileTransfer.debug( + "System requested modification for folder with ocID \(item.itemIdentifier.rawValue, privacy: .public) (\(newServerUrlFileName, privacy: .public)) of something other than folder name." + ) completionHandler(modifiedItem, [], false, nil) return Progress() } @@ -463,41 +617,62 @@ class FileProviderExtension: NSObject, NSFileProviderReplicatedExtension, NKComm if changedFields.contains(.contents) { dispatchQueue.async { - Logger.fileProviderExtension.debug("Item modification for \(item.itemIdentifier.rawValue, privacy: .public) \(item.filename, privacy: .public) includes contents") + Logger.fileProviderExtension.debug( + "Item modification for \(item.itemIdentifier.rawValue, privacy: .public) \(item.filename, privacy: .public) includes contents" + ) guard newContents != nil else { - Logger.fileProviderExtension.warning("WARNING. Could not upload modified contents as was provided nil contents url. ocId: \(item.itemIdentifier.rawValue, privacy: .public)") + Logger.fileProviderExtension.warning( + "WARNING. Could not upload modified contents as was provided nil contents url. ocId: \(item.itemIdentifier.rawValue, privacy: .public)" + ) completionHandler(modifiedItem, [], false, NSFileProviderError(.noSuchItem)) return } let ocId = item.itemIdentifier.rawValue guard let metadata = dbManager.itemMetadataFromOcId(ocId) else { - Logger.fileProviderExtension.error("Could not acquire metadata of item with identifier: \(ocId, privacy: .public)") - completionHandler(item, NSFileProviderItemFields(), false, NSFileProviderError(.noSuchItem)) + Logger.fileProviderExtension.error( + "Could not acquire metadata of item with identifier: \(ocId, privacy: .public)" + ) + completionHandler( + item, NSFileProviderItemFields(), false, NSFileProviderError(.noSuchItem)) return } - dbManager.setStatusForItemMetadata(metadata, status: NextcloudItemMetadataTable.Status.uploading) { updatedMetadata in + dbManager.setStatusForItemMetadata( + metadata, status: NextcloudItemMetadataTable.Status.uploading + ) { updatedMetadata in if updatedMetadata == nil { - Logger.fileProviderExtension.warning("Could not acquire updated metadata of item with identifier: \(ocId, privacy: .public), unable to update item status to uploading") + Logger.fileProviderExtension.warning( + "Could not acquire updated metadata of item with identifier: \(ocId, privacy: .public), unable to update item status to uploading" + ) } - self.ncKit.upload(serverUrlFileName: newServerUrlFileName, - fileNameLocalPath: fileNameLocalPath, - requestHandler: { request in - progress.setHandlersFromAfRequest(request) - }, taskHandler: { task in - NSFileProviderManager(for: self.domain)?.register(task, forItemWithIdentifier: item.itemIdentifier, completionHandler: { _ in }) - }, progressHandler: { uploadProgress in - uploadProgress.copyCurrentStateToProgress(progress) - }) { account, ocId, etag, date, size, _, _, error in - if error == .success, let ocId = ocId { - Logger.fileProviderExtension.info("Successfully uploaded item with identifier: \(ocId, privacy: .public) and filename: \(item.filename, privacy: .public)") + self.ncKit.upload( + serverUrlFileName: newServerUrlFileName, + fileNameLocalPath: fileNameLocalPath, + requestHandler: { request in + progress.setHandlersFromAfRequest(request) + }, + taskHandler: { task in + NSFileProviderManager(for: self.domain)?.register( + task, forItemWithIdentifier: item.itemIdentifier, + completionHandler: { _ in }) + }, + progressHandler: { uploadProgress in + uploadProgress.copyCurrentStateToProgress(progress) + } + ) { account, ocId, etag, date, size, _, _, error in + if error == .success, let ocId { + Logger.fileProviderExtension.info( + "Successfully uploaded item with identifier: \(ocId, privacy: .public) and filename: \(item.filename, privacy: .public)" + ) if size != item.documentSize as? Int64 { - Logger.fileTransfer.warning("Created item upload reported as successful, but there are differences between the received file size (\(size, privacy: .public)) and the original file size (\(item.documentSize??.int64Value ?? 0))") + Logger.fileTransfer.warning( + "Created item upload reported as successful, but there are differences between the received file size (\(size, privacy: .public)) and the original file size (\(item.documentSize??.int64Value ?? 0))" + ) } let newMetadata = NextcloudItemMetadataTable() @@ -519,10 +694,15 @@ class FileProviderExtension: NSObject, NSFileProviderReplicatedExtension, NKComm dbManager.addLocalFileMetadataFromItemMetadata(newMetadata) dbManager.addItemMetadata(newMetadata) - modifiedItem = FileProviderItem(metadata: newMetadata, parentItemIdentifier: parentItemIdentifier, ncKit: self.ncKit) + modifiedItem = FileProviderItem( + metadata: newMetadata, parentItemIdentifier: parentItemIdentifier, + ncKit: self.ncKit + ) completionHandler(modifiedItem, [], false, nil) } else { - Logger.fileTransfer.error("Could not upload item \(item.itemIdentifier.rawValue, privacy: .public) with filename: \(item.filename, privacy: .public), received error: \(error.errorDescription, privacy: .public)") + Logger.fileTransfer.error( + "Could not upload item \(item.itemIdentifier.rawValue, privacy: .public) with filename: \(item.filename, privacy: .public), received error: \(error.errorDescription, privacy: .public)" + ) metadata.status = NextcloudItemMetadataTable.Status.uploadError.rawValue metadata.sessionError = error.errorDescription @@ -536,19 +716,28 @@ class FileProviderExtension: NSObject, NSFileProviderReplicatedExtension, NKComm } } } else { - Logger.fileProviderExtension.debug("Nothing more to do with \(item.itemIdentifier.rawValue, privacy: .public) \(item.filename, privacy: .public), modifications complete") + Logger.fileProviderExtension.debug( + "Nothing more to do with \(item.itemIdentifier.rawValue, privacy: .public) \(item.filename, privacy: .public), modifications complete" + ) completionHandler(modifiedItem, [], false, nil) } return progress } - - func deleteItem(identifier: NSFileProviderItemIdentifier, baseVersion version: NSFileProviderItemVersion, options: NSFileProviderDeleteItemOptions = [], request: NSFileProviderRequest, completionHandler: @escaping (Error?) -> Void) -> Progress { - Logger.fileProviderExtension.debug("Received delete item request for item with identifier: \(identifier.rawValue, privacy: .public)") + func deleteItem( + identifier: NSFileProviderItemIdentifier, baseVersion _: NSFileProviderItemVersion, + options _: NSFileProviderDeleteItemOptions = [], request _: NSFileProviderRequest, + completionHandler: @escaping (Error?) -> Void + ) -> Progress { + Logger.fileProviderExtension.debug( + "Received delete item request for item with identifier: \(identifier.rawValue, privacy: .public)" + ) guard ncAccount != nil else { - Logger.fileProviderExtension.error("Not deleting item: \(identifier.rawValue, privacy: .public) as account not set up yet") + Logger.fileProviderExtension.error( + "Not deleting item: \(identifier.rawValue, privacy: .public) as account not set up yet" + ) completionHandler(NSFileProviderError(.notAuthenticated)) return Progress() } @@ -566,14 +755,18 @@ class FileProviderExtension: NSObject, NSFileProviderReplicatedExtension, NKComm return Progress() } - self.ncKit.deleteFileOrFolder(serverUrlFileName: serverFileNameUrl) { account, error in + ncKit.deleteFileOrFolder(serverUrlFileName: serverFileNameUrl) { _, error in guard error == .success else { - Logger.fileTransfer.error("Could not delete item with ocId \(identifier.rawValue, privacy: .public) at \(serverFileNameUrl, privacy: .public), received error: \(error.errorDescription, privacy: .public)") + Logger.fileTransfer.error( + "Could not delete item with ocId \(identifier.rawValue, privacy: .public) at \(serverFileNameUrl, privacy: .public), received error: \(error.errorDescription, privacy: .public)" + ) completionHandler(error.fileProviderError) return } - Logger.fileTransfer.info("Successfully deleted item with identifier: \(identifier.rawValue, privacy: .public) at: \(serverFileNameUrl, privacy: .public)") + Logger.fileTransfer.info( + "Successfully deleted item with identifier: \(identifier.rawValue, privacy: .public) at: \(serverFileNameUrl, privacy: .public)" + ) if itemMetadata.directory { _ = dbManager.deleteDirectoryAndSubdirectoriesMetadata(ocId: ocId) @@ -589,32 +782,41 @@ class FileProviderExtension: NSObject, NSFileProviderReplicatedExtension, NKComm return Progress() } - - func enumerator(for containerItemIdentifier: NSFileProviderItemIdentifier, request: NSFileProviderRequest) throws -> NSFileProviderEnumerator { - guard let ncAccount = ncAccount else { - Logger.fileProviderExtension.error("Not providing enumerator for container with identifier \(containerItemIdentifier.rawValue, privacy: .public) yet as account not set up") + func enumerator( + for containerItemIdentifier: NSFileProviderItemIdentifier, request _: NSFileProviderRequest + ) throws -> NSFileProviderEnumerator { + guard let ncAccount else { + Logger.fileProviderExtension.error( + "Not providing enumerator for container with identifier \(containerItemIdentifier.rawValue, privacy: .public) yet as account not set up" + ) throw NSFileProviderError(.notAuthenticated) } - return FileProviderEnumerator(enumeratedItemIdentifier: containerItemIdentifier, ncAccount: ncAccount, ncKit: ncKit) + return FileProviderEnumerator( + enumeratedItemIdentifier: containerItemIdentifier, ncAccount: ncAccount, ncKit: ncKit) } func materializedItemsDidChange(completionHandler: @escaping () -> Void) { - guard let ncAccount = self.ncAccount else { - Logger.fileProviderExtension.error("Not purging stale local file metadatas, account not set up") + guard let ncAccount else { + Logger.fileProviderExtension.error( + "Not purging stale local file metadatas, account not set up") completionHandler() return } guard let fpManager = NSFileProviderManager(for: domain) else { - Logger.fileProviderExtension.error("Could not get file provider manager for domain: \(self.domain.displayName, privacy: .public)") + Logger.fileProviderExtension.error( + "Could not get file provider manager for domain: \(self.domain.displayName, privacy: .public)" + ) completionHandler() return } let materialisedEnumerator = fpManager.enumeratorForMaterializedItems() - let materialisedObserver = FileProviderMaterialisedEnumerationObserver(ncKitAccount: ncAccount.ncKitAccount) { _ in + let materialisedObserver = FileProviderMaterialisedEnumerationObserver( + ncKitAccount: ncAccount.ncKitAccount + ) { _ in completionHandler() } let startingPage = NSFileProviderPage(NSFileProviderPage.initialPageSortedByName as Data) @@ -622,9 +824,11 @@ class FileProviderExtension: NSObject, NSFileProviderReplicatedExtension, NKComm materialisedEnumerator.enumerateItems(for: materialisedObserver, startingAt: startingPage) } - func signalEnumerator(completionHandler: @escaping(_ error: Error?) -> Void) { - guard let fpManager = NSFileProviderManager(for: self.domain) else { - Logger.fileProviderExtension.error("Could not get file provider manager for domain, could not signal enumerator. This might lead to future conflicts.") + func signalEnumerator(completionHandler: @escaping (_ error: Error?) -> Void) { + guard let fpManager = NSFileProviderManager(for: domain) else { + Logger.fileProviderExtension.error( + "Could not get file provider manager for domain, could not signal enumerator. This might lead to future conflicts." + ) return } diff --git a/shell_integration/MacOSX/NextcloudIntegration/FileProviderExt/FileProviderItem.swift b/shell_integration/MacOSX/NextcloudIntegration/FileProviderExt/FileProviderItem.swift index 9a3c3e722..b571c38d4 100644 --- a/shell_integration/MacOSX/NextcloudIntegration/FileProviderExt/FileProviderItem.swift +++ b/shell_integration/MacOSX/NextcloudIntegration/FileProviderExt/FileProviderItem.swift @@ -13,11 +13,10 @@ */ import FileProvider -import UniformTypeIdentifiers import NextcloudKit +import UniformTypeIdentifiers class FileProviderItem: NSObject, NSFileProviderItem { - enum FileProviderItemTransferError: Error { case downloadError case uploadError @@ -26,71 +25,78 @@ class FileProviderItem: NSObject, NSFileProviderItem { let metadata: NextcloudItemMetadataTable let parentItemIdentifier: NSFileProviderItemIdentifier let ncKit: NextcloudKit - + var itemIdentifier: NSFileProviderItemIdentifier { - return NSFileProviderItemIdentifier(metadata.ocId) + NSFileProviderItemIdentifier(metadata.ocId) } - + var capabilities: NSFileProviderItemCapabilities { guard !metadata.directory else { - return [ .allowsAddingSubItems, - .allowsContentEnumerating, - .allowsReading, - .allowsDeleting, - .allowsRenaming ] + return [ + .allowsAddingSubItems, + .allowsContentEnumerating, + .allowsReading, + .allowsDeleting, + .allowsRenaming, + ] } guard !metadata.lock else { - return [ .allowsReading ] + return [.allowsReading] } - return [ .allowsWriting, - .allowsReading, - .allowsDeleting, - .allowsRenaming, - .allowsReparenting ] + return [ + .allowsWriting, + .allowsReading, + .allowsDeleting, + .allowsRenaming, + .allowsReparenting, + ] } - + var itemVersion: NSFileProviderItemVersion { - NSFileProviderItemVersion(contentVersion: metadata.etag.data(using: .utf8)!, - metadataVersion: metadata.etag.data(using: .utf8)!) + NSFileProviderItemVersion( + contentVersion: metadata.etag.data(using: .utf8)!, + metadataVersion: metadata.etag.data(using: .utf8)!) } - + var filename: String { - return metadata.fileNameView + metadata.fileNameView } - + var contentType: UTType { - if self.itemIdentifier == .rootContainer || metadata.directory { + if itemIdentifier == .rootContainer || metadata.directory { return .folder } - let internalType = ncKit.nkCommonInstance.getInternalType(fileName: metadata.fileNameView, - mimeType: "", - directory: metadata.directory) + let internalType = ncKit.nkCommonInstance.getInternalType( + fileName: metadata.fileNameView, + mimeType: "", + directory: metadata.directory) return UTType(filenameExtension: internalType.ext) ?? .content } var documentSize: NSNumber? { - return NSNumber(value: metadata.size) + NSNumber(value: metadata.size) } var creationDate: Date? { - return metadata.creationDate as Date + metadata.creationDate as Date } var lastUsedDate: Date? { - return metadata.date as Date + metadata.date as Date } var contentModificationDate: Date? { - return metadata.date as Date + metadata.date as Date } var isDownloaded: Bool { - return metadata.directory || NextcloudFilesDatabaseManager.shared.localFileMetadataFromOcId(metadata.ocId) != nil + metadata.directory + || NextcloudFilesDatabaseManager.shared.localFileMetadataFromOcId(metadata.ocId) != nil } var isDownloading: Bool { - return metadata.status == NextcloudItemMetadataTable.Status.downloading.rawValue + metadata.status == NextcloudItemMetadataTable.Status.downloading.rawValue } var downloadingError: Error? { @@ -101,30 +107,36 @@ class FileProviderItem: NSObject, NSFileProviderItem { } var isUploaded: Bool { - return NextcloudFilesDatabaseManager.shared.localFileMetadataFromOcId(metadata.ocId) != nil + NextcloudFilesDatabaseManager.shared.localFileMetadataFromOcId(metadata.ocId) != nil } var isUploading: Bool { - return metadata.status == NextcloudItemMetadataTable.Status.uploading.rawValue + metadata.status == NextcloudItemMetadataTable.Status.uploading.rawValue } var uploadingError: Error? { if metadata.status == NextcloudItemMetadataTable.Status.uploadError.rawValue { - return FileProviderItemTransferError.uploadError + FileProviderItemTransferError.uploadError } else { - return nil + nil } } var childItemCount: NSNumber? { if metadata.directory { - return NSNumber(integerLiteral: NextcloudFilesDatabaseManager.shared.childItemsForDirectory(metadata).count) + NSNumber( + integerLiteral: NextcloudFilesDatabaseManager.shared.childItemsForDirectory( + metadata + ).count) } else { - return nil + nil } } - required init(metadata: NextcloudItemMetadataTable, parentItemIdentifier: NSFileProviderItemIdentifier, ncKit: NextcloudKit) { + required init( + metadata: NextcloudItemMetadataTable, parentItemIdentifier: NSFileProviderItemIdentifier, + ncKit: NextcloudKit + ) { self.metadata = metadata self.parentItemIdentifier = parentItemIdentifier self.ncKit = ncKit diff --git a/shell_integration/MacOSX/NextcloudIntegration/FileProviderExt/FileProviderMaterialisedEnumerationObserver.swift b/shell_integration/MacOSX/NextcloudIntegration/FileProviderExt/FileProviderMaterialisedEnumerationObserver.swift index 168de6680..e68c3fd8b 100644 --- a/shell_integration/MacOSX/NextcloudIntegration/FileProviderExt/FileProviderMaterialisedEnumerationObserver.swift +++ b/shell_integration/MacOSX/NextcloudIntegration/FileProviderExt/FileProviderMaterialisedEnumerationObserver.swift @@ -12,44 +12,53 @@ * for more details. */ -import Foundation import FileProvider +import Foundation import OSLog -class FileProviderMaterialisedEnumerationObserver : NSObject, NSFileProviderEnumerationObserver { +class FileProviderMaterialisedEnumerationObserver: NSObject, NSFileProviderEnumerationObserver { let ncKitAccount: String let completionHandler: (_ deletedOcIds: Set) -> Void - var allEnumeratedItemIds: Set = Set() + var allEnumeratedItemIds: Set = .init() - required init(ncKitAccount: String, completionHandler: @escaping(_ deletedOcIds: Set) -> Void) { + required init( + ncKitAccount: String, completionHandler: @escaping (_ deletedOcIds: Set) -> Void + ) { self.ncKitAccount = ncKitAccount self.completionHandler = completionHandler super.init() } func didEnumerate(_ updatedItems: [NSFileProviderItemProtocol]) { - let updatedItemsIds = Array(updatedItems.map { $0.itemIdentifier.rawValue }) + let updatedItemsIds = Array(updatedItems.map(\.itemIdentifier.rawValue)) for updatedItemsId in updatedItemsIds { allEnumeratedItemIds.insert(updatedItemsId) } } - func finishEnumerating(upTo nextPage: NSFileProviderPage?) { + func finishEnumerating(upTo _: NSFileProviderPage?) { Logger.materialisedFileHandling.debug("Handling enumerated materialised items.") - FileProviderMaterialisedEnumerationObserver.handleEnumeratedItems(self.allEnumeratedItemIds, - account: self.ncKitAccount, - completionHandler: self.completionHandler) + FileProviderMaterialisedEnumerationObserver.handleEnumeratedItems( + allEnumeratedItemIds, + account: ncKitAccount, + completionHandler: completionHandler) } func finishEnumeratingWithError(_ error: Error) { - Logger.materialisedFileHandling.error("Ran into error when enumerating materialised items: \(error.localizedDescription, privacy: .public). Handling items enumerated so far") - FileProviderMaterialisedEnumerationObserver.handleEnumeratedItems(self.allEnumeratedItemIds, - account: self.ncKitAccount, - completionHandler: self.completionHandler) + Logger.materialisedFileHandling.error( + "Ran into error when enumerating materialised items: \(error.localizedDescription, privacy: .public). Handling items enumerated so far" + ) + FileProviderMaterialisedEnumerationObserver.handleEnumeratedItems( + allEnumeratedItemIds, + account: ncKitAccount, + completionHandler: completionHandler) } - static func handleEnumeratedItems(_ itemIds: Set, account: String, completionHandler: @escaping(_ deletedOcIds: Set) -> Void) { + static func handleEnumeratedItems( + _ itemIds: Set, account: String, + completionHandler: @escaping (_ deletedOcIds: Set) -> Void + ) { let dbManager = NextcloudFilesDatabaseManager.shared let databaseLocalFileMetadatas = dbManager.localFileMetadatas(account: account) var noLongerMaterialisedIds = Set() @@ -60,12 +69,13 @@ class FileProviderMaterialisedEnumerationObserver : NSObject, NSFileProviderEnum guard itemIds.contains(localFileOcId) else { noLongerMaterialisedIds.insert(localFileOcId) - continue; + continue } } DispatchQueue.main.async { - Logger.materialisedFileHandling.info("Cleaning up local file metadatas for unmaterialised items") + Logger.materialisedFileHandling.info( + "Cleaning up local file metadatas for unmaterialised items") for itemId in noLongerMaterialisedIds { dbManager.deleteLocalFileMetadata(ocId: itemId) } diff --git a/shell_integration/MacOSX/NextcloudIntegration/FileProviderExt/FileProviderSocketLineProcessor.swift b/shell_integration/MacOSX/NextcloudIntegration/FileProviderExt/FileProviderSocketLineProcessor.swift index cf6ff8c77..3a9f54a10 100644 --- a/shell_integration/MacOSX/NextcloudIntegration/FileProviderExt/FileProviderSocketLineProcessor.swift +++ b/shell_integration/MacOSX/NextcloudIntegration/FileProviderExt/FileProviderSocketLineProcessor.swift @@ -24,25 +24,27 @@ class FileProviderSocketLineProcessor: NSObject, LineProcessor { } func process(_ line: String) { - if (line.contains("~")) { // We use this as the separator specifically in ACCOUNT_DETAILS - Logger.desktopClientConnection.debug("Processing file provider line with potentially sensitive user data") + if line.contains("~") { // We use this as the separator specifically in ACCOUNT_DETAILS + Logger.desktopClientConnection.debug( + "Processing file provider line with potentially sensitive user data") } else { - Logger.desktopClientConnection.debug("Processing file provider line: \(line, privacy: .public)") + Logger.desktopClientConnection.debug( + "Processing file provider line: \(line, privacy: .public)") } let splitLine = line.split(separator: ":", maxSplits: 1) guard let commandSubsequence = splitLine.first else { Logger.desktopClientConnection.error("Input line did not have a first element") - return; + return } - let command = String(commandSubsequence); + let command = String(commandSubsequence) Logger.desktopClientConnection.debug("Received command: \(command, privacy: .public)") - if (command == "SEND_FILE_PROVIDER_DOMAIN_IDENTIFIER") { + if command == "SEND_FILE_PROVIDER_DOMAIN_IDENTIFIER" { delegate.sendFileProviderDomainIdentifier() - } else if (command == "ACCOUNT_NOT_AUTHENTICATED") { + } else if command == "ACCOUNT_NOT_AUTHENTICATED" { delegate.removeAccountConfig() - } else if (command == "ACCOUNT_DETAILS") { + } else if command == "ACCOUNT_DETAILS" { guard let accountDetailsSubsequence = splitLine.last else { return } let splitAccountDetails = accountDetailsSubsequence.split(separator: "~", maxSplits: 2) diff --git a/shell_integration/MacOSX/NextcloudIntegration/FileProviderExt/LocalFilesUtils.swift b/shell_integration/MacOSX/NextcloudIntegration/FileProviderExt/LocalFilesUtils.swift index 1e68cf890..d1465276a 100644 --- a/shell_integration/MacOSX/NextcloudIntegration/FileProviderExt/LocalFilesUtils.swift +++ b/shell_integration/MacOSX/NextcloudIntegration/FileProviderExt/LocalFilesUtils.swift @@ -12,17 +12,22 @@ * for more details. */ -import Foundation import FileProvider +import Foundation import OSLog func pathForAppGroupContainer() -> URL? { - guard let appGroupIdentifier = Bundle.main.object(forInfoDictionaryKey: "SocketApiPrefix") as? String else { - Logger.localFileOps.critical("Could not get container url as missing SocketApiPrefix info in app Info.plist") + guard + let appGroupIdentifier = Bundle.main.object(forInfoDictionaryKey: "SocketApiPrefix") + as? String + else { + Logger.localFileOps.critical( + "Could not get container url as missing SocketApiPrefix info in app Info.plist") return nil } - return FileManager.default.containerURL(forSecurityApplicationGroupIdentifier: appGroupIdentifier) + return FileManager.default.containerURL( + forSecurityApplicationGroupIdentifier: appGroupIdentifier) } func pathForFileProviderExtData() -> URL? { @@ -32,7 +37,9 @@ func pathForFileProviderExtData() -> URL? { func pathForFileProviderTempFilesForDomain(_ domain: NSFileProviderDomain) throws -> URL? { guard let fpManager = NSFileProviderManager(for: domain) else { - Logger.localFileOps.error("Unable to get file provider manager for domain: \(domain.displayName, privacy: .public)") + Logger.localFileOps.error( + "Unable to get file provider manager for domain: \(domain.displayName, privacy: .public)" + ) throw NSFileProviderError(.providerNotFound) } @@ -40,9 +47,13 @@ func pathForFileProviderTempFilesForDomain(_ domain: NSFileProviderDomain) throw return fileProviderDataUrl.appendingPathComponent("TemporaryNextcloudFiles/") } -func localPathForNCFile(ocId: String, fileNameView: String, domain: NSFileProviderDomain) throws -> URL { +func localPathForNCFile(ocId _: String, fileNameView: String, domain: NSFileProviderDomain) throws + -> URL +{ guard let fileProviderFilesPathUrl = try pathForFileProviderTempFilesForDomain(domain) else { - Logger.localFileOps.error("Unable to get path for file provider temp files for domain: \(domain.displayName, privacy: .public)") + Logger.localFileOps.error( + "Unable to get path for file provider temp files for domain: \(domain.displayName, privacy: .public)" + ) throw URLError(.badURL) } diff --git a/shell_integration/MacOSX/NextcloudIntegration/FileProviderExt/NextcloudAccount.swift b/shell_integration/MacOSX/NextcloudIntegration/FileProviderExt/NextcloudAccount.swift index 0dc628d7d..9e5b64656 100644 --- a/shell_integration/MacOSX/NextcloudIntegration/FileProviderExt/NextcloudAccount.swift +++ b/shell_integration/MacOSX/NextcloudIntegration/FileProviderExt/NextcloudAccount.swift @@ -12,21 +12,20 @@ * for more details. */ -import Foundation import FileProvider +import Foundation class NextcloudAccount: NSObject { static let webDavFilesUrlSuffix: String = "/remote.php/dav/files/" let username, password, ncKitAccount, serverUrl, davFilesUrl: String init(user: String, serverUrl: String, password: String) { - self.username = user + username = user self.password = password - self.ncKitAccount = user + " " + serverUrl + ncKitAccount = user + " " + serverUrl self.serverUrl = serverUrl - self.davFilesUrl = serverUrl + NextcloudAccount.webDavFilesUrlSuffix + user + davFilesUrl = serverUrl + NextcloudAccount.webDavFilesUrlSuffix + user super.init() } } -