Skip to content

fix: enhance artist folder detection with directory traversal #4151

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
May 30, 2025

Conversation

deluan
Copy link
Member

@deluan deluan commented May 30, 2025

Problem

Fixed the bug where artist.jpg files in artist folders were not detected for new artists with only one album. This issue occurred because the original fromArtistFolder implementation only searched in the calculated artist folder without any fallback mechanism.

Specific scenario that was failing:

  • New artist with only 1 album
  • artist.jpg file present in the artist folder
  • File was not being picked up and displayed in the UI
  • Once a second album was added and library re-scanned, the artist.jpg file would then be recognized

Solution

Enhanced the fromArtistFolder function to implement directory traversal fallback for finding artist images:

Key Changes

  1. Directory Traversal: Search up to 3 levels (artist folder + 2 parent levels)
  2. Priority Order: Always prioritizes images found in closer directories
  3. Helper Function: Extracted findImageInFolder for cleaner code organization
  4. Boundary Checks: Proper filesystem boundary handling to prevent infinite traversal
  5. Error Handling: Continues searching even if individual files can't be opened
  6. Logging: Added trace and debug logging for better troubleshooting

Code Changes

  • Modified fromArtistFolder: Now searches multiple directory levels with fallback
  • Added findImageInFolder: Helper function for searching in a single directory
  • Maintained Compatibility: All existing functionality preserved

Tests

Added comprehensive test suite with 10 test scenarios covering:

  • ✅ Basic artist folder image detection
  • ✅ Parent directory fallback (single album artist scenario)
  • ✅ Grandparent directory fallback (two-level traversal)
  • ✅ Multiple level priority handling
  • ✅ Pattern matching edge cases
  • ✅ Filesystem boundary conditions
  • ✅ Error handling for file access issues
  • ✅ Complex glob patterns
  • Specific test for original single album artist issue

Compatibility

✅ Backward Compatibility

  • All existing functionality preserved
  • Default ArtistArtPriority patterns work unchanged: "artist.*, album/artist.*, external"
  • Multi-album artists continue to work as before
  • No performance regression for existing working cases

✅ Configuration Support

  • Works with all patterns: artist.*, artist.jpg, *.jpg, etc.
  • Integrates seamlessly with album/artist.* and external priorities
  • Respects existing caching and update mechanisms

Test Results

  • All existing tests pass: 49/49 specs in artwork suite ✅
  • New tests pass: All 10 new test scenarios ✅
  • Integration verified: Tested with full core package suite ✅
  • Linting passes: All security and code quality checks ✅

Benefits

  1. Fixes single album artist issue - Artist images now display correctly for new artists with one album
  2. Improves robustness - Better handling of various folder structures
  3. Maintains performance - Efficient search with early termination
  4. Enhanced logging - Better debugging and troubleshooting capabilities
  5. Future-proof - Handles edge cases and different directory layouts

Usage

The fix works automatically with the default configuration. When searching for artist images:

  1. First checks the calculated artist folder for artist.* files
  2. If none found, checks parent directory for artist.* files
  3. If still none found, checks grandparent directory for artist.* files
  4. Falls back to album images (album/artist.*) and external sources as configured

This ensures that artist.jpg files in artist folders are now properly detected for single album artists while maintaining all existing functionality.

Enhanced fromArtistFolder function to implement directory traversal fallback for finding artist images. The original implementation only searched in the calculated artist folder, which failed for single album artists where artist.jpg files were not detected.

Changes: Modified fromArtistFolder to search up to 3 directory levels (artist folder + 2 parent levels), extracted findImageInFolder helper function for cleaner code organization, added proper boundary checks to prevent infinite traversal, maintained backward compatibility with existing functionality.

Added comprehensive test suite with 10 test scenarios covering basic artist folder image detection, parent and grandparent directory fallback, multiple level priority handling, pattern matching edge cases, filesystem boundary conditions, error handling for file access issues, and specific test for original single album artist issue.

Fixed file permissions in tests to use 0600 for security compliance.

This fix ensures artist.jpg files are properly detected for single album artists while preserving all existing behavior for multi-album artists.
Copy link
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hello @deluan, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

Summary of Changes

Hello! Gemini here, providing a summary of this pull request to help everyone get up to speed quickly.

This PR addresses a bug where artist images (artist.jpg, etc.) located directly in the artist's main folder were not being detected for artists with only a single album. The original implementation of fromArtistFolder only searched the calculated artist folder, which in the single-album case might not have been the correct location relative to the image file.

The solution implemented here enhances the fromArtistFolder logic to perform a directory traversal fallback. It now searches for the specified artist image pattern not just in the initial folder, but also in its parent and grandparent directories (up to 3 levels total). This ensures that images placed higher up in the directory structure, common in single-album artist layouts, are correctly found. The search prioritizes images found in directories closer to the initial folder.

Highlights

  • Bug Fix: Fixes the specific issue where artist images in the artist folder were not detected for artists with only one album.
  • Directory Traversal Fallback: The fromArtistFolder function now searches up to 3 directory levels (initial folder + 2 parents) to find artist images.
  • Search Prioritization: Images found in directories closer to the initial artist folder are prioritized over those found further up the tree.
  • Code Refactoring: The logic for searching within a single folder has been extracted into a new helper function, findImageInFolder, improving code organization.
  • Comprehensive Testing: A new, extensive test suite with 10 scenarios has been added to cover various traversal depths, priority rules, edge cases (like filesystem boundaries and file errors), and specifically the original single-album artist issue.

Changelog

  • core/artwork/reader_artist.go
    • Refactored fromArtistFolder (lines 109-134 -> 109-124) to implement a loop for directory traversal, searching up to 3 levels.
    • Introduced a new helper function findImageInFolder (lines 127-149) which contains the core logic for globbing and opening an image file within a single specified directory.
    • fromArtistFolder now calls findImageInFolder iteratively for the current directory and its parents.
    • Added boundary checks (current != string(filepath.Separator)) to prevent infinite traversal.
    • Improved error handling within the search loop to continue searching even if opening a specific file fails.
  • core/artwork/reader_artist_test.go
    • Added necessary imports for io and os (lines 6-7).
    • Added a new Describe block specifically for testing the fromArtistFolder function (lines 114-383).
    • Included 10 distinct test scenarios covering successful finds at different depths, priority checks, multiple matches, no matches, filesystem root boundary, file access errors, glob patterns, and a specific test for the original single-album artist bug.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point in your pull request via creating an issue comment (i.e. comment on the pull request page) using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in issue comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist is currently in preview and may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments to provide feedback.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.


A folder deep, an image sought,
Up the tree, a path is wrought.
Three steps high, the search will go,
To find the art, and make it show.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This is a well-thought-out pull request that effectively addresses the bug with artist image detection for single-album artists. The introduction of directory traversal is a sensible solution, and the code changes are clear and well-structured. The extraction of findImageInFolder greatly improves readability. The accompanying tests are comprehensive and cover a wide range of scenarios, which is excellent.

I have a few suggestions for minor improvements, mostly around maintainability and test completeness. Overall, great work on this fix!

Summary of Findings

  • Hardcoded Traversal Depth: The directory traversal depth in fromArtistFolder is hardcoded (line 112 of core/artwork/reader_artist.go). Using a named constant would improve readability and maintainability.
  • Error Message Clarity: The error message in fromArtistFolder when no image is found (line 123 of core/artwork/reader_artist.go) could be more informative by mentioning that parent directories were also searched.
  • Test Completeness for Unreadable Files: The test case for handling unreadable files (core/artwork/reader_artist_test.go, lines 315-325) doesn't fully validate the 'continues searching' behavior if the first matched file in a directory is unreadable and a subsequent one is readable. Enhancing this test would provide greater confidence in this specific error handling path.

Merge Readiness

The pull request is in good shape and addresses an important bug. The implemented solution is robust and the tests are generally comprehensive. There are a few medium-severity suggestions related to maintainability and test completeness that I recommend addressing or discussing before merging. As I am an AI assistant, I am not authorized to approve pull requests; please ensure other reviewers approve these changes before merging.

Applied review suggestions from gemini-code-assist bot:

- Added maxArtistFolderTraversalDepth constant instead of hardcoded value 3

- Updated error message to mention that parent directories were also searched

- Enhanced test assertion to verify the improved error message
@deluan deluan requested a review from Copilot May 30, 2025 16:30
Copy link
Contributor

@Copilot Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

Enhances the fromArtistFolder logic to search parent directories (up to two levels) when no artist image is found in the initial folder, fixing cases where single‐album artists’ images were missed.

  • Introduce maxArtistFolderTraversalDepth and loop up to parent/grandparent directories
  • Extract findImageInFolder helper for single‐directory searches with error handling and logging
  • Expand tests to cover traversal depth, pattern matching, error cases, and the original single‐album bug

Reviewed Changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.

File Description
core/artwork/reader_artist.go Refactored fromArtistFolder to walk up directories; added findImageInFolder
core/artwork/reader_artist_test.go New test suite covering folder traversal, pattern edge cases, and error paths
Comments suppressed due to low confidence (2)

core/artwork/reader_artist.go:149

  • Pass the error under a named key (e.g., "error", err) instead of as a positional argument to maintain consistency in structured logs.
log.Warn(ctx, "Could not open cover art file", "file", filePath, err)

core/artwork/reader_artist_test.go:344

  • [nitpick] Make this test deterministic by explicitly asserting that an error occurs (e.g., Expect(err).To(HaveOccurred())) rather than handling both success and failure paths conditionally.
if err != nil {
    Expect(err.Error()).To(ContainSubstring("no matches"))
} else {
    Expect(reader).ToNot(BeNil())
    reader.Close()
}

Signed-off-by: Deluan <deluan@navidrome.org>
@deluan deluan merged commit 22c3486 into master May 30, 2025
20 checks passed
@deluan deluan deleted the fix/artist-folder-detection-single-album branch May 30, 2025 22:06
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