mirror of https://github.com/nextcloud/desktop
Use NCFPK item modify method
Signed-off-by: Claudio Cambra <claudio.cambra@nextcloud.com>
This commit is contained in:
parent
c9a131736a
commit
485b07a805
|
@ -213,285 +213,58 @@ import OSLog
|
||||||
}
|
}
|
||||||
|
|
||||||
func modifyItem(
|
func modifyItem(
|
||||||
_ item: NSFileProviderItem, baseVersion _: NSFileProviderItemVersion,
|
_ item: NSFileProviderItem,
|
||||||
changedFields: NSFileProviderItemFields, contents newContents: URL?,
|
baseVersion: NSFileProviderItemVersion,
|
||||||
options: NSFileProviderModifyItemOptions = [], request: NSFileProviderRequest,
|
changedFields: NSFileProviderItemFields,
|
||||||
completionHandler: @escaping (NSFileProviderItem?, NSFileProviderItemFields, Bool, Error?)
|
contents newContents: URL?,
|
||||||
->
|
options: NSFileProviderModifyItemOptions = [],
|
||||||
Void
|
request: NSFileProviderRequest,
|
||||||
|
completionHandler: @escaping (
|
||||||
|
NSFileProviderItem?, NSFileProviderItemFields, Bool, Error?
|
||||||
|
) -> Void
|
||||||
) -> Progress {
|
) -> Progress {
|
||||||
// An item was modified on disk, process the item's modification
|
// An item was modified on disk, process the item's modification
|
||||||
// TODO: Handle finder things like tags, other possible item changed fields
|
// TODO: Handle finder things like tags, other possible item changed fields
|
||||||
|
|
||||||
|
let identifier = item.itemIdentifier
|
||||||
|
let ocId = identifier.rawValue
|
||||||
Logger.fileProviderExtension.debug(
|
Logger.fileProviderExtension.debug(
|
||||||
"Received modify item request for item with identifier: \(item.itemIdentifier.rawValue, privacy: .public) and filename: \(item.filename, privacy: .public)"
|
"""
|
||||||
|
Received modify item request for item with identifier: \(ocId, privacy: .public)
|
||||||
|
and filename: \(item.filename, privacy: .public)
|
||||||
|
"""
|
||||||
)
|
)
|
||||||
|
|
||||||
guard let ncAccount else {
|
guard let ncAccount else {
|
||||||
Logger.fileProviderExtension.error(
|
Logger.fileProviderExtension.error(
|
||||||
"Not modifying item: \(item.itemIdentifier.rawValue, privacy: .public) as account not set up yet"
|
"Not modifying item: \(ocId, privacy: .public) as account not set up yet."
|
||||||
)
|
)
|
||||||
completionHandler(item, [], false, NSFileProviderError(.notAuthenticated))
|
completionHandler(item, [], false, NSFileProviderError(.notAuthenticated))
|
||||||
return Progress()
|
return Progress()
|
||||||
}
|
}
|
||||||
|
|
||||||
let dbManager = FilesDatabaseManager.shared
|
guard let item = Item.storedItem(identifier: identifier, usingKit: ncKit) else {
|
||||||
let parentItemIdentifier = item.parentItemIdentifier
|
Logger.fileProviderExtension.error(
|
||||||
let itemTemplateIsFolder = item.contentType == .folder || item.contentType == .directory
|
"Not modifying item: \(ocId, privacy: .public) as item not found."
|
||||||
|
|
||||||
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"
|
|
||||||
)
|
)
|
||||||
}
|
completionHandler(item, [], false, NSFileProviderError(.noSuchItem))
|
||||||
|
|
||||||
var parentItemServerUrl: String
|
|
||||||
|
|
||||||
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)"
|
|
||||||
)
|
|
||||||
completionHandler(item, [], false, NSFileProviderError(.noSuchItem))
|
|
||||||
return Progress()
|
|
||||||
}
|
|
||||||
|
|
||||||
parentItemServerUrl = parentItemMetadata.serverUrl + "/" + parentItemMetadata.fileName
|
|
||||||
}
|
|
||||||
|
|
||||||
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)"
|
|
||||||
)
|
|
||||||
|
|
||||||
var modifiedItem = item
|
|
||||||
|
|
||||||
// Create a serial dispatch queue
|
|
||||||
// We want to wait for network operations to finish before we fire off subsequent network
|
|
||||||
// operations, or we might cause explosions (e.g. trying to modify items that have just been
|
|
||||||
// moved elsewhere)
|
|
||||||
let dispatchQueue = DispatchQueue(label: "modifyItemQueue", qos: .userInitiated)
|
|
||||||
|
|
||||||
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..."
|
|
||||||
)
|
|
||||||
|
|
||||||
guard let metadata = dbManager.itemMetadataFromOcId(ocId) else {
|
|
||||||
Logger.fileProviderExtension.error(
|
|
||||||
"Could not acquire metadata of item with identifier: \(item.itemIdentifier.rawValue, privacy: .public)"
|
|
||||||
)
|
|
||||||
completionHandler(item, [], false, NSFileProviderError(.noSuchItem))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
var renameError: NSFileProviderError?
|
|
||||||
let oldServerUrlFileName = metadata.serverUrl + "/" + metadata.fileName
|
|
||||||
|
|
||||||
let moveFileOrFolderDispatchGroup = DispatchGroup() // Make this block wait until done
|
|
||||||
moveFileOrFolderDispatchGroup.enter()
|
|
||||||
|
|
||||||
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)"
|
|
||||||
)
|
|
||||||
renameError = error.fileProviderError
|
|
||||||
moveFileOrFolderDispatchGroup.leave()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// 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)
|
|
||||||
self.signalEnumerator { error in
|
|
||||||
if error != nil {
|
|
||||||
Logger.fileTransfer.error(
|
|
||||||
"Error notifying change in moved directory: \(error)")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
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"
|
|
||||||
)
|
|
||||||
renameError = NSFileProviderError(.noSuchItem)
|
|
||||||
moveFileOrFolderDispatchGroup.leave()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
modifiedItem = Item(
|
|
||||||
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)"
|
|
||||||
)
|
|
||||||
completionHandler(modifiedItem, [], false, renameError)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
guard !itemTemplateIsFolder else {
|
|
||||||
Logger.fileTransfer.debug(
|
|
||||||
"Only handling renaming for folders. ocId: \(ocId, privacy: .public)")
|
|
||||||
completionHandler(modifiedItem, [], false, nil)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Return the progress if item is folder here while the async block runs
|
|
||||||
guard !itemTemplateIsFolder else {
|
|
||||||
return Progress()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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."
|
|
||||||
)
|
|
||||||
completionHandler(modifiedItem, [], false, nil)
|
|
||||||
return Progress()
|
return Progress()
|
||||||
}
|
}
|
||||||
|
|
||||||
let progress = Progress()
|
let progress = Progress()
|
||||||
|
Task {
|
||||||
if changedFields.contains(.contents) {
|
let (modifiedItem, error) = await item.modify(
|
||||||
dispatchQueue.async {
|
baseVersion: baseVersion,
|
||||||
Logger.fileProviderExtension.debug(
|
changedFields: changedFields,
|
||||||
"Item modification for \(item.itemIdentifier.rawValue, privacy: .public) \(item.filename, privacy: .public) includes contents"
|
contents: newContents,
|
||||||
)
|
options: options,
|
||||||
|
request: request,
|
||||||
guard newContents != nil else {
|
ncAccount: ncAccount,
|
||||||
Logger.fileProviderExtension.warning(
|
domain: domain,
|
||||||
"WARNING. Could not upload modified contents as was provided nil contents url. ocId: \(item.itemIdentifier.rawValue, privacy: .public)"
|
progress: progress
|
||||||
)
|
|
||||||
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))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
dbManager.setStatusForItemMetadata(
|
|
||||||
metadata, status: ItemMetadata.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"
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
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))"
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
let newMetadata = ItemMetadata()
|
|
||||||
newMetadata.date = (date ?? NSDate()) as Date
|
|
||||||
newMetadata.etag = etag ?? ""
|
|
||||||
newMetadata.account = account
|
|
||||||
newMetadata.fileName = item.filename
|
|
||||||
newMetadata.fileNameView = item.filename
|
|
||||||
newMetadata.ocId = ocId
|
|
||||||
newMetadata.size = size
|
|
||||||
newMetadata.contentType = item.contentType?.preferredMIMEType ?? ""
|
|
||||||
newMetadata.directory = itemTemplateIsFolder
|
|
||||||
newMetadata.serverUrl = parentItemServerUrl
|
|
||||||
newMetadata.session = ""
|
|
||||||
newMetadata.sessionError = ""
|
|
||||||
newMetadata.sessionTaskIdentifier = 0
|
|
||||||
newMetadata.status = ItemMetadata.Status.normal.rawValue
|
|
||||||
|
|
||||||
dbManager.addLocalFileMetadataFromItemMetadata(newMetadata)
|
|
||||||
dbManager.addItemMetadata(newMetadata)
|
|
||||||
|
|
||||||
modifiedItem = Item(
|
|
||||||
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)"
|
|
||||||
)
|
|
||||||
|
|
||||||
metadata.status = ItemMetadata.Status.uploadError.rawValue
|
|
||||||
metadata.sessionError = error.errorDescription
|
|
||||||
|
|
||||||
dbManager.addItemMetadata(metadata)
|
|
||||||
|
|
||||||
completionHandler(modifiedItem, [], false, error.fileProviderError)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
Logger.fileProviderExtension.debug(
|
|
||||||
"Nothing more to do with \(item.itemIdentifier.rawValue, privacy: .public) \(item.filename, privacy: .public), modifications complete"
|
|
||||||
)
|
)
|
||||||
completionHandler(modifiedItem, [], false, nil)
|
completionHandler(modifiedItem ?? item, [], false, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
return progress
|
return progress
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue