Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions REUSE.toml
Original file line number Diff line number Diff line change
Expand Up @@ -32,9 +32,9 @@ SPDX-License-Identifier = "GPL-2.0-or-later"
[[annotations]]
path = [
"admin/osx/container-migration.plist.cmake",
"admin/osx/TransifexStringCatalogSanitizer/Package.swift",
"admin/osx/TransifexStringCatalogSanitizer/Package.resolved",
"admin/osx/TransifexStringCatalogSanitizer/README.md",
"shell_integration/MacOSX/TransifexStringCatalogSanitizer/Package.swift",
"shell_integration/MacOSX/TransifexStringCatalogSanitizer/Package.resolved",
"shell_integration/MacOSX/TransifexStringCatalogSanitizer/README.md",
]
precedence = "aggregate"
SPDX-FileCopyrightText = "2025 Nextcloud GmbH and Nextcloud contributors"
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ public extension FilesDatabaseManager {
return nil
}

// Deletes all metadatas related to the info of the directory provided
/// Deletes all metadatas related to the info of the directory provided
func deleteDirectoryAndSubdirectoriesMetadata(
ocId: String
) -> [SendableItemMetadata]? {
Expand Down Expand Up @@ -126,7 +126,8 @@ public extension FilesDatabaseManager {
"""
Moved childItem at: \(oldServerUrl)
to: \(movedServerUrl)
""")
"""
)
}
}
} catch {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,9 @@ public final class FilesDatabaseManager: Sendable {
let logger: FileProviderLogger
let account: Account

var itemMetadatas: Results<RealmItemMetadata> { ncDatabase().objects(RealmItemMetadata.self) }
var itemMetadatas: Results<RealmItemMetadata> {
ncDatabase().objects(RealmItemMetadata.self)
}

///
/// Convenience initializer which defines a default configuration for Realm.
Expand Down Expand Up @@ -278,8 +280,8 @@ public final class FilesDatabaseManager: Sendable {
return (returningNewMetadatas, returningUpdatedMetadatas, directoriesNeedingRename)
}

// ONLY HANDLES UPDATES FOR IMMEDIATE CHILDREN
// (in case of directory renames/moves, the changes are recursed down)
/// ONLY HANDLES UPDATES FOR IMMEDIATE CHILDREN
/// (in case of directory renames/moves, the changes are recursed down)
public func depth1ReadUpdateItemMetadatas(
account: String,
serverUrl: String,
Expand Down Expand Up @@ -389,8 +391,8 @@ public final class FilesDatabaseManager: Sendable {
}
}

// If setting a downloading or uploading status, also modified the relevant boolean properties
// of the item metadata object
/// If setting a downloading or uploading status, also modified the relevant boolean properties
/// of the item metadata object
public func setStatusForItemMetadata(
_ metadata: SendableItemMetadata, status: Status
) -> SendableItemMetadata? {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,9 @@ extension Enumerator {
return (metadatas, nil)
}

// With paginated requests, you do not have a way to know what has changed remotely when
// handling the result of an individual PROPFIND request. When handling a paginated read this
// therefore only returns the acquired metadatas.
/// With paginated requests, you do not have a way to know what has changed remotely when
/// handling the result of an individual PROPFIND request. When handling a paginated read this
/// therefore only returns the acquired metadatas.
static func handleDepth1ReadFileOrFolder(
serverUrl: String,
account: Account,
Expand Down Expand Up @@ -92,19 +92,19 @@ extension Enumerator {
)
}

// READ THIS CAREFULLY.
//
// This method supports paginated and non-paginated reads. Handled by the pageSettings argument.
// Paginated reads is used by enumerateItems, non-paginated reads is used by enumerateChanges.
//
// Paginated reads WILL NOT HANDLE REMOVAL OF REMOTELY DELETED ITEMS FROM THE LOCAL DATABASE.
// Paginated reads WILL ONLY REPORT THE FILES DISCOVERED REMOTELY.
// This means that if you decide to use this method to implement change enumeration, you will
// have to collect the full results of all the pages before proceeding with discovering what
// has changed relative to the state of the local database -- manually!
//
// Non-paginated reads will update the database with all of the discovered files and folders
// that have been found to be created, updated, and deleted. No extra work required.
/// READ THIS CAREFULLY.
///
/// This method supports paginated and non-paginated reads. Handled by the pageSettings argument.
/// Paginated reads is used by enumerateItems, non-paginated reads is used by enumerateChanges.
///
/// Paginated reads WILL NOT HANDLE REMOVAL OF REMOTELY DELETED ITEMS FROM THE LOCAL DATABASE.
/// Paginated reads WILL ONLY REPORT THE FILES DISCOVERED REMOTELY.
/// This means that if you decide to use this method to implement change enumeration, you will
/// have to collect the full results of all the pages before proceeding with discovering what
/// has changed relative to the state of the local database -- manually!
///
/// Non-paginated reads will update the database with all of the discovered files and folders
/// that have been found to be created, updated, and deleted. No extra work required.
static func readServerUrl(
_ serverUrl: String,
pageSettings: (page: NSFileProviderPage?, index: Int, size: Int)? = nil,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,8 @@ public final class Enumerator: NSObject, NSFileProviderEnumerator, Sendable {
} else {
logger.debug("Providing enumerator for item with identifier.", [.item: enumeratedItemIdentifier])
enumeratedItemMetadata = dbManager.itemMetadata(
enumeratedItemIdentifier)
enumeratedItemIdentifier
)

if let enumeratedItemMetadata {
serverUrl = enumeratedItemMetadata.serverUrl + "/" + enumeratedItemMetadata.fileName
Expand Down Expand Up @@ -493,7 +494,8 @@ public final class Enumerator: NSObject, NSFileProviderEnumerator, Sendable {
}

let allFpItemDeletionsIdentifiers = Array(
allDeletedMetadatas.map { NSFileProviderItemIdentifier($0.ocId) })
allDeletedMetadatas.map { NSFileProviderItemIdentifier($0.ocId) }
)
if !allFpItemDeletionsIdentifiers.isEmpty {
observer.didDeleteItems(withIdentifiers: allFpItemDeletionsIdentifiers)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,9 @@ public final class RemoteChangeObserver: NSObject, @unchecked Sendable {
public let domain: NSFileProviderDomain?
public let dbManager: FilesDatabaseManager
public var account: Account
public var accountId: String { account.ncKitAccount }
public var accountId: String {
account.ncKitAccount
}

public var webSocketPingIntervalNanoseconds: UInt64 = 3 * 1_000_000_000
public let webSocketReconfigureIntervalNanoseconds: UInt64 = 1 * 1_000_000_000
Expand Down Expand Up @@ -272,7 +274,7 @@ public final class RemoteChangeObserver: NSObject, @unchecked Sendable {
return
}

guard await invalidated == false else {
guard invalidated == false else {
return
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ extension RandomAccessCollection {
}

/// Performs an asynchronous `compactMap` operation on the collection in concurrent chunks.
func concurrentChunkedCompactMap<T>(into size: Int = defaultChunkSize, transform: @escaping @Sendable (Element) throws -> T?) async throws -> [T] where T: Sendable, Element: Sendable {
func concurrentChunkedCompactMap<T: Sendable>(into size: Int = defaultChunkSize, transform: @escaping @Sendable (Element) throws -> T?) async throws -> [T] where Element: Sendable {
try await withThrowingTaskGroup(of: [T].self) { group in
var results = [T]()
// Reserving capacity is still a good optimization, though we can't know the exact final count.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,7 @@
// SPDX-License-Identifier: LGPL-3.0-or-later

public extension Substring {
func toString() -> String { String(self) }
func toString() -> String {
String(self)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -84,24 +84,19 @@ extension NextcloudKit: RemoteInterface {
modificationDate: Date? = nil,
account: Account,
options: NKRequestOptions = .init(),
currentNumChunksUpdateHandler: @escaping (_ num: Int) -> Void = { _ in },
chunkCounter: @escaping (_ counter: Int) -> Void = { _ in },
currentNumChunksUpdateHandler _: @escaping (_ num: Int) -> Void = { _ in },
chunkCounter _: @escaping (_ counter: Int) -> Void = { _ in },
log: any FileProviderLogging,
chunkUploadStartHandler: @escaping (_ filesChunk: [RemoteFileChunk]) -> Void = { _ in },
requestHandler: @escaping (_ request: UploadRequest) -> Void = { _ in },
requestHandler _: @escaping (_ request: UploadRequest) -> Void = { _ in },
taskHandler: @escaping (_ task: URLSessionTask) -> Void = { _ in },
progressHandler: @escaping (Progress) -> Void = { _ in },
chunkUploadCompleteHandler: @escaping (_ fileChunk: RemoteFileChunk) -> Void = { _ in }
) async -> (
account: String,
fileChunks: [RemoteFileChunk]?,
file: NKFile?,
nkError: NKError
) {
) async -> (account: String, file: NKFile?, nkError: NKError) {
let logger = FileProviderLogger(category: "NextcloudKit+RemoteInterface", log: log)

guard let remoteUrl = URL(string: remotePath) else {
return ("", nil, nil, .urlError)
return ("", nil, .urlError)
}
let localUrl = URL(fileURLWithPath: localPath)

Expand All @@ -116,7 +111,7 @@ extension NextcloudKit: RemoteInterface {
Could not create temporary directory for chunked files: \(error)
"""
)
return ("", nil, nil, .urlError)
return ("", nil, .urlError)
}

var directory = localUrl.deletingLastPathComponent().path
Expand All @@ -134,7 +129,7 @@ extension NextcloudKit: RemoteInterface {
logger.error(
"NCKit ext: Could not get server url from \(remotePath)"
)
return ("", nil, nil, .urlError)
return ("", nil, .urlError)
}
let fileChunks = remainingChunks.toNcKitChunks()

Expand All @@ -154,8 +149,8 @@ extension NextcloudKit: RemoteInterface {
"""
)

return await withCheckedContinuation { continuation in
uploadChunk(
do {
let (account, file) = try await uploadChunkAsync(
directory: directory,
fileChunksOutputDirectory: fileChunksOutputDirectory,
fileName: fileName,
Expand All @@ -168,34 +163,27 @@ extension NextcloudKit: RemoteInterface {
chunkSize: chunkSize,
account: account.ncKitAccount,
options: options,
numChunks: currentNumChunksUpdateHandler,
counterChunk: chunkCounter,
start: { processedChunks in
let chunks = RemoteFileChunk.fromNcKitChunks(
processedChunks, remoteChunkStoreFolderName: remoteChunkStoreFolderName
)
uploadStart: { processedChunks in
let chunks = RemoteFileChunk.fromNcKitChunks(processedChunks, remoteChunkStoreFolderName: remoteChunkStoreFolderName)
chunkUploadStartHandler(chunks)
},
requestHandler: requestHandler,
taskHandler: taskHandler,
progressHandler: { totalBytesExpected, totalBytes, _ in
uploadTaskHandler: taskHandler,
uploadProgressHandler: { totalBytesExpected, totalBytes, _ in
let currentProgress = Progress(totalUnitCount: totalBytesExpected)
currentProgress.completedUnitCount = totalBytes
progressHandler(currentProgress)
},
uploaded: { uploadedChunk in
let chunk = RemoteFileChunk(
ncKitChunk: uploadedChunk,
remoteChunkStoreFolderName: remoteChunkStoreFolderName
)
let chunk = RemoteFileChunk(ncKitChunk: uploadedChunk, remoteChunkStoreFolderName: remoteChunkStoreFolderName)
chunkUploadCompleteHandler(chunk)
}
) { account, receivedChunks, file, error in
let chunks = RemoteFileChunk.fromNcKitChunks(
receivedChunks ?? [], remoteChunkStoreFolderName: remoteChunkStoreFolderName
)
continuation.resume(returning: (account, chunks, file, error))
}
)

return (account, file, .success)
} catch let nkError as NKError {
return (account.ncKitAccount, nil, nkError)
} catch {
return (account.ncKitAccount, nil, NKError.urlError)
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,6 @@ public protocol RemoteInterface: Sendable {
chunkUploadCompleteHandler: @escaping (_ fileChunk: RemoteFileChunk) -> Void
) async -> (
account: String,
fileChunks: [RemoteFileChunk]?,
file: NKFile?,
nkError: NKError
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@ public extension Item {
let logger = FileProviderLogger(category: "Item", log: log)
let chunkUploadId =
itemTemplate.itemIdentifier.rawValue.replacingOccurrences(of: "/", with: "")
let (ocId, _, etag, date, size, error) = await upload(
let (ocId, etag, date, size, error) = await upload(
fileLocatedAt: localPath,
toRemotePath: remotePath,
usingRemoteInterface: remoteInterface,
Expand Down Expand Up @@ -338,7 +338,7 @@ public extension Item {
Handling child bundle or package file at: \(childUrlPath)
"""
)
let (_, _, _, _, _, error) = await upload(
let (_, _, _, _, error) = await upload(
fileLocatedAt: childUrlPath,
toRemotePath: childRemoteUrl,
usingRemoteInterface: remoteInterface,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -86,11 +86,11 @@ public extension Item {
}
}

// NOTE: the trashing metadata modification procedure here is rough. You SHOULD run a rescan of
// the trash in order to ensure you are getting a correct picture of the item's current remote
// state! This is important particularly for receiving the correct trash bin filename in case of
// there being a previous item in the trash with the same name, prompting the server to rename
// the newly-trashed target item
/// NOTE: the trashing metadata modification procedure here is rough. You SHOULD run a rescan of
/// the trash in order to ensure you are getting a correct picture of the item's current remote
/// state! This is important particularly for receiving the correct trash bin filename in case of
/// there being a previous item in the trash with the same name, prompting the server to rename
/// the newly-trashed target item
private func handleMetadataTrashModification() -> Error? {
let ocId = metadata.ocId

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@ public extension Item {

let options = NKRequestOptions(customHeader: headers, queue: .global(qos: .utility))

let (_, _, etag, date, size, error) = await upload(
let (_, etag, date, size, error) = await upload(
fileLocatedAt: newContents.path,
toRemotePath: remotePath,
usingRemoteInterface: remoteInterface,
Expand Down Expand Up @@ -401,7 +401,7 @@ public extension Item {
Handling child bundle or package file at: \(childUrlPath)
"""
)
let (_, _, _, _, _, error) = await upload(
let (_, _, _, _, error) = await upload(
fileLocatedAt: childUrlPath,
toRemotePath: childRemoteUrl,
usingRemoteInterface: remoteInterface,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
import NextcloudKit

extension Item {
// Note: When handling trashing, the server handles filename conflicts for us
/// Note: When handling trashing, the server handles filename conflicts for us
static func trash(
_ modifiedItem: Item,
account: Account,
Expand Down Expand Up @@ -142,7 +142,7 @@ extension Item {
return (postDeleteItem, nil)
}

// Note: When restoring from the trash, the server handles filename conflicts for us
/// Note: When restoring from the trash, the server handles filename conflicts for us
static func restoreFromTrash(
_ modifiedItem: Item,
account: Account,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
@preconcurrency import FileProvider

extension Item {
// Creates a file that was previously unuploaded (e.g. a previously ignored/lock file) on server
/// Creates a file that was previously unuploaded (e.g. a previously ignored/lock file) on server
func createUnuploaded(
itemTarget: NSFileProviderItem,
baseVersion _: NSFileProviderItemVersion = NSFileProviderItemVersion(),
Expand Down Expand Up @@ -59,7 +59,7 @@ extension Item {
)
}

// Just modifies metadata
/// Just modifies metadata
func modifyUnuploaded(
itemTarget: NSFileProviderItem,
baseVersion _: NSFileProviderItemVersion = NSFileProviderItemVersion(),
Expand Down
Loading
Loading