importadded: PermissionError thrown when converting from a readonly source
- Dominant language
- Python
- Stars
- 15.7k
- Forks
- 2.1k
- Avg merge
- 4d 21h
- Merged PRs (30d)
- 31
Description
### Problem
To avoid messing up my extensive flac collection, I have a cron job setting up the immutable flag on flac files that are older than X days. In the rare case where I have to retag old music with beets I'd then `chattr -i` the relevant files.
I have the importadded plugin enabled with both preserve_mtimes' and 'preserve_write_mtimes' set to 'yes'.
Today I needed to reconvert old files, so I ran `beet convert -y` on albums that had the immutable bit set; my assumption was that beets/importadded wouldn't need write permission to the original flac files, but it threw the following exception:
```
File "/home/user/.local/lib/python3.14/site-packages/beetsplug/importadded.py", line 149, in update_after_write_time
self.write_item_mtime(item, item.added)
~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^
File "/home/user/.local/lib/python3.14/site-packages/beetsplug/importadded.py", line 86, in write_item_mtime
self.write_file_mtime(util.syspath(item.path), mtime)
~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/user/.local/lib/python3.14/site-packages/beetsplug/importadded.py", line 79, in write_file_mtime
os.utime(util.syspath(path), (stat.st_atime, mtime))
~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
PermissionError: [Errno 1] Operation not permitted: '/01 somename.flac'
```
So - for some reason, importadded wants to write to the original flac file despite not needing it.
Looking at beetsplug/importadded.py, function `update_after_write_time(self, item, path)` actually doesn't use the 'path' argument and forcibly sets the time on 'item', rather than 'path' (which IIUC is the file that was just converted). So it seems that the right way would be to set the mtime on 'path' rather than 'item'. Replacing `self.write_item_mtime(item, item.added)` by the following fixed the issue:
```
self.write_file_mtime(util.syspath(path), item.added)
# update item.mtime only when 'path' is the item's own file, not a converted file
if path == item.path:
item.mtime = item.added
```
(It may be the wrong fix though, I'm not familiar with beets' code - so I'm not opening a PR)
### Setup
* OS: fedora 44
* Python version: 3.14.7
* beets version: 2.13.1 (but I checked the code of importadded - it's the same as in the current 'main' branch)
Contributor guide
Research direction
Start in beetsplug/importadded.py, especially update_after_write_time, write_item_mtime, and write_file_mtime, and reproduce the issue with beet convert -y on an immutable source file. Confirm that conversion no longer attempts to modify the original file and that the intended modification time is applied to the converted path.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- python
- Domain
- cli
- Issue type
- Bug
- Difficulty
- 2/5
- Estimated time
- 1-3 hours
- Activity status
- Active
- Clarity
- Clearly specified
- Newbie friendliness
- 78/100