mirror of
https://github.com/beetbox/beets.git
synced 2025-12-15 21:14:19 +01:00
fix copying destination for full-album imports
This commit is contained in:
parent
e478ae740d
commit
11c5b15c8d
4 changed files with 70 additions and 13 deletions
|
|
@ -385,7 +385,7 @@ class Item(object):
|
|||
|
||||
# Dealing with files themselves.
|
||||
|
||||
def move(self, library, copy=False):
|
||||
def move(self, library, copy=False, in_album=False):
|
||||
"""Move the item to its designated location within the library
|
||||
directory (provided by destination()). Subdirectories are
|
||||
created as needed. If the operation succeeds, the item's path
|
||||
|
|
@ -393,6 +393,11 @@ class Item(object):
|
|||
|
||||
If copy is True, moving the file is copied rather than moved.
|
||||
|
||||
If in_album is True, then the track is treated as part of an
|
||||
album even if it does not yet have an album_id associated with
|
||||
it. (This allows items to be moved before they are added to the
|
||||
database, a performance optimization.)
|
||||
|
||||
Passes on appropriate exceptions if directories cannot be created
|
||||
or moving/copying fails.
|
||||
|
||||
|
|
@ -400,7 +405,7 @@ class Item(object):
|
|||
library.save() after this method in order to keep on-disk data
|
||||
consistent.
|
||||
"""
|
||||
dest = library.destination(self)
|
||||
dest = library.destination(self, in_album=in_album)
|
||||
|
||||
# Create necessary ancestry for the move.
|
||||
_mkdirall(dest)
|
||||
|
|
@ -908,14 +913,15 @@ class Library(BaseLibrary):
|
|||
self.conn.executescript(setup_sql)
|
||||
self.conn.commit()
|
||||
|
||||
def destination(self, item, pathmod=None):
|
||||
def destination(self, item, pathmod=None, in_album=False):
|
||||
"""Returns the path in the library directory designated for item
|
||||
item (i.e., where the file ought to be).
|
||||
item (i.e., where the file ought to be). in_album forces the
|
||||
item to be treated as part of an album.
|
||||
"""
|
||||
pathmod = pathmod or os.path
|
||||
|
||||
# Use a path format based on the album type, if available.
|
||||
if not item.album_id:
|
||||
if not item.album_id and not in_album:
|
||||
# Singleton track. Never use the "album" formats.
|
||||
if 'singleton' in self.path_formats:
|
||||
path_format = self.path_formats['singleton']
|
||||
|
|
|
|||
|
|
@ -563,7 +563,7 @@ def apply_choices(lib, copy, write, art, delete, progress):
|
|||
for item in task.items]
|
||||
for item in task.items:
|
||||
if copy:
|
||||
item.move(lib, True)
|
||||
item.move(lib, True, task.choice_flag != CHOICE_TRACKS)
|
||||
if write and task.choice_flag == CHOICE_ALBUM:
|
||||
item.write()
|
||||
|
||||
|
|
@ -621,7 +621,7 @@ def simple_import(lib, paths, copy, delete, resume):
|
|||
if delete:
|
||||
old_paths = [os.path.realpath(item.path) for item in task.items]
|
||||
for item in task.items:
|
||||
item.move(lib, True)
|
||||
item.move(lib, True, True)
|
||||
|
||||
album = lib.add_album(task.items, True)
|
||||
lib.save()
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
"""Some common functionality for beets' test cases."""
|
||||
import time
|
||||
import sys
|
||||
import os
|
||||
|
||||
# Mangle the search path to include the beets sources.
|
||||
sys.path.insert(0, '..')
|
||||
|
|
@ -126,3 +127,15 @@ class DummyIO(object):
|
|||
def restore(self):
|
||||
sys.stdin = sys.__stdin__
|
||||
sys.stdout = sys.__stdout__
|
||||
|
||||
|
||||
# Mixin for additional assertions.
|
||||
|
||||
class ExtraAsserts(object):
|
||||
def assertExists(self, path):
|
||||
self.assertTrue(os.path.exists(path),
|
||||
'file does not exist: %s' % path)
|
||||
|
||||
def assertNotExists(self, path):
|
||||
self.assertFalse(os.path.exists(path),
|
||||
'file exists: %s' % path)
|
||||
|
|
|
|||
|
|
@ -130,15 +130,21 @@ class ImportTest(unittest.TestCase):
|
|||
paths = self._run_import(['sometrack'], delete=True)
|
||||
self.assertFalse(os.path.exists(paths[0]))
|
||||
|
||||
class ImportApplyTest(unittest.TestCase):
|
||||
class ImportApplyTest(unittest.TestCase, _common.ExtraAsserts):
|
||||
def setUp(self):
|
||||
self.libdir = os.path.join('rsrc', 'testlibdir')
|
||||
os.mkdir(self.libdir)
|
||||
self.lib = library.Library(':memory:', self.libdir)
|
||||
self.lib.path_formats = {
|
||||
'default': 'one',
|
||||
'comp': 'two',
|
||||
'singleton': 'three',
|
||||
}
|
||||
|
||||
self.srcpath = os.path.join(self.libdir, 'srcfile.mp3')
|
||||
shutil.copy(os.path.join('rsrc', 'full.mp3'), self.srcpath)
|
||||
self.i = library.Item.from_path(self.srcpath)
|
||||
self.i.comp = False
|
||||
|
||||
trackinfo = {'title': 'one', 'artist': 'some artist',
|
||||
'track': 1, 'length': 1, 'id': 'trackid'}
|
||||
|
|
@ -155,24 +161,56 @@ class ImportApplyTest(unittest.TestCase):
|
|||
def tearDown(self):
|
||||
shutil.rmtree(self.libdir)
|
||||
|
||||
def call_apply(self, coro, items, info):
|
||||
def _call_apply(self, coro, items, info):
|
||||
task = commands.ImportTask(None, None, None)
|
||||
task.set_choice((info, items))
|
||||
coro.send(task)
|
||||
|
||||
def _call_apply_choice(self, coro, items, choice):
|
||||
task = commands.ImportTask(None, None, items)
|
||||
task.set_choice(choice)
|
||||
coro.send(task)
|
||||
|
||||
def test_apply_no_delete(self):
|
||||
coro = commands.apply_choices(self.lib, True, False, False,
|
||||
False, False)
|
||||
coro.next() # Prime coroutine.
|
||||
self.call_apply(coro, [self.i], self.info)
|
||||
self.assertTrue(os.path.exists(self.srcpath))
|
||||
self._call_apply(coro, [self.i], self.info)
|
||||
self.assertExists(self.srcpath)
|
||||
|
||||
def test_apply_with_delete(self):
|
||||
coro = commands.apply_choices(self.lib, True, False, False,
|
||||
True, False)
|
||||
coro.next() # Prime coroutine.
|
||||
self.call_apply(coro, [self.i], self.info)
|
||||
self.assertFalse(os.path.exists(self.srcpath))
|
||||
self._call_apply(coro, [self.i], self.info)
|
||||
self.assertNotExists(self.srcpath)
|
||||
|
||||
def test_apply_asis_uses_album_path(self):
|
||||
coro = commands.apply_choices(self.lib, True, False, False,
|
||||
False, False)
|
||||
coro.next() # Prime coroutine.
|
||||
self._call_apply_choice(coro, [self.i], commands.CHOICE_ASIS)
|
||||
self.assertExists(
|
||||
os.path.join(self.libdir, self.lib.path_formats['default']+'.mp3')
|
||||
)
|
||||
|
||||
def test_apply_match_uses_album_path(self):
|
||||
coro = commands.apply_choices(self.lib, True, False, False,
|
||||
False, False)
|
||||
coro.next() # Prime coroutine.
|
||||
self._call_apply(coro, [self.i], self.info)
|
||||
self.assertExists(
|
||||
os.path.join(self.libdir, self.lib.path_formats['default']+'.mp3')
|
||||
)
|
||||
|
||||
def test_apply_as_tracks_uses_singleton_path(self):
|
||||
coro = commands.apply_choices(self.lib, True, False, False,
|
||||
False, False)
|
||||
coro.next() # Prime coroutine.
|
||||
self._call_apply_choice(coro, [self.i], commands.CHOICE_TRACKS)
|
||||
self.assertExists(
|
||||
os.path.join(self.libdir, self.lib.path_formats['singleton']+'.mp3')
|
||||
)
|
||||
|
||||
class DuplicateCheckTest(unittest.TestCase):
|
||||
def setUp(self):
|
||||
|
|
|
|||
Loading…
Reference in a new issue