A fully locked photo keeps its name where upstream's forced provider likely renames it #224

Closed
opened 2026-09-15 23:30:08 +02:00 by Claude · 1 comment
Collaborator

A photo whose metadata is fully locked keeps its name here. Upstream likely renames it from the picture's title.

Both sides

upstream/Emby.Photos/PhotoProvider.cs is an IForcedProvider, so it runs even when the item's metadata is locked. The only lock it checks is LockedFields.Contains(MetadataField.Name) before taking ImageTag.Title.

Ours holds the name in unprobed (crates/ephyra-app/src/scan/run/read.rs) whenever held.whole is set, meaning the item is locked outright, as well as when the name field is locked.

What differs

Take a photo with IsLocked set and no field-level Name lock, whose file carries a title. Upstream files the title as the name on the next refresh, and ours keeps the old name. The other photo columns are assigned outright on both.

Confidence

This is low: it is read from the provider's code, not measured. Measure it first in a container of its own, since locking an item is a write, then match the result. A scan test with a locked, titled photo is the one that can fail.

Found reviewing #209.

A photo whose metadata is fully locked keeps its name here. Upstream likely renames it from the picture's title. ## Both sides `upstream/Emby.Photos/PhotoProvider.cs` is an `IForcedProvider`, so it runs even when the item's metadata is locked. The only lock it checks is `LockedFields.Contains(MetadataField.Name)` before taking `ImageTag.Title`. Ours holds the name in `unprobed` (`crates/ephyra-app/src/scan/run/read.rs`) whenever `held.whole` is set, meaning the item is locked outright, as well as when the name field is locked. ## What differs Take a photo with `IsLocked` set and no field-level `Name` lock, whose file carries a title. Upstream files the title as the name on the next refresh, and ours keeps the old name. The other photo columns are assigned outright on both. ## Confidence This is low: it is read from the provider's code, not measured. Measure it first in a container of its own, since locking an item is a write, then match the result. A scan test with a locked, titled photo is the one that can fail. Found reviewing #209.
Author
Collaborator

Closing this the other way round: the premise was wrong, and ours was diverging in the opposite direction. Fixed on main at 76f368b8.

Measured. In a container of its own: a locked photo, renamed by hand, with its file then replaced by one carrying different tags, and a full refresh. Upstream kept the name, overview, rating and keywords. Unlocking and repeating the same refresh took all four. The source agrees: MetadataService.RefreshWithProviders runs the pre-refresh providers and then returns early on item.IsLocked, and PhotoProvider is a plain custom provider, so it does not run at all for a locked item.

So upstream does not rename a locked photo — and ours was applying every photo column except the name.

A row locked outright now takes nothing from its file. Width, height and the picture's hash come from what is already on record rather than from a fresh read, because dropping them outright would have deleted the locked photo's image row: the image write clears an item's rows before re-inserting them.

Test: a_locked_picture_takes_nothing_from_its_file, which swaps the file for one of a different size and a different hash and asserts neither moved.

Left: the image row's DateModified still follows the file.

Closing this the other way round: the premise was wrong, and ours was diverging in the opposite direction. Fixed on `main` at `76f368b8`. **Measured.** In a container of its own: a locked photo, renamed by hand, with its file then replaced by one carrying different tags, and a full refresh. Upstream **kept** the name, overview, rating and keywords. Unlocking and repeating the same refresh took all four. The source agrees: `MetadataService.RefreshWithProviders` runs the pre-refresh providers and then returns early on `item.IsLocked`, and `PhotoProvider` is a plain custom provider, so it does not run at all for a locked item. So upstream does not rename a locked photo — and ours was applying every photo column *except* the name. A row locked outright now takes nothing from its file. Width, height and the picture's hash come from what is already on record rather than from a fresh read, because dropping them outright would have deleted the locked photo's image row: the image write clears an item's rows before re-inserting them. Test: `a_locked_picture_takes_nothing_from_its_file`, which swaps the file for one of a different size and a different hash and asserts neither moved. Left: the image row's `DateModified` still follows the file.
Sign in to join this conversation.
No description provided.