mirror of
https://github.com/beetbox/beets.git
synced 2025-12-11 02:53:58 +01:00
Merge pull request #925 from silb/bug-911-importadded-reimport
Fixes bug #911
This commit is contained in:
commit
6f9abf4340
2 changed files with 59 additions and 21 deletions
|
|
@ -1,5 +1,7 @@
|
|||
"""Populate an items `added` and `mtime` field by using the file modification
|
||||
time (mtime) of the item's source file before import.
|
||||
"""Populate an item's `added` and `mtime` fields by using the file
|
||||
modification time (mtime) of the item's source file before import.
|
||||
|
||||
Reimported albums and items are skipped.
|
||||
"""
|
||||
|
||||
from __future__ import unicode_literals, absolute_import, print_function
|
||||
|
|
@ -26,6 +28,29 @@ class ImportAddedPlugin(BeetsPlugin):
|
|||
def check_config(task, session):
|
||||
config['importadded']['preserve_mtimes'].get(bool)
|
||||
|
||||
# item.id for new items that were reimported
|
||||
reimported_item_ids = None
|
||||
|
||||
# album.path for old albums that were replaced by a new reimported album
|
||||
replaced_album_paths = None
|
||||
|
||||
|
||||
def reimported_item(item):
|
||||
return item.id in reimported_item_ids
|
||||
|
||||
|
||||
def reimported_album(album):
|
||||
return album.path in replaced_album_paths
|
||||
|
||||
|
||||
@ImportAddedPlugin.listen('import_task_files')
|
||||
def record_reimported(task, session):
|
||||
global reimported_item_ids, replaced_album_paths
|
||||
reimported_item_ids = set([item.id for item, replaced_items
|
||||
in task.replaced_items.iteritems()
|
||||
if replaced_items])
|
||||
replaced_album_paths = set(task.replaced_albums.keys())
|
||||
|
||||
|
||||
def write_file_mtime(path, mtime):
|
||||
"""Write the given mtime to the destination path.
|
||||
|
|
@ -34,17 +59,13 @@ def write_file_mtime(path, mtime):
|
|||
os.utime(util.syspath(path),
|
||||
(stat.st_atime, mtime))
|
||||
|
||||
# key: item path in the library
|
||||
# value: the file mtime of the file the item was imported from
|
||||
item_mtime = dict()
|
||||
|
||||
|
||||
def write_item_mtime(item, mtime):
|
||||
"""Write the given mtime to an item's `mtime` field and to the mtime of the
|
||||
item's file.
|
||||
"""
|
||||
if mtime is None:
|
||||
log.warn(u"No mtime to be preserved for item {0}"
|
||||
log.warn(u"No mtime to be preserved for item '{0}'"
|
||||
.format(util.displayable_path(item.path)))
|
||||
return
|
||||
|
||||
|
|
@ -53,15 +74,16 @@ def write_item_mtime(item, mtime):
|
|||
item.mtime = mtime
|
||||
|
||||
|
||||
# key: item path in the library
|
||||
# value: the file mtime of the file the item was imported from
|
||||
item_mtime = dict()
|
||||
|
||||
|
||||
@ImportAddedPlugin.listen('before_item_moved')
|
||||
@ImportAddedPlugin.listen('item_copied')
|
||||
def record_import_mtime(item, source, destination):
|
||||
"""Record the file mtime of an item's path before import.
|
||||
"""Record the file mtime of an item's path before its import.
|
||||
"""
|
||||
if (source == destination):
|
||||
# Re-import of an existing library item?
|
||||
return
|
||||
|
||||
mtime = os.stat(util.syspath(source)).st_mtime
|
||||
item_mtime[destination] = mtime
|
||||
log.debug(u"Recorded mtime {0} for item '{1}' imported from '{2}'".format(
|
||||
|
|
@ -71,26 +93,37 @@ def record_import_mtime(item, source, destination):
|
|||
|
||||
@ImportAddedPlugin.listen('album_imported')
|
||||
def update_album_times(lib, album):
|
||||
if reimported_album(album):
|
||||
log.debug(u"Album '{0}' is reimported, skipping import of added dates"
|
||||
u" for the album and its items."
|
||||
.format(util.displayable_path(album.path)))
|
||||
return
|
||||
|
||||
album_mtimes = []
|
||||
for item in album.items():
|
||||
mtime = item_mtime[item.path]
|
||||
if mtime is not None:
|
||||
mtime = item_mtime.pop(item.path, None)
|
||||
if mtime:
|
||||
album_mtimes.append(mtime)
|
||||
if config['importadded']['preserve_mtimes'].get(bool):
|
||||
write_item_mtime(item, mtime)
|
||||
item.store()
|
||||
del item_mtime[item.path]
|
||||
|
||||
album.added = min(album_mtimes)
|
||||
log.debug(u"Import of album '{0}', selected album.added={1} from item"
|
||||
u" file mtimes.".format(album.album, album.added))
|
||||
album.store()
|
||||
|
||||
|
||||
@ImportAddedPlugin.listen('item_imported')
|
||||
def update_item_times(lib, item):
|
||||
mtime = item_mtime[item.path]
|
||||
if mtime is not None:
|
||||
if reimported_item(item):
|
||||
log.debug(u"Item '{0}' is reimported, skipping import of added "
|
||||
u"date.".format(util.displayable_path(item.path)))
|
||||
return
|
||||
mtime = item_mtime.pop(item.path, None)
|
||||
if mtime:
|
||||
item.added = mtime
|
||||
if config['importadded']['preserve_mtimes'].get(bool):
|
||||
write_item_mtime(item, mtime)
|
||||
log.debug(u"Import of item '{0}', selected item.added={1}"
|
||||
.format(util.displayable_path(item.path), item.added))
|
||||
item.store()
|
||||
del item_mtime[item.path]
|
||||
|
|
|
|||
|
|
@ -12,9 +12,9 @@ The ``item.added`` field is populated as follows:
|
|||
|
||||
* For singleton items with no album, ``item.added`` is set to the item's file
|
||||
mtime before it was imported.
|
||||
* For items that are part of an album, ``album.added`` and ``item.added`` is
|
||||
* For items that are part of an album, ``album.added`` and ``item.added`` are
|
||||
set to the oldest mtime of the files in the album before they were imported.
|
||||
The mtime of album directories are ignored.
|
||||
The mtime of album directories is ignored.
|
||||
|
||||
This plugin can optionally be configured to also preserve mtimes::
|
||||
|
||||
|
|
@ -31,3 +31,8 @@ File modification times are preserved as follows:
|
|||
|
||||
Note that there is no ``album.mtime`` field in the database and that the mtime
|
||||
of album directories on disk aren't preserved.
|
||||
|
||||
Reimport
|
||||
--------
|
||||
|
||||
This plugin will skip reimported singleton items and reimported albums and all of their items.
|
||||
|
|
|
|||
Loading…
Reference in a new issue