Skip to content

fix(collections): keep collection folders recognisable after MO2 saves meta.ini or the user renames them - #100

Merged
MotherSphere merged 6 commits into
mainfrom
fix/collections-mo2-markers
Oct 16, 2026
Merged

MotherSphere merged 6 commits into
mainfrom
fix/collections-mo2-markers

Conversation

@MotherSphere

Copy link
Copy Markdown
Member

Two collection defects confirmed in the review of #72 and left open there, plus the guide note that #72's backup fix (<name>_backup) was missing.

MO2 saving meta.ini

MO2 writes meta.ini through QSettings, which reads an unquoted value with a comma as a string list and saves it back joined with ", " and without its quotes. After any MO2 edit of a collection member (a note, a category, a colour), eidosCollectionOwner=["owner","key"] came back as [owner, key]. Eidos no longer saw the folder as owned: a new revision skipped the takeover, installed a second copy beside the old one and did not name it. eidosCollectionIniFragments had the same problem, and an install warning MO2 rewrote showed doubled backslashes.

  • The marker and the fragment record are written quoted and escaped the way QSettings writes a string with a comma, which it saves back byte for byte.
  • Reading accepts that shape, the bare JSON 1.19.3 and earlier wrote (read as JSON first), and the list QSettings made of it, with an item containing ", " kept whole. Qt 5 (MO2 2.4) \xNN byte escapes are decoded as UTF-8.
  • collection_owner() returns the decoded marker; a cleared marker reads as no owner.

Renamed member folders

A member folder the user renamed was found by its recorded name only, so a new revision neither took it over nor named it as a leftover, and going back or re-running a revision installed a second copy under the old name. The takeover, going back and reserve_folder now follow a missing folder to the one carrying its marker (never a _backup, a separator, or a marker two folders share).

Guide

usage.md and its 15 translations say that a replaced member folder you had changed is first kept as <name>_backup, which is never loaded into the game, and named in the report.

Checks

  • cargo fmt --all -- --check, clippy (Rust 1.99.0, -D warnings) and cargo check on the 1.89 MSRV: clean.
  • Tests outside the GUI: 1283 pass. GUI: 406 pass; nif_preview::tests::real_nif_helper_parses_both_native_fixtures_and_rejects_invalid_input needs the native helper CI builds.
  • New tests fail without their fix: QSettings shapes of all three keys, a renamed member and leftover, a marker two folders share, going back and re-running after a rename, a member whose meta.ini MO2 saved.
  • An adversarial review of the first commit found the bare-JSON item split, the Qt 5 escapes and the going-back gap; all three are fixed in the last commit.

…rom release-please's output

The 1.19.2 release PR was merged with Cargo.toml at 1.19.2 and Cargo.lock
still at 1.19.1, so every --locked build on main fails and the 1.19.2
release stayed a draft without binaries.

The lock sync looked the release PR up by its "autorelease: pending" label.
One second after release-please opened PR #97 and labelled it, that lookup
came back empty, so the sync never ran. The step now also takes the PRs
release-please reports opening or updating in this run, and keeps the label
lookup for a PR it left unchanged, so a missed sync is still retried.

Bring the workspace members' versions in Cargo.lock to 1.19.2.
…s meta.ini or the user renames them

MO2 saves meta.ini through QSettings, which reads an unquoted value with a
comma as a string list and writes it back joined with ", " and without its
quotes. The owner marker eidosCollectionOwner=["owner","key"] came back as
[owner, key], so after any MO2 edit of a collection member (a note, a
category) Eidos no longer saw the folder as owned: a new revision skipped
the takeover, installed a second copy and did not name the old one. The
eidosCollectionIniFragments record had the same problem, and an install
warning MO2 rewrote showed its backslashes doubled.

The marker and the fragment record are now written quoted and escaped the
way QSettings writes a string with a comma, which it saves back byte for
byte. Reading accepts that shape, the bare JSON older versions wrote, and
the list QSettings made of it. collection_owner() returns the decoded
marker, and a cleared marker reads as no owner.

A member folder the user renamed was found by its recorded name only, so a
new revision neither took it over nor named it as a leftover. The takeover
now looks such a folder up by its marker (never a _backup or a separator,
and never a marker two folders share).
…ck and on a re-run

Review of the marker decoding found that it ran the QSettings decoder before
trying JSON, so a marker Eidos 1.19.2 or earlier wrote as bare JSON lost an
item boundary when an item held ", " (a name-keyed member such as
"Presets, Outfits", or a fragment named "Foo, Bar.ini"). The folder then read
as not owned, and a fragment record could name a file the user added.

- Bare JSON is now read as JSON first. The QSettings decoder keeps its items
  apart, so the list it makes of that JSON keeps an item with a comma whole,
  and one such item alone stays one name.
- Qt 5 (MO2 2.4) writes each UTF-8 byte above 0x7E as its own \xNN escape;
  a run of those is decoded as UTF-8 again.
- A folder this revision recorded that no longer exists no longer blocks the
  takeover from following the renamed one, so going back after a rename
  works, and a re-run reserves the renamed folder by its marker instead of
  creating a second one under the old name.
- The rename lookup only scans mods/ when the recorded folder is missing or
  unmarked.
@MotherSphere
MotherSphere merged commit 856e962 into main Oct 16, 2026
9 checks passed
@MotherSphere
MotherSphere deleted the fix/collections-mo2-markers branch October 16, 2026 14:29
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant