diff --git a/Sources/NextcloudFileProviderKit/Database/FilesDatabaseManager.swift b/Sources/NextcloudFileProviderKit/Database/FilesDatabaseManager.swift index 1f529605..3f79688e 100644 --- a/Sources/NextcloudFileProviderKit/Database/FilesDatabaseManager.swift +++ b/Sources/NextcloudFileProviderKit/Database/FilesDatabaseManager.swift @@ -599,11 +599,7 @@ public final class FilesDatabaseManager: Sendable { var handledUpdateOcIds = Set(updated.map(\.ocId)) updated - .map { - var serverUrl = $0.serverUrl + "/" + $0.fileName - if serverUrl.last == "/" { serverUrl.removeLast() } - return serverUrl - } + .map { $0.remotePath() } .forEach { serverUrl in logger.debug("Checking updated item...", [.url: serverUrl]) @@ -630,15 +626,7 @@ public final class FilesDatabaseManager: Sendable { let handledDeleteOcIds = Set(deleted.map(\.ocId)) deleted - .map { // assemble remote location - var serverUrl = $0.serverUrl + "/" + $0.fileName - - if serverUrl.last == "/" { - serverUrl.removeLast() - } - - return serverUrl - } + .map { $0.remotePath() } .forEach { serverUrl in logger.debug("Verifying deleted item...", [.url: serverUrl]) diff --git a/Sources/NextcloudFileProviderKit/Enumeration/RemoteChangeObserver.swift b/Sources/NextcloudFileProviderKit/Enumeration/RemoteChangeObserver.swift index 05e47a81..45790036 100644 --- a/Sources/NextcloudFileProviderKit/Enumeration/RemoteChangeObserver.swift +++ b/Sources/NextcloudFileProviderKit/Enumeration/RemoteChangeObserver.swift @@ -456,10 +456,7 @@ public final class RemoteChangeObserver: NSObject, NextcloudKitDelegate, URLSess // This way we ensure we visit parent folders before their children. let materialisedItems = dbManager .materialisedItemMetadatas(account: accountId) - .sorted { - ($0.serverUrl + "/" + $0.fileName).count < - ($1.serverUrl + "/" + $1.fileName).count - } + .sorted { $0.remotePath().count < $1.remotePath().count } var allNewMetadatas = [SendableItemMetadata]() var allUpdatedMetadatas = [SendableItemMetadata]() @@ -480,7 +477,7 @@ public final class RemoteChangeObserver: NSObject, NextcloudKitDelegate, URLSess continue } - let itemRemoteUrl = item.serverUrl + "/" + item.fileName + let itemRemoteUrl = item.remotePath() let (metadatas, newMetadatas, updatedMetadatas, deletedMetadatas, _, readError) = await Enumerator.readServerUrl( itemRemoteUrl, @@ -550,7 +547,7 @@ public final class RemoteChangeObserver: NSObject, NextcloudKitDelegate, URLSess // Also mark any materialized children of this directory as examined let grandChildren = materialisedItems.filter { - $0.serverUrl.hasPrefix(localItem.serverUrl + "/" + localItem.fileName) + $0.serverUrl.hasPrefix(localItem.remotePath()) } examinedChildFilesAndDeletedItems.formUnion(grandChildren.map(\.ocId)) } diff --git a/Sources/NextcloudFileProviderKit/Item/Item+Create.swift b/Sources/NextcloudFileProviderKit/Item/Item+Create.swift index 856ee4e5..72beccc9 100644 --- a/Sources/NextcloudFileProviderKit/Item/Item+Create.swift +++ b/Sources/NextcloudFileProviderKit/Item/Item+Create.swift @@ -490,7 +490,7 @@ public extension Item { ) return (nil, NSFileProviderError(.cannotSynchronize)) } - parentItemRemotePath = parentItemMetadata.serverUrl + "/" + parentItemMetadata.fileName + parentItemRemotePath = parentItemMetadata.remotePath() parentItemRelativePath = parentItemRemotePath.replacingOccurrences( of: account.davFilesUrl, with: "" ) diff --git a/Sources/NextcloudFileProviderKit/Item/Item+Delete.swift b/Sources/NextcloudFileProviderKit/Item/Item+Delete.swift index deea53f3..88e1426d 100644 --- a/Sources/NextcloudFileProviderKit/Item/Item+Delete.swift +++ b/Sources/NextcloudFileProviderKit/Item/Item+Delete.swift @@ -24,7 +24,7 @@ public extension Item { } let ocId = itemIdentifier.rawValue - let relativePath = (metadata.serverUrl + "/" + metadata.fileName).replacingOccurrences(of: metadata.urlBase, with: "") + let relativePath = (metadata.remotePath()).replacingOccurrences(of: metadata.urlBase, with: "") guard metadata.isLockFileOfLocalOrigin == false else { return await deleteLockFile(domain: domain, dbManager: dbManager) @@ -36,7 +36,7 @@ public extension Item { return nil } - let serverFileNameUrl = metadata.serverUrl + "/" + metadata.fileName + let serverFileNameUrl = metadata.remotePath() guard serverFileNameUrl != "" else { return NSError.fileProviderErrorForNonExistentItem(withIdentifier: itemIdentifier) diff --git a/Sources/NextcloudFileProviderKit/Item/Item+Fetch.swift b/Sources/NextcloudFileProviderKit/Item/Item+Fetch.swift index 5cfd5a31..7d9ff4da 100644 --- a/Sources/NextcloudFileProviderKit/Item/Item+Fetch.swift +++ b/Sources/NextcloudFileProviderKit/Item/Item+Fetch.swift @@ -50,7 +50,7 @@ public extension Item { progress.totalUnitCount += Int64(metadatas.count) for var metadata in metadatas { - let remotePath = metadata.serverUrl + "/" + metadata.fileName + let remotePath = metadata.remotePath() let relativePath = remotePath.replacingOccurrences(of: directoryRemotePath, with: "") let childLocalPath = directoryLocalPath + relativePath @@ -129,7 +129,7 @@ public extension Item { } } - let serverUrlFileName = metadata.serverUrl + "/" + metadata.fileName + let serverUrlFileName = metadata.remotePath() logger.debug("Fetching item.", [.name: metadata.fileName, .url: serverUrlFileName]) diff --git a/Sources/NextcloudFileProviderKit/Metadata/ItemMetadata.swift b/Sources/NextcloudFileProviderKit/Metadata/ItemMetadata.swift index 62bcca51..8aa35afc 100644 --- a/Sources/NextcloudFileProviderKit/Metadata/ItemMetadata.swift +++ b/Sources/NextcloudFileProviderKit/Metadata/ItemMetadata.swift @@ -1,6 +1,7 @@ // SPDX-FileCopyrightText: 2023 Nextcloud GmbH and Nextcloud contributors // SPDX-License-Identifier: GPL-2.0-or-later +import FileProvider import Foundation /// @@ -73,7 +74,7 @@ public protocol ItemMetadata: Equatable { var quotaAvailableBytes: Int64 { get set } var resourceType: String { get set } var richWorkspace: String? { get set } - var serverUrl: String { get set } // For parent folder! Build remote url by adding fileName + var serverUrl: String { get set } // For parent folder! Retrieve the full remote url via .remotePath() var session: String? { get set } var sessionError: String? { get set } var sessionTaskIdentifier: Int? { get set } @@ -170,4 +171,14 @@ public extension ItemMetadata { .init(name: "a", value: "true"), ]) } + + func remotePath() -> String { + if ocId == NSFileProviderItemIdentifier.rootContainer.rawValue { + // For the root container the fileName is "__NC_ROOT__" (aka NextcloudKit.shared.nkCommonInstance.rootFileName) + // --> appending the fileName to that is not correct, as it most likely won't ecist + return serverUrl + } + + return "\(serverUrl)/\(fileName)" + } } diff --git a/Tests/NextcloudFileProviderKitTests/ItemCreateTests.swift b/Tests/NextcloudFileProviderKitTests/ItemCreateTests.swift index 1b960bd8..e7327713 100644 --- a/Tests/NextcloudFileProviderKitTests/ItemCreateTests.swift +++ b/Tests/NextcloudFileProviderKitTests/ItemCreateTests.swift @@ -715,7 +715,12 @@ final class ItemCreateTests: NextcloudFileProviderKitTestCase { XCTAssertNil(createdItem) let unwrappedError = try XCTUnwrap(error) as? NSFileProviderError - XCTAssertEqual(unwrappedError, NSFileProviderError(.cannotSynchronize)) + let expectedError = if #available(macOS 13.0, *) { + NSFileProviderError(.excludedFromSync) + } else { + NSFileProviderError(.cannotSynchronize) + } + XCTAssertEqual(unwrappedError, expectedError) XCTAssertNil(Self.dbManager.itemMetadata(ocId: lockFileMetadata.ocId)) XCTAssertFalse(targetRemote.locked) }