Refactor try_sync to also include moving

This will remove a bunch of duplication we currently have for moving files
*inside the library directory* when their metadata changes.
This commit is contained in:
Adrian Sampson 2016-01-08 14:56:52 -08:00
parent 36ad0cf70d
commit 963a66a40c
3 changed files with 32 additions and 27 deletions

View file

@ -630,20 +630,26 @@ class Item(LibModel):
log.error("{0}", exc)
return False
def try_sync(self, write=None):
"""Synchronize the item with the database and the media file
tags, updating them with this object's current state.
def try_sync(self, write, move, with_album=True):
"""Synchronize the item with the database and, possibly, updates its
tags on disk and its path (by moving the file).
By default, the current `path` for the item is used to write
tags. If `write` is `False`, no tags are written. If `write` is
a path, tags are written to that file instead.
`write` indicates whether to write new tags into the file. Similarly,
`move` controls whether the path should be updated. In the
latter case, files are *only* moved when they are inside their
library's directory (if any).
Similar to calling :meth:`write` and :meth:`store`.
Similar to calling :meth:`write`, :meth:`move`, and :meth:`store`
(conditionally).
"""
if write is True:
write = None
if write is not False:
self.try_write(path=write)
if write:
self.try_write()
if move:
# Check whether this file is inside the library directory.
if self._db and self._db.directory in util.ancestry(self.path):
log.debug('moving {0} to synchronize path',
util.displayable_path(self.path))
self.move(with_album=with_album)
self.store()
# Files themselves.
@ -1108,15 +1114,18 @@ class Album(LibModel):
item[key] = value
item.store()
def try_sync(self, write=True):
"""Synchronize the album and its items with the database and
their files by updating them with this object's current state.
def try_sync(self, write, move):
"""Synchronize the album and its items with the database.
Optionally, also write any new tags into the files and update
their paths.
`write` indicates whether to write tags to the item files.
`write` indicates whether to write tags to the item files, and
`move` controls whether files (both audio and album art) are
moved.
"""
self.store()
for item in self.items():
item.try_sync(bool(write))
item.try_sync(write, move)
# Query construction helpers.

View file

@ -1353,13 +1353,7 @@ def modify_items(lib, mods, dels, query, write, move, album, confirm):
# Apply changes to database and files
with lib.transaction():
for obj in changed:
if move:
cur_path = obj.path
if lib.directory in ancestry(cur_path): # In library?
log.debug(u'moving object {0}', displayable_path(cur_path))
obj.move()
obj.try_sync(write)
obj.try_sync(write, move)
def modify_parse_args(args):
@ -1510,7 +1504,9 @@ def write_items(lib, query, pretend, force):
changed = ui.show_model_changes(item, clean_item,
library.Item._media_tag_fields, force)
if (changed or force) and not pretend:
item.try_sync()
# We use `try_sync` here to keep the mtime up to date in the
# database.
item.try_sync(True, False)
def write_func(lib, opts, args):

View file

@ -220,7 +220,7 @@ class EditPlugin(plugins.BeetsPlugin):
# Save the new data.
if success:
self.save_write(objs)
self.save_changes(objs)
def edit_objects(self, objs, fields):
"""Dump a set of Model objects to a file as text, ask the user
@ -316,11 +316,11 @@ class EditPlugin(plugins.BeetsPlugin):
id = int(old_dict['id'])
apply(obj_by_id[id], new_dict)
def save_write(self, objs):
def save_changes(self, objs):
"""Save a list of updated Model objects to the database.
"""
# Save to the database and possibly write tags.
for ob in objs:
if ob._dirty:
self._log.debug('saving changes to {}', ob)
ob.try_sync(ui.should_write())
ob.try_sync(ui.should_write(), False)