Skip to content
Merged
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
7 changes: 6 additions & 1 deletion PotassiumProviderCore/KDriveModels.swift
Original file line number Diff line number Diff line change
Expand Up @@ -514,13 +514,16 @@ public enum KDriveConflictFilename {

public enum KDriveItemIdentifier: Equatable, Hashable, Sendable {
case root
case workingSet
case trash
case item(Int)

public init(rawValue: String) throws {
switch rawValue {
case "NSFileProviderRootContainerItemIdentifier":
self = .root
case "NSFileProviderWorkingSetContainerItemIdentifier":
self = .workingSet
case "NSFileProviderTrashContainerItemIdentifier":
self = .trash
default:
Expand All @@ -543,7 +546,7 @@ public enum KDriveItemIdentifier: Equatable, Hashable, Sendable {
switch self {
case .root:
return rootFileID
case .trash:
case .workingSet, .trash:
return nil
case .item(let id):
return id
Expand All @@ -554,6 +557,8 @@ public enum KDriveItemIdentifier: Equatable, Hashable, Sendable {
switch self {
case .root:
return "NSFileProviderRootContainerItemIdentifier"
case .workingSet:
return "NSFileProviderWorkingSetContainerItemIdentifier"
case .trash:
return "NSFileProviderTrashContainerItemIdentifier"
case .item(let id):
Expand Down
9 changes: 7 additions & 2 deletions doc/FILE_PROVIDER_LIFECYCLE.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,12 +48,17 @@ Behavior:

- `.rootContainer` returns a synthetic `FileProviderItem` from
`ProviderDomainConfiguration`.
- Other identifiers are parsed as `KDriveItemIdentifier.item(fileID)`.
- `.workingSet` is a virtual enumeration container, not a kDrive item. Metadata
lookup returns `.noSuchItem` immediately without loading a runtime, making a
remote request, or recording an expected failure activity.
- Other identifiers are parsed as `KDriveItemIdentifier`; only identifiers with
a concrete kDrive file ID proceed to remote metadata lookup.
- The extension calls `PotassiumKDriveService.item(...)`, which uses
`KDriveService.getFile(...)`.
- The result is wrapped as `FileProviderItem`.

SQLite: not touched.
SQLite: successful lookups do not update snapshots. The expected `.workingSet`
rejection is not written to the activity audit.

## `fetchContents`

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,14 @@ public final class PotassiumFileProviderExtension: NSObject, NSFileProviderRepli
lifecycle.start { lifecycle in
var runtime: FileProviderRuntime?
do {
if identifier == .workingSet {
FileProviderLog.replicatedExtension.debug("working set is a virtual enumeration container; return noSuchItem for metadata lookup")
await lifecycle.finish(markProgressComplete: false) {
completionHandler(nil, NSFileProviderError(.noSuchItem))
}
return
}

let loadedRuntime = try await FileProviderRuntime.load(domain: self.domain)
runtime = loadedRuntime
if identifier == .rootContainer {
Expand Down Expand Up @@ -640,7 +648,8 @@ public final class PotassiumFileProviderExtension: NSObject, NSFileProviderRepli
if parentIdentifier == .rootContainer {
return runtime.configuration.rootFileID
}
guard parentIdentifier != .trashContainer else {
guard parentIdentifier != .trashContainer,
parentIdentifier != .workingSet else {
throw NSFileProviderError(.cannotSynchronize)
}
return try KDriveItemIdentifier(rawValue: parentIdentifier.rawValue).fileID(rootFileID: runtime.configuration.rootFileID)
Expand Down
4 changes: 4 additions & 0 deletions potassiumProviderTests/potassiumProviderTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -1138,11 +1138,15 @@ struct PotassiumProviderCoreTests {

@Test func itemIdentifierParsesFileProviderAndKDriveValues() throws {
#expect(try KDriveItemIdentifier(rawValue: "NSFileProviderRootContainerItemIdentifier") == .root)
#expect(try KDriveItemIdentifier(rawValue: "NSFileProviderWorkingSetContainerItemIdentifier") == .workingSet)
#expect(try KDriveItemIdentifier(rawValue: "NSFileProviderTrashContainerItemIdentifier") == .trash)
#expect(try KDriveItemIdentifier(rawValue: "123") == .item(123))
#expect(KDriveItemIdentifier.workingSet.rawValue == "NSFileProviderWorkingSetContainerItemIdentifier")
#expect(KDriveItemIdentifier.item(456).rawValue == "456")
#expect(KDriveItemIdentifier.root.fileID == ProviderConstants.defaultRootFileID)
#expect(KDriveItemIdentifier.root.fileID(rootFileID: 999) == 999)
#expect(KDriveItemIdentifier.workingSet.fileID == nil)
#expect(KDriveItemIdentifier.trash.fileID == nil)
#expect(throws: KDriveItemIdentifierError.invalid("not-a-number")) {
try KDriveItemIdentifier(rawValue: "not-a-number")
}
Expand Down