-
Notifications
You must be signed in to change notification settings - Fork 2k
fix(fetchart): prevent deletion of configured fallback cover art #6283
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
base: master
Are you sure you want to change the base?
fix(fetchart): prevent deletion of configured fallback cover art #6283
Conversation
|
Thank you for the PR! The changelog has not been updated, so here is a friendly reminder to check if you need to add an entry. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hey - I've left some high level feedback:
- The direct
candidate.path != self.fallbackcomparison may be fragile if paths differ in representation (e.g., symlinks, relative vs absolute, case differences on case-insensitive filesystems); consider normalizing and/or usingos.path.samefile(guarded for existence) to robustly detect the configured fallback file.
Prompt for AI Agents
Please address the comments from this code review:
## Overall Comments
- The direct `candidate.path != self.fallback` comparison may be fragile if paths differ in representation (e.g., symlinks, relative vs absolute, case differences on case-insensitive filesystems); consider normalizing and/or using `os.path.samefile` (guarded for existence) to robustly detect the configured fallback file.Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.
7959f50 to
af547e4
Compare
925da4b to
4ed7686
Compare
|
Thank you for the PR! The changelog has not been updated, so here is a friendly reminder to check if you need to add an entry. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hey - I've found 1 issue, and left some high level feedback:
- The
os.path.samefile(candidate.path, self.fallback)call will raise if either path doesn’t exist (e.g., missing or deleted fallback), so it would be safer to guard this with an existence check or wrap it in atry/except (OSError, FileNotFoundError)and default toFalseon error. - The new
removal_enabledexpression is getting fairly complex; consider extracting the fallback-protection logic into a small helper (e.g.,_is_prunable_source(candidate.path)) to make the intent clearer and easier to reason about.
Prompt for AI Agents
Please address the comments from this code review:
## Overall Comments
- The `os.path.samefile(candidate.path, self.fallback)` call will raise if either path doesn’t exist (e.g., missing or deleted fallback), so it would be safer to guard this with an existence check or wrap it in a `try`/`except (OSError, FileNotFoundError)` and default to `False` on error.
- The new `removal_enabled` expression is getting fairly complex; consider extracting the fallback-protection logic into a small helper (e.g., `_is_prunable_source(candidate.path)`) to make the intent clearer and easier to reason about.
## Individual Comments
### Comment 1
<location> `beetsplug/fetchart.py:1492-1497` </location>
<code_context>
if task in self.art_candidates:
candidate = self.art_candidates.pop(task)
- removal_enabled = self._is_source_file_removal_enabled()
+ removal_enabled = (
+ self._is_source_file_removal_enabled()
+ and candidate.path
+ and (
+ not self.fallback
+ or not os.path.samefile(candidate.path, self.fallback)
+ )
+ )
</code_context>
<issue_to_address>
**issue (bug_risk):** Guard `os.path.samefile` against missing or non-existent paths to avoid unexpected exceptions.
`os.path.samefile` may raise `FileNotFoundError`/`OSError` if `candidate.path` or `self.fallback` doesn’t exist, turning a previously skipped removal into an import-time crash. Please either wrap `samefile` in a helper that catches these exceptions and returns `False`, or guard it with an `os.path.exists` check on both paths before calling it.
</issue_to_address>Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## master #6283 +/- ##
=======================================
Coverage 68.77% 68.78%
=======================================
Files 140 140
Lines 18619 18624 +5
Branches 3054 3054
=======================================
+ Hits 12806 12811 +5
Misses 5165 5165
Partials 648 648
🚀 New features to boost your workflow:
|
bd9ff47 to
40c8480
Compare
|
Thank you for the PR! The changelog has not been updated, so here is a friendly reminder to check if you need to add an entry. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hey - I've found 1 issue
Prompt for AI Agents
Please address the comments from this code review:
## Individual Comments
### Comment 1
<location> `beetsplug/fetchart.py:1454` </location>
<code_context>
+ and self.fallback
+ and os.path.exists(candidate.path)
+ and os.path.exists(self.fallback)
+ and os.path.samefile(candidate.path, self.fallback)
+ )
+
</code_context>
<issue_to_address>
**issue (bug_risk):** Guard `os.path.samefile` call against a possible race between `exists` and `samefile`.
`os.path.exists` doesn’t fully protect against a race where `candidate.path` or `self.fallback` is removed or becomes unavailable between the `exists` calls and `samefile`, which can raise `FileNotFoundError` or `OSError`. Please wrap `os.path.samefile` in a `try/except (OSError, FileNotFoundError)` and return `False` on failure to make this resilient to concurrent file changes or external cleanup.
</issue_to_address>Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.
30ee0da to
a689d9c
Compare
a689d9c to
75c44e8
Compare
When `import.delete` or `import.move` is enabled, the `assign_art` method calls `task.prune(candidate.path)` unconditionally. This incorrectly deletes the configured `fetchart.fallback` file. Add explicit check to skip pruning when the candidate path matches the configured fallback.
Description
When
import.deleteorimport.moveis enabled, theassign_artmethod callstask.prune(candidate.path)unconditionally. This incorrectly deletes the configuredfetchart.fallbackfile. Add explicit check to skip pruning when the candidate path matches the configured fallback.To Do
docs/to describe it.) - not required because it's a fixup for 9ddddf4docs/changelog.rstto the bottom of one of the lists near the top of the document.) - not required because it's a fixup for 9ddddf4 and there was no release since then