Skip to content

FwHeadless never clears untracked files, so settings a user deleted come back on every sync #2506

Description

@myieye

A FLEx user's deletion of a settings file cannot stick. FwHeadless re-commits the file on its next sync, indefinitely.

Measured on one production project, where the same reversal-index configuration under CachedSettings/ConfigurationSettings/ReversalIndex/ went through three full cycles:

when who what
Nov 2023 FLEx user created
Jun 2025 FLEx user deleted
Mar 2026 FwHeadless re-added
Mar 2026, four days later FLEx user deleted again
Jul 2026 FwHeadless re-added
Jul 2026, three weeks later FLEx user deleted again
Jul 2026, a week after that FwHeadless kept by its merge; present at the repo tip today

It is only UI configuration, so nothing was lost. But the loop is mechanical, it has run three times, and it will keep running.

Mechanism

FwHeadless's project directory is long-lived: it is the fwdata cache, and it survives between syncs. hg update never removes untracked files, so a copy of the file has been sitting in the working directory's ConfigurationSettings/ since it was first created, and no checkout will ever clear it.

FLExBridge then copies the settings folders into the tracked CachedSettings/ tree on every send/receive, and CachedSettings/ tracks files that ConfigurationSettings/ does not: several ReversalIndex/*.fwdictconfig files exist only under CachedSettings/ in that project's repository. So the stray gets committed through the cache each time, no matter how many times a user deletes it.

Same class of problem, not observed leaking yet: two WritingSystemStore/*.ldml files are also untracked in that directory. If those ever reach the cache, the container starts inventing writing systems for the project.

Why "purge untracked files" is the wrong fix

The untracked set in a real project directory:

fw.fwdata                             the project itself, reconstituted at checkout
fw.bak                                its backup
ConfigurationSettings/**              17 files, the actual leak
WritingSystemStore/*.ldml             2 files
SharedSettings/LexiconSettings.plsx

hg purge, or hg update -C with --clean semantics over the whole tree, deletes the project. Any fix has to name what it removes rather than removing what it does not recognise.

What needs deciding

A rule for which subtrees are project data, never touched, and which are container-local state that may be reconciled. Proposal to argue with:

  • Reconcile ConfigurationSettings/ only. It is regenerable UI configuration and never holds lexical data.
  • Delete a file there only when the tracked CachedSettings/ConfigurationSettings/ tree at the current revision does not contain it. That borrows FLExBridge's own idea of what belongs to the project instead of inventing a list we have to maintain.
  • Do not touch the project root, LinkedFiles/, WritingSystemStore/ or SharedSettings/ in this pass. Flag the writing-system strays separately.
  • Run it after checkout and before the pre-sync send/receive, so a stray never reaches the cache in the first place.

Tests

  • a stray file dropped into ConfigurationSettings/ is absent from the commit the sync produces
  • fw.fwdata, fw.bak, LinkedFiles/** and untracked WritingSystemStore/*.ldml all survive the reconcile
  • a settings file that is tracked under CachedSettings/ is not deleted
  • regression: a file deleted upstream and still present untracked locally does not reappear in the next commit

Notes

Found while auditing what the sync has written into fwdata across a project's full Mercurial history. It is the only thing the sync has re-added to a repository more than once, which is what makes it worth its own issue rather than a footnote.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Send & Receiveowner: Robin, KevinbugSomething isn't working📦 Lexboxissues related to any server side code, fw-headless included

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions