mirror of
https://github.com/beetbox/beets.git
synced 2025-12-24 09:33:46 +01:00
destination option for "beet move" (also tests)
This commit is contained in:
parent
99b7cb8854
commit
45eeea343e
4 changed files with 126 additions and 14 deletions
|
|
@ -212,7 +212,7 @@ class Item(object):
|
|||
|
||||
# Dealing with files themselves.
|
||||
|
||||
def move(self, library, copy=False, in_album=False):
|
||||
def move(self, library, copy=False, in_album=False, basedir=None):
|
||||
"""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
|
||||
|
|
@ -225,14 +225,17 @@ class Item(object):
|
|||
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.
|
||||
basedir overrides the library base directory for the
|
||||
destination.
|
||||
|
||||
Passes on appropriate exceptions if directories cannot be
|
||||
created or moving/copying fails.
|
||||
|
||||
Note that one should almost certainly call store() and
|
||||
library.save() after this method in order to keep on-disk data
|
||||
consistent.
|
||||
"""
|
||||
dest = library.destination(self, in_album=in_album)
|
||||
dest = library.destination(self, in_album=in_album, basedir=basedir)
|
||||
|
||||
# Create necessary ancestry for the move.
|
||||
util.mkdirall(dest)
|
||||
|
|
@ -793,13 +796,15 @@ class Library(BaseLibrary):
|
|||
self.conn.executescript(setup_sql)
|
||||
self.conn.commit()
|
||||
|
||||
def destination(self, item, pathmod=None, in_album=False, fragment=False):
|
||||
def destination(self, item, pathmod=None, in_album=False,
|
||||
fragment=False, basedir=None):
|
||||
"""Returns the path in the library directory designated for item
|
||||
item (i.e., where the file ought to be). in_album forces the
|
||||
item to be treated as part of an album. fragment makes this
|
||||
method return just the path fragment underneath the root library
|
||||
directory; the path is also returned as Unicode instead of
|
||||
encoded as a bytestring.
|
||||
encoded as a bytestring. basedir can override the library's base
|
||||
directory for the destination.
|
||||
"""
|
||||
pathmod = pathmod or os.path
|
||||
|
||||
|
|
@ -859,7 +864,8 @@ class Library(BaseLibrary):
|
|||
if fragment:
|
||||
return subpath
|
||||
else:
|
||||
return normpath(os.path.join(self.directory, subpath))
|
||||
basedir = basedir or self.directory
|
||||
return normpath(os.path.join(basedir, subpath))
|
||||
|
||||
|
||||
# Main interface.
|
||||
|
|
@ -1154,14 +1160,17 @@ class Album(BaseAlbum):
|
|||
(self.id,)
|
||||
)
|
||||
|
||||
def move(self, copy=False):
|
||||
def move(self, copy=False, basedir=None):
|
||||
"""Moves (or copies) all items to their destination. Any
|
||||
album art moves along with them.
|
||||
album art moves along with them. basedir overrides the library
|
||||
base directory for the destination.
|
||||
"""
|
||||
basedir = basedir or self._library.directory
|
||||
|
||||
# Move items.
|
||||
items = list(self.items())
|
||||
for item in items:
|
||||
item.move(self._library, copy)
|
||||
item.move(self._library, copy, basedir=basedir)
|
||||
newdir = os.path.dirname(items[0].path)
|
||||
|
||||
# Move art.
|
||||
|
|
|
|||
|
|
@ -958,13 +958,13 @@ def move_items(lib, dest, query, copy, album):
|
|||
entity = 'album' if album else 'item'
|
||||
logging.info('%s %i %ss.' % (action, len(objs), entity))
|
||||
for obj in objs:
|
||||
old_path = obj.item_path() if album else obj.path
|
||||
old_path = obj.item_dir() if album else obj.path
|
||||
logging.debug('moving: %s' % old_path)
|
||||
|
||||
if album:
|
||||
obj.move(copy)
|
||||
obj.move(copy, basedir=dest)
|
||||
else:
|
||||
obj.move(lib, copy)
|
||||
obj.move(lib, copy, basedir=dest)
|
||||
lib.store(obj)
|
||||
lib.save()
|
||||
|
||||
|
|
|
|||
|
|
@ -45,17 +45,25 @@ class MoveTest(unittest.TestCase, _common.ExtraAsserts):
|
|||
self.i.album = 'two'
|
||||
self.i.title = 'three'
|
||||
self.dest = join(self.libdir, 'one', 'two', 'three.mp3')
|
||||
|
||||
self.otherdir = join(_common.RSRC, 'testotherdir')
|
||||
|
||||
def tearDown(self):
|
||||
if os.path.exists(self.path):
|
||||
os.remove(self.path)
|
||||
if os.path.exists(self.libdir):
|
||||
shutil.rmtree(self.libdir)
|
||||
if os.path.exists(self.otherdir):
|
||||
shutil.rmtree(self.otherdir)
|
||||
|
||||
def test_move_arrives(self):
|
||||
self.i.move(self.lib)
|
||||
self.assertExists(self.dest)
|
||||
|
||||
def test_move_to_custom_dir(self):
|
||||
self.i.move(self.lib, basedir=self.otherdir)
|
||||
self.assertExists(join(self.otherdir, 'one', 'two', 'three.mp3'))
|
||||
|
||||
def test_move_departs(self):
|
||||
self.i.move(self.lib)
|
||||
self.assertNotExists(self.path)
|
||||
|
|
@ -148,9 +156,13 @@ class AlbumFileTest(unittest.TestCase):
|
|||
touch(self.i.path)
|
||||
# Make an album.
|
||||
self.ai = self.lib.add_album((self.i,))
|
||||
# Alternate destination dir.
|
||||
self.otherdir = os.path.join(_common.RSRC, 'testotherdir')
|
||||
def tearDown(self):
|
||||
if os.path.exists(self.libdir):
|
||||
shutil.rmtree(self.libdir)
|
||||
if os.path.exists(self.otherdir):
|
||||
shutil.rmtree(self.otherdir)
|
||||
|
||||
def test_albuminfo_move_changes_paths(self):
|
||||
self.ai.album = 'newAlbumName'
|
||||
|
|
@ -177,7 +189,12 @@ class AlbumFileTest(unittest.TestCase):
|
|||
self.assertTrue(os.path.exists(oldpath))
|
||||
self.assertTrue(os.path.exists(self.i.path))
|
||||
|
||||
class ArtFileTest(unittest.TestCase):
|
||||
def test_albuminfo_move_to_custom_dir(self):
|
||||
self.ai.move(basedir=self.otherdir)
|
||||
self.lib.load(self.i)
|
||||
self.assert_('testotherdir' in self.i.path)
|
||||
|
||||
class ArtFileTest(unittest.TestCase, _common.ExtraAsserts):
|
||||
def setUp(self):
|
||||
# Make library and item.
|
||||
self.lib = beets.library.Library(':memory:')
|
||||
|
|
@ -194,9 +211,13 @@ class ArtFileTest(unittest.TestCase):
|
|||
self.art = self.lib.get_album(self.i).art_destination('something.jpg')
|
||||
touch(self.art)
|
||||
self.ai.artpath = self.art
|
||||
# Alternate destination dir.
|
||||
self.otherdir = os.path.join(_common.RSRC, 'testotherdir')
|
||||
def tearDown(self):
|
||||
if os.path.exists(self.libdir):
|
||||
shutil.rmtree(self.libdir)
|
||||
if os.path.exists(self.otherdir):
|
||||
shutil.rmtree(self.otherdir)
|
||||
|
||||
def test_art_deleted_when_items_deleted(self):
|
||||
self.assertTrue(os.path.exists(self.art))
|
||||
|
|
@ -215,6 +236,17 @@ class ArtFileTest(unittest.TestCase):
|
|||
newart = self.lib.get_album(self.i).art_destination(self.art)
|
||||
self.assertTrue(os.path.exists(newart))
|
||||
|
||||
def test_art_moves_with_album_to_custom_dir(self):
|
||||
# Move the album to another directory.
|
||||
self.ai.move(basedir=self.otherdir)
|
||||
self.lib.load(self.i)
|
||||
|
||||
# Art should be in new directory.
|
||||
self.assertNotExists(self.art)
|
||||
newart = self.lib.get_album(self.i).artpath
|
||||
self.assertExists(newart)
|
||||
self.assertTrue('testotherdir' in newart)
|
||||
|
||||
def test_setart_copies_image(self):
|
||||
newart = os.path.join(self.libdir, 'newart.jpg')
|
||||
touch(newart)
|
||||
|
|
|
|||
|
|
@ -199,6 +199,77 @@ class ModifyTest(unittest.TestCase):
|
|||
item.read()
|
||||
self.assertFalse('newAlbum' in item.path)
|
||||
|
||||
class MoveTest(unittest.TestCase, _common.ExtraAsserts):
|
||||
def setUp(self):
|
||||
self.io = _common.DummyIO()
|
||||
self.io.install()
|
||||
|
||||
self.libdir = os.path.join(_common.RSRC, 'testlibdir')
|
||||
os.mkdir(self.libdir)
|
||||
|
||||
self.itempath = os.path.join(self.libdir, 'srcfile')
|
||||
shutil.copy(os.path.join(_common.RSRC, 'full.mp3'), self.itempath)
|
||||
|
||||
# Add a file to the library but don't copy it in yet.
|
||||
self.lib = library.Library(':memory:', self.libdir)
|
||||
self.i = library.Item.from_path(self.itempath)
|
||||
self.lib.add(self.i, False)
|
||||
self.album = self.lib.add_album([self.i])
|
||||
|
||||
# Alternate destination directory.
|
||||
self.otherdir = os.path.join(_common.RSRC, 'testotherdir')
|
||||
|
||||
def tearDown(self):
|
||||
self.io.restore()
|
||||
shutil.rmtree(self.libdir)
|
||||
if os.path.exists(self.otherdir):
|
||||
shutil.rmtree(self.otherdir)
|
||||
|
||||
def _move(self, query=(), dest=None, copy=False, album=False):
|
||||
commands.move_items(self.lib, dest, query, copy, album)
|
||||
|
||||
def test_move_item(self):
|
||||
self._move()
|
||||
self.lib.load(self.i)
|
||||
self.assertTrue('testlibdir' in self.i.path)
|
||||
self.assertExists(self.i.path)
|
||||
self.assertNotExists(self.itempath)
|
||||
|
||||
def test_copy_item(self):
|
||||
self._move(copy=True)
|
||||
self.lib.load(self.i)
|
||||
self.assertTrue('testlibdir' in self.i.path)
|
||||
self.assertExists(self.i.path)
|
||||
self.assertExists(self.itempath)
|
||||
|
||||
def test_move_album(self):
|
||||
self._move(album=True)
|
||||
self.lib.load(self.i)
|
||||
self.assertTrue('testlibdir' in self.i.path)
|
||||
self.assertExists(self.i.path)
|
||||
self.assertNotExists(self.itempath)
|
||||
|
||||
def test_copy_album(self):
|
||||
self._move(copy=True, album=True)
|
||||
self.lib.load(self.i)
|
||||
self.assertTrue('testlibdir' in self.i.path)
|
||||
self.assertExists(self.i.path)
|
||||
self.assertExists(self.itempath)
|
||||
|
||||
def test_move_item_custom_dir(self):
|
||||
self._move(dest=self.otherdir)
|
||||
self.lib.load(self.i)
|
||||
self.assertTrue('testotherdir' in self.i.path)
|
||||
self.assertExists(self.i.path)
|
||||
self.assertNotExists(self.itempath)
|
||||
|
||||
def test_move_album_custom_dir(self):
|
||||
self._move(dest=self.otherdir, album=True)
|
||||
self.lib.load(self.i)
|
||||
self.assertTrue('testotherdir' in self.i.path)
|
||||
self.assertExists(self.i.path)
|
||||
self.assertNotExists(self.itempath)
|
||||
|
||||
class UpdateTest(unittest.TestCase, _common.ExtraAsserts):
|
||||
def setUp(self):
|
||||
self.io = _common.DummyIO()
|
||||
|
|
|
|||
Loading…
Reference in a new issue