Visitar URL original
fix(file-provider): scan into a new directory created inside a pinned folder by juliusvaart · Pull Request #11031 · nextcloud/desktop · GitHub
Skip to content

fix(file-provider): scan into a new directory created inside a pinned folder - #11031

Open
juliusvaart wants to merge 1 commit into
nextcloud:masterfrom
juliusvaart:macos/vf/pinned-new-folder
Open

juliusvaart wants to merge 1 commit into
nextcloud:masterfrom
juliusvaart:macos/vf/pinned-new-folder

Conversation

@juliusvaart

@juliusvaart juliusvaart commented Oct 7, 2026 •

Copy link
Copy Markdown
Contributor

Resolves

No issue filed. Found while testing on a live account.

Summary

A folder created on the server inside a folder set to "Always keep downloaded" appears locally, but the files in it stay invisible until the user opens it.

The working-set scan only descends into a changed child directory when something inside it is already materialised. That bound keeps a single push from walking entire never-visited subtrees on a sparse domain. A directory created on the server can never pass it, because nothing inside it is known yet. No later pass recovers the files either: the new row is not visitedDirectory, so it never seeds the scan.

The fix

"Always keep downloaded" asks for the whole subtree, so the scan now also descends when the child carries the pin. The bound still holds for every folder that is not pinned.

The pin is read from the stored row rather than from the metadata the read returns, because depth1ReadUpdateItemMetadatas applies the parent's pin to a new row on its own copy.

The change is 6 lines in Enumerator+WorkingSetScan.swift.

Tests

New RemoteChangePropagationTests.testNewFolderUnderAPinnedFolderIsCrawled: a pinned folder gains a new subfolder holding a file. The test checks that the subfolder is read and that the file is reported. Both assertions fail without the fix and pass with it. The seeding helper gained a keepDownloaded parameter for it.

Full suite, run locally with swift test on top of master (edf26f2b1b):

  • 390 XCTest (6 skipped, 0 failures) and 195 swift-testing tests, on master 3527955c09.
  • The only failures were the known timing-flaky EnumeratorTests cases (testWorkingSetChangesBatchMixingUpdatesAndDeletions, testWorkingSetChangesResumeAcrossNewEnumeratorInstances). They fail the same way on unmodified master: three runs there gave 1, 0 and 3 failures. A rerun of EnumeratorTests on this branch was clean.
  • swiftformat --lint and git diff --check are clean.

Checklist

AI (if applicable)

The code, tests and this description were written by Claude Code (Claude Opus 5.5) at my request, from a diagnosis of my own account's logs and database.

🤖 Generated with Claude Code

@github-actions

Copy link
Copy Markdown
Contributor

Hello there,
Thank you so much for taking the time and effort to create a pull request to our Nextcloud project.

We hope that the review process is going smooth and is helpful for you. We want to ensure your pull request is reviewed to your satisfaction. If you have a moment, our community management team would very much appreciate your feedback on your experience with this PR review process.

Your feedback is valuable to us as we continuously strive to improve our community developer experience. Please take a moment to complete our short survey by clicking on the following link: https://cloud.nextcloud.com/apps/forms/s/i9Ago4EQRZ7TWxjfmeEpPkf6

Thank you for contributing to Nextcloud and we hope to hear from you soon!

(If you believe you should not receive this message, you can add yourself to the blocklist.)

@camilasan camilasan added this to the 35.0.2 milestone Oct 27, 2026
@nilsding nilsding modified the milestones: 35.0.2, 35.0.3 Oct 30, 2026
@i2h3

i2h3 commented Oct 30, 2026

Copy link
Copy Markdown
Collaborator

@juliusvaart I am sorry it took so long. Please rebase your work onto the latest HEAD of master because an important and inevitable major change has landed (#11004). This changes a lot of call sites related to data persistence within the file provider extension. 🫣

This also applies to your other pull requests which I now want to focus on fully to finally get this whole sync performance problem complex resolved until version 36 (with gradual ports back to 35 based on progress).

Once pull requests have been merged, the ports back likely will cause conflicts and fail due to the changes introduced with #11004. We will deal with that later in due time. Because the changes of #11004 do not completely change architecture but mostly call site signatures, the back ports are expected to not cause double work.

… folder

The working-set scan only descends into a changed child directory when
something inside it is already materialised, which keeps one push from
walking whole never-visited subtrees on a sparse domain. A directory
created on the server inside a pinned folder can never pass that test,
because nothing inside it is known yet. The folder appeared locally while
the files in it stayed invisible until the user opened it, and no later
pass recovered them, because the row is not visitedDirectory and so never
seeds the scan.

"Always keep downloaded" asks for the whole subtree, so the scan now
descends when the child carries the pin. The bound holds everywhere else.

The pin is read from the stored row, because the read applies the
parent's pin to a new row on its own copy, so the metadata it hands back
still has the value from before.

Assisted-by: ClaudeCode:claude-opus-5-5
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Signed-off-by: Julius van der Vaart <julius@vanderva.art>
@juliusvaart
juliusvaart force-pushed the macos/vf/pinned-new-folder branch from 097ede2 to 5a34eda Compare October 30, 2026 09:25
@juliusvaart

Copy link
Copy Markdown
Contributor Author

Hi @i2h3,

Nice work on the GRDB move!

All nine my PR's are rebased onto master at 3527955, including the #11004 changes: #10733, #10809, #10810, #10811, #10812, #11024, #11025, #11030 and #11031. Each passes the full package suite and SwiftFormat lint. The two performance claims were re-measured on the SQLite store with the harness from #10733: #10809's working-set walk goes from 7.5–7.9 s to 1.9–2.0 s with the same 203 PROPFINDs, and #10811 still removes all 501 redundant row writes on a repeat enumeration (its duration gain is within noise, so I no longer claim one). The descriptions are updated to match.

@i2h3 i2h3 self-assigned this Oct 30, 2026
@i2h3 i2h3 added bug os: 🍎 macOS Apple macOS, formerly also known as OS X feature: 📁 file provider macOS File Provider Extension, more general also known as virtual file system. labels Oct 30, 2026
@i2h3

i2h3 commented Oct 30, 2026

Copy link
Copy Markdown
Collaborator

/backport to stable-35.0

@i2h3

i2h3 commented Oct 30, 2026

Copy link
Copy Markdown
Collaborator

I tested the branch by hand against a local server and also ran the PR's base commit as a control. On my machine, the behaviour described in the PR does not reproduce without the fix: the files in the new folder still appear and get downloaded, just about one minute later.

Setup

  • Client 35.0.50 (NextcloudDev), macOS (Darwin 27.2.0), local test server.
  • With the PR: 5a34eda062. Control: its parent 3527955c09.
  • Steps:
    1. Pin /Documents with "Always keep downloaded".
    2. In the web UI, copy Documents/Subfolder (which contains Subject.md) to Documents/Subfolder (1).
    3. Do not open the new folder in Finder.
  • I watched the dataless flags with stat -f %Sf and followed the extension and fileproviderd in the unified log.
  • Caveat: in the PR run, Documents and Documents/Subfolder had already been listed once before pinning. The control run used a fresh domain. Each variant ran once.

Observed timings, counted from the working-set change batch that reports Subfolder (1):

With PR Without PR
Extension reports the new folder's file 0 s not reported
fileproviderd lists the new folder on its own (FPFS enumeration of <ocId> for pid=… name=fileproviderd) +1 s +60 s
Subject.md downloaded +62 s +120 s

In both runs, the download was started by fileproviderd itself:

fetch-content(<ocId>) why:materialization|itemChangedRemotely|backgroundWork sched:background

This matches the contentPolicy:3 (downloadEagerlyAndKeepDownloaded) that the new folder inherits. fileproviderd lists the pinned folder itself and downloads its contents through its background-download activity, so a later pass does recover the files without this change.

What this means for the PR

  • On this setup, the change makes the files known about one background cycle earlier (~60 s). It doesn't fix files that never appear.
  • It is a valuable contribution nonetheless.
  • The unit test checks that the extension reads the folder. It can't cover what fileproviderd does afterwards, because the mock has no counterpart for it.

Question

Do you have logs from the account where you saw the files stay invisible? It would help to know whether fileproviderd ever listed the new folder there and started a fetch-content … backgroundWork. You could check with:
log stream --level debug --predicate 'subsystem == "com.nextcloud.desktopclient.FileProviderExt" OR process == "fileproviderd"'.
macOS can defer that background activity for much longer, for example on battery or in Low Power Mode. That could explain a difference from my results. Without such evidence, the change only makes the files appear about one background cycle sooner here, which doesn't justify it as a fix.

@i2h3 i2h3 modified the milestones: 35.0.3, 36.0.0 Oct 30, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

backport-request bug feature: 📁 file provider macOS File Provider Extension, more general also known as virtual file system. feedback-requested os: 🍎 macOS Apple macOS, formerly also known as OS X

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants