Skip to content

Commit 41c1a7f

Browse files
authored
Merge pull request #68 from claucambra/bugfix/ignore-files
Fix ignored files behaviour
2 parents 28e8e94 + e68b0a3 commit 41c1a7f

5 files changed

Lines changed: 152 additions & 80 deletions

File tree

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
//
2+
// Item+CreateUnuploaded.swift
3+
// NextcloudFileProviderKit
4+
//
5+
// Created by Claudio Cambra on 25/4/25.
6+
//
7+
8+
import FileProvider
9+
10+
extension Item {
11+
// Creates a file that was previously unuploaded (e.g. a previously ignored/lock file) on server
12+
func createUnuploaded(
13+
itemTarget: NSFileProviderItem,
14+
baseVersion: NSFileProviderItemVersion = NSFileProviderItemVersion(),
15+
changedFields: NSFileProviderItemFields,
16+
contents newContents: URL?,
17+
options: NSFileProviderModifyItemOptions = [],
18+
request: NSFileProviderRequest = NSFileProviderRequest(),
19+
ignoredFiles: IgnoredFilesMatcher? = nil,
20+
domain: NSFileProviderDomain? = nil,
21+
forcedChunkSize: Int? = nil,
22+
progress: Progress = .init(),
23+
dbManager: FilesDatabaseManager
24+
) async -> (Item?, Error?) {
25+
guard newContents != nil || domain != nil else {
26+
Self.logger.error(
27+
"""
28+
Unable to upload modified item that was previously unuploaded.
29+
filename: \(self.filename, privacy: .public)
30+
either the domain is nil, the provided contents are nil, or both.
31+
"""
32+
)
33+
return (nil, NSFileProviderError(.cannotSynchronize))
34+
}
35+
let modifiedItem = self
36+
var contentsLocation = newContents
37+
if contentsLocation == nil {
38+
assert(domain != nil)
39+
guard let domain, let localUrl = await localUrlForContents(domain: domain) else {
40+
Self.logger.error(
41+
"""
42+
Unable to upload modified item that was previously unuploaded.
43+
filename: \(modifiedItem.filename, privacy: .public)
44+
local url for contents could not be acquired.
45+
"""
46+
)
47+
return (nil, NSFileProviderError(.cannotSynchronize))
48+
}
49+
contentsLocation = localUrl
50+
}
51+
return await Self.create(
52+
basedOn: itemTarget,
53+
contents: contentsLocation,
54+
domain: domain,
55+
account: account,
56+
remoteInterface: remoteInterface,
57+
ignoredFiles: ignoredFiles,
58+
forcedChunkSize: forcedChunkSize,
59+
progress: progress,
60+
dbManager: dbManager
61+
)
62+
}
63+
}

Sources/NextcloudFileProviderKit/Item/Item+Modify.swift

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -854,13 +854,36 @@ public extension Item {
854854
Will delete locally with no remote effect.
855855
"""
856856
)
857-
return (modifiedItem, nil)
857+
guard let modifiedIgnored = modifyUnuploaded(
858+
itemTarget: itemTarget,
859+
baseVersion: baseVersion,
860+
changedFields: changedFields,
861+
contents: newContents,
862+
options: options,
863+
request: request,
864+
ignoredFiles: ignoredFiles,
865+
domain: domain,
866+
forcedChunkSize: forcedChunkSize,
867+
progress: progress,
868+
dbManager: dbManager
869+
) else {
870+
Self.logger.error(
871+
"Unable to modify ignored file, got nil item: \(relativePath, privacy: .public)"
872+
)
873+
return (nil, NSFileProviderError(.cannotSynchronize))
874+
}
875+
modifiedItem = modifiedIgnored
876+
if #available(macOS 13.0, *) {
877+
return (modifiedItem, NSFileProviderError(.excludedFromSync))
878+
} else {
879+
return (modifiedItem, nil)
880+
}
858881
}
859882

860883
// We are handling an item that is available locally but not on the server -- so create it
861884
// This can happen when a previously ignored file is no longer ignored
862885
if !modifiedItem.isUploaded, modifiedItem.isDownloaded, modifiedItem.metadata.etag == "" {
863-
return await modifiedItem.modifyUnuploaded(
886+
return await modifiedItem.createUnuploaded(
864887
itemTarget: itemTarget,
865888
baseVersion: baseVersion,
866889
changedFields: changedFields,

Sources/NextcloudFileProviderKit/Item/Item+ModifyLockFile.swift

Lines changed: 18 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -29,56 +29,24 @@ extension Item {
2929
)
3030
assert(isLockFileName(filename), "Should not handle non-lock files here.")
3131

32-
var modifiedParentItemIdentifier = parentItemIdentifier
33-
var modifiedMetadata = metadata
34-
35-
if changedFields.contains(.filename) {
36-
modifiedMetadata.fileName = itemTarget.filename
37-
if !isLockFileName(modifiedMetadata.fileName) {
38-
modifiedMetadata.classFile = ""
39-
// Do the actual upload at the end, not yet
40-
}
41-
}
42-
if changedFields.contains(.contents),
43-
let newSize = try? newContents?.resourceValues(forKeys: [.fileSizeKey]).fileSize
44-
{
45-
modifiedMetadata.size = Int64(newSize)
46-
}
47-
if changedFields.contains(.parentItemIdentifier) {
48-
guard let parentMetadata = dbManager.itemMetadata(
49-
ocId: itemTarget.parentItemIdentifier.rawValue
50-
) else {
51-
Self.logger.error(
52-
"""
53-
Unable to find new parent item identifier during lock file modification.
54-
Lock file: \(self.filename, privacy: .public)
55-
"""
56-
)
57-
return (nil, NSFileProviderError(.cannotSynchronize))
58-
}
59-
modifiedMetadata.serverUrl = parentMetadata.serverUrl + "/" + parentMetadata.fileName
60-
modifiedParentItemIdentifier = .init(parentMetadata.ocId)
61-
}
62-
if changedFields.contains(.creationDate),
63-
let newCreationDate = itemTarget.creationDate,
64-
let newCreationDate
65-
{
66-
modifiedMetadata.creationDate = newCreationDate
67-
}
68-
if changedFields.contains(.contentModificationDate),
69-
let newModificationDate = itemTarget.contentModificationDate,
70-
let newModificationDate
71-
{
72-
modifiedMetadata.date = newModificationDate
73-
}
74-
75-
let modifiedItem = Item(
76-
metadata: modifiedMetadata,
77-
parentItemIdentifier: modifiedParentItemIdentifier,
78-
account: account,
79-
remoteInterface: remoteInterface,
32+
guard let modifiedItem = modifyUnuploaded(
33+
itemTarget: itemTarget,
34+
baseVersion: baseVersion,
35+
changedFields: changedFields,
36+
contents: newContents,
37+
options: options,
38+
request: request,
39+
ignoredFiles: ignoredFiles,
40+
domain: domain,
41+
forcedChunkSize: forcedChunkSize,
42+
progress: progress,
8043
dbManager: dbManager
81-
)
44+
) else {
45+
Self.logger.info(
46+
"Cannot modify lock file: \(self.filename) as received a nil modified item"
47+
)
48+
return (nil, NSFileProviderError(.cannotSynchronize))
49+
}
8250

8351
if !isLockFileName(modifiedItem.filename) {
8452
Self.logger.info(
@@ -88,7 +56,7 @@ extension Item {
8856
Will proceed with creating item on server (if possible).
8957
"""
9058
)
91-
return await modifiedItem.modifyUnuploaded(
59+
return await modifiedItem.createUnuploaded(
9260
itemTarget: itemTarget,
9361
baseVersion: baseVersion,
9462
changedFields: changedFields,

Sources/NextcloudFileProviderKit/Item/Item+ModifyUnuploaded.swift

Lines changed: 41 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
import FileProvider
99

1010
extension Item {
11+
// Just modifies metadata
1112
func modifyUnuploaded(
1213
itemTarget: NSFileProviderItem,
1314
baseVersion: NSFileProviderItemVersion = NSFileProviderItemVersion(),
@@ -20,42 +21,55 @@ extension Item {
2021
forcedChunkSize: Int? = nil,
2122
progress: Progress = .init(),
2223
dbManager: FilesDatabaseManager
23-
) async -> (Item?, Error?) {
24-
guard newContents != nil || domain != nil else {
25-
Self.logger.error(
26-
"""
27-
Unable to upload modified item that was previously ignored.
28-
filename: \(self.filename, privacy: .public)
29-
either the domain is nil, the provided contents are nil, or both.
30-
"""
31-
)
32-
return (nil, NSFileProviderError(.cannotSynchronize))
24+
) -> Item? {
25+
var modifiedParentItemIdentifier = parentItemIdentifier
26+
var modifiedMetadata = metadata
27+
28+
if changedFields.contains(.filename) {
29+
modifiedMetadata.fileName = itemTarget.filename
30+
if !isLockFileName(modifiedMetadata.fileName) {
31+
modifiedMetadata.classFile = ""
32+
// Do the actual upload at the end, not yet
33+
}
34+
}
35+
if changedFields.contains(.contents),
36+
let newSize = try? newContents?.resourceValues(forKeys: [.fileSizeKey]).fileSize
37+
{
38+
modifiedMetadata.size = Int64(newSize)
3339
}
34-
let modifiedItem = self
35-
var contentsLocation = newContents
36-
if contentsLocation == nil {
37-
assert(domain != nil)
38-
guard let domain, let localUrl = await localUrlForContents(domain: domain) else {
40+
if changedFields.contains(.parentItemIdentifier) {
41+
guard let parentMetadata = dbManager.itemMetadata(
42+
ocId: itemTarget.parentItemIdentifier.rawValue
43+
) else {
3944
Self.logger.error(
4045
"""
41-
Unable to upload modified item that was previously ignored.
42-
filename: \(modifiedItem.filename, privacy: .public)
43-
local url for contents could not be acquired.
46+
Unable to find new parent item identifier during unuploaded item modification.
47+
Filename: \(self.filename, privacy: .public)
4448
"""
4549
)
46-
return (nil, NSFileProviderError(.cannotSynchronize))
50+
return nil
4751
}
48-
contentsLocation = localUrl
52+
modifiedMetadata.serverUrl = parentMetadata.serverUrl + "/" + parentMetadata.fileName
53+
modifiedParentItemIdentifier = .init(parentMetadata.ocId)
4954
}
50-
return await Self.create(
51-
basedOn: itemTarget,
52-
contents: contentsLocation,
53-
domain: domain,
55+
if changedFields.contains(.creationDate),
56+
let newCreationDate = itemTarget.creationDate,
57+
let newCreationDate
58+
{
59+
modifiedMetadata.creationDate = newCreationDate
60+
}
61+
if changedFields.contains(.contentModificationDate),
62+
let newModificationDate = itemTarget.contentModificationDate,
63+
let newModificationDate
64+
{
65+
modifiedMetadata.date = newModificationDate
66+
}
67+
68+
return Item(
69+
metadata: modifiedMetadata,
70+
parentItemIdentifier: modifiedParentItemIdentifier,
5471
account: account,
5572
remoteInterface: remoteInterface,
56-
ignoredFiles: ignoredFiles,
57-
forcedChunkSize: forcedChunkSize,
58-
progress: progress,
5973
dbManager: dbManager
6074
)
6175
}

Tests/NextcloudFileProviderKitTests/ItemModifyTests.swift

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1349,7 +1349,11 @@ final class ItemModifyTests: XCTestCase {
13491349
ignoredFiles: ignoredMatcher,
13501350
dbManager: Self.dbManager
13511351
)
1352-
XCTAssertNil(error)
1352+
if #available(macOS 13.0, *) {
1353+
XCTAssertEqual(error as? NSFileProviderError, NSFileProviderError(.excludedFromSync))
1354+
} else {
1355+
XCTAssertNil(error)
1356+
}
13531357
XCTAssertNotNil(resultItem)
13541358
XCTAssertEqual(resultItem?.metadata.fileName, "error.bak")
13551359
}

0 commit comments

Comments
 (0)