Three folders the scan walk treats as leaves where upstream resolves through them #213

Closed
opened 2026-09-12 19:06:31 +02:00 by Claude · 1 comment
Collaborator

Three folders where upstream keeps walking and we stop. All three are one shape — the walk treats a directory as a leaf that upstream resolves through — and all three are pre-existing rather than introduced by #208, which is where they were found.

1. A directory below a Season

crates/ephyra-app/src/scan/tree/shows.rs makes every directory under a series a Season and reads nothing below it.

/tv/Show/Season 01/Bonus/{Show S01E02.mkv, track.mp3} upstream: SeasonResolver needs args.Parent is Series and MovieResolver bails on HasParent<Series>(), so FolderResolver (Last) claims Bonus — then EpisodeResolver reaches the file inside it, finding the season through parent.GetParents().OfType<Season>(). Upstream files Folder("Bonus") and an Episode; we file neither.

2. An extras folder beside a film that does not collapse

/movies/Double/{Alpha.mkv, Beta.mkv, Extras/Bonus.mkv}: because Double holds two films it keeps its own row, and upstream then files Folder("Extras") and Movie("Bonus") inside it — the DirectoryName extra rule is suppressed on that second pass, where fullDirectory == libraryRoot (upstream/Emby.Server.Implementations/Library/Resolvers/ExtraRuleResolver.cs:51). We drop the subtree.

An extras folder beside a film that does collapse is correctly not an item, which is the case the fixture covers today — hence the gap.

3. A series subfolder holding no video

upstream/Emby.Server.Implementations/Library/Resolvers/TV/SeasonResolver.cs:88-94 returns null when hasAnyVideo is false, falling through to Folder. We make every subdirectory of a series a Season, so a Artwork/ or Subs/ folder beside the seasons becomes one.

Why they are worth one issue

Each is a directory we treat as a leaf. The fix in all three is the same question — what the walk does below a node it has already claimed — and settling it once is cheaper than three times.

Verifying

cargo xtask reference gen-library-kinds covers all three: the tvshows tree has no season subfolder and no non-video folder under a series, and the movies tree has no extras beside a folder that keeps its row. Three entries, one run.

Found reviewing #208.

Three folders where upstream keeps walking and we stop. All three are one shape — the walk treats a directory as a leaf that upstream resolves through — and all three are pre-existing rather than introduced by #208, which is where they were found. ## 1. A directory below a `Season` `crates/ephyra-app/src/scan/tree/shows.rs` makes every directory under a series a `Season` and reads nothing below it. `/tv/Show/Season 01/Bonus/{Show S01E02.mkv, track.mp3}` upstream: `SeasonResolver` needs `args.Parent is Series` and `MovieResolver` bails on `HasParent<Series>()`, so `FolderResolver` (Last) claims `Bonus` — then `EpisodeResolver` reaches the file inside it, finding the season through `parent.GetParents().OfType<Season>()`. Upstream files `Folder("Bonus")` and an `Episode`; we file neither. ## 2. An extras folder beside a film that does not collapse `/movies/Double/{Alpha.mkv, Beta.mkv, Extras/Bonus.mkv}`: because `Double` holds two films it keeps its own row, and upstream then files `Folder("Extras")` and `Movie("Bonus")` inside it — the `DirectoryName` extra rule is suppressed on that second pass, where `fullDirectory == libraryRoot` (`upstream/Emby.Server.Implementations/Library/Resolvers/ExtraRuleResolver.cs:51`). We drop the subtree. An extras folder beside a film that *does* collapse is correctly not an item, which is the case the fixture covers today — hence the gap. ## 3. A series subfolder holding no video `upstream/Emby.Server.Implementations/Library/Resolvers/TV/SeasonResolver.cs:88-94` returns null when `hasAnyVideo` is false, falling through to `Folder`. We make every subdirectory of a series a `Season`, so a `Artwork/` or `Subs/` folder beside the seasons becomes one. ## Why they are worth one issue Each is a directory we treat as a leaf. The fix in all three is the same question — what the walk does below a node it has already claimed — and settling it once is cheaper than three times. ## Verifying `cargo xtask reference gen-library-kinds` covers all three: the `tvshows` tree has no season subfolder and no non-video folder under a series, and the `movies` tree has no extras beside a folder that keeps its row. Three entries, one run. Found reviewing #208.
Author
Collaborator

Two of the three are fixed in fe6b37c8, landed on main at 53ac9c6c. The third was wrong about upstream.

1. A directory below a season. folder_at now walks through any folder under a series that is not itself a season, so Season 01/Bonus/Show S01E02.mkv files a Folder and the episode inside it, with the season number taken from the nearest season. The key agrees.

3. A series subfolder holding no video. is_a_season applies SeasonResolver's rule: named as a season, or else not episode-named and holding a video somewhere below. An Artwork/ folder beside the seasons is a Folder on both sides now.

2. An extras folder beside a film that does not collapse — not a bug. The key shows upstream files no row for movies/Double/Extras or Double/Extras/Bonus.mp4. The issue misread ExtraRuleResolver.cs:51: the DirectoryName rule is suppressed only when fullDirectory == libraryRoot, and here fullDirectory is …/Double/Extras, never the root. So Bonus.mp4 stays an extra, and it is an extra of a plain Folder, which carries none. Our walk drops extras directories, so both sides file nothing, and the row-by-row comparison would fail if either did.

For contrast, the key does file movies/Extras Beside (2011)/Extras/Bonus.mp4, owned by the film that collapsed into its folder — the case that already worked.

Two of the three are fixed in `fe6b37c8`, landed on `main` at `53ac9c6c`. The third was wrong about upstream. **1. A directory below a season.** `folder_at` now walks through any folder under a series that is not itself a season, so `Season 01/Bonus/Show S01E02.mkv` files a `Folder` and the episode inside it, with the season number taken from the nearest season. The key agrees. **3. A series subfolder holding no video.** `is_a_season` applies `SeasonResolver`'s rule: named as a season, or else not episode-named and holding a video somewhere below. An `Artwork/` folder beside the seasons is a `Folder` on both sides now. **2. An extras folder beside a film that does not collapse — not a bug.** The key shows upstream files **no row** for `movies/Double/Extras` or `Double/Extras/Bonus.mp4`. The issue misread `ExtraRuleResolver.cs:51`: the `DirectoryName` rule is suppressed only when `fullDirectory == libraryRoot`, and here `fullDirectory` is `…/Double/Extras`, never the root. So `Bonus.mp4` stays an extra, and it is an extra of a plain `Folder`, which carries none. Our walk drops extras directories, so both sides file nothing, and the row-by-row comparison would fail if either did. For contrast, the key does file `movies/Extras Beside (2011)/Extras/Bonus.mp4`, owned by the film that collapsed into its folder — the case that already worked.
Sign in to join this conversation.
No description provided.