From 66d02bc289f199948642bdd3c8bd3b1309ffcf8e Mon Sep 17 00:00:00 2001 From: Adrian Sampson Date: Sat, 15 Nov 2014 12:41:40 -0800 Subject: [PATCH] Add link parameter to Item.move (#710) --- beets/importer.py | 2 +- beets/library.py | 13 +++++++------ test/test_files.py | 14 ++++++++++++++ test/test_importer.py | 31 ++++++++++++++++++++++--------- 4 files changed, 44 insertions(+), 16 deletions(-) diff --git a/beets/importer.py b/beets/importer.py index 526ac495b..16a2b123b 100644 --- a/beets/importer.py +++ b/beets/importer.py @@ -215,8 +215,8 @@ class ImportSession(object): iconfig['copy'] = False iconfig['link'] = False elif iconfig['link']: + iconfig['copy'] = False iconfig['move'] = False - iconfig['link'] = False # Only delete when copying. if not iconfig['copy']: diff --git a/beets/library.py b/beets/library.py index d20ecb067..5c702c053 100644 --- a/beets/library.py +++ b/beets/library.py @@ -580,13 +580,14 @@ class Item(LibModel): self._db._memotable = {} - def move(self, copy=False, basedir=None, with_album=True): + def move(self, copy=False, link=False, basedir=None, with_album=True): """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 field is updated to reflect the new location. - If copy is True, moving the file is copied rather than moved. + If `copy` is true, moving the file is copied rather than moved. + Similarly, `link` creates a symlink instead. basedir overrides the library base directory for the destination. @@ -608,7 +609,7 @@ class Item(LibModel): # Perform the move and store the change. old_path = self.path - self.move_file(dest, copy) + self.move_file(dest, copy, link) self.store() # If this item is in an album, move its art. @@ -846,7 +847,7 @@ class Album(LibModel): util.prune_dirs(os.path.dirname(old_art), self._db.directory) - def move(self, copy=False, basedir=None): + def move(self, copy=False, link=False, basedir=None): """Moves (or copies) all items to their destination. Any album art moves along with them. basedir overrides the library base directory for the destination. The album is stored to the @@ -861,10 +862,10 @@ class Album(LibModel): # Move items. items = list(self.items()) for item in items: - item.move(copy, basedir=basedir, with_album=False) + item.move(copy, link, basedir=basedir, with_album=False) # Move art. - self.move_art(copy) + self.move_art(copy, link) self.store() def item_dir(self): diff --git a/test/test_files.py b/test/test_files.py index 1eb54ffa3..272a33fe7 100644 --- a/test/test_files.py +++ b/test/test_files.py @@ -121,6 +121,20 @@ class MoveTest(_common.TestCase): self.assertEqual(os.path.dirname(self.i.path), os.path.dirname(dest)) + def test_link_arrives(self): + self.i.move(link=True) + self.assertExists(self.dest) + self.assertTrue(os.path.islink(self.dest)) + self.assertEqual(os.readlink(self.dest), self.path) + + def test_link_does_not_depart(self): + self.i.move(link=True) + self.assertExists(self.path) + + def test_link_changes_path(self): + self.i.move(link=True) + self.assertEqual(self.i.path, util.normpath(self.dest)) + class HelperTest(_common.TestCase): def test_ancestry_works_on_file(self): diff --git a/test/test_importer.py b/test/test_importer.py index feafad923..4058e3ef6 100644 --- a/test/test_importer.py +++ b/test/test_importer.py @@ -39,10 +39,10 @@ class AutotagStub(object): autotagger returns. """ - NONE = 'NONE' - IDENT = 'IDENT' - GOOD = 'GOOD' - BAD = 'BAD' + NONE = 'NONE' + IDENT = 'IDENT' + GOOD = 'GOOD' + BAD = 'BAD' MISSING = 'MISSING' """Generate an album match for all but one track """ @@ -196,7 +196,7 @@ class ImportHelper(TestHelper): def _setup_import_session(self, import_dir=None, delete=False, threaded=False, copy=True, singletons=False, - move=False, autotag=True): + move=False, autotag=True, link=False): config['import']['copy'] = copy config['import']['delete'] = delete config['import']['timid'] = True @@ -205,6 +205,7 @@ class ImportHelper(TestHelper): config['import']['move'] = move config['import']['autotag'] = autotag config['import']['resume'] = False + config['import']['link'] = link self.importer = TestImportSession( self.lib, logfile=None, query=None, @@ -321,6 +322,18 @@ class NonAutotaggedImportTest(_common.TestCase, ImportHelper): self.importer.run() self.assertNotExists(os.path.join(self.import_dir, 'the_album')) + def test_import_link_arrives(self): + config['import']['link'] = True + self.importer.run() + for mediafile in self.import_media: + filename = os.path.join( + self.libdir, + 'Tag Artist', 'Tag Album', '%s.mp3' % mediafile.title + ) + self.assertExists(filename) + self.assertTrue(os.path.islink(filename)) + self.assertEqual(os.readlink(filename), mediafile.path) + class ImportZipTest(unittest.TestCase, ImportHelper): @@ -806,7 +819,7 @@ class GroupAlbumsImportTest(_common.TestCase, ImportHelper): def test_add_album_for_different_artist_and_different_album(self): self.import_media[0].artist = "Artist B" - self.import_media[0].album = "Album B" + self.import_media[0].album = "Album B" self.import_media[0].save() self.importer.run() @@ -826,7 +839,7 @@ class GroupAlbumsImportTest(_common.TestCase, ImportHelper): self.assertEqual(artists, set(['Album Artist', 'Tag Artist'])) def test_add_album_for_same_artist_and_different_album(self): - self.import_media[0].album = "Album B" + self.import_media[0].album = "Album B" self.import_media[0].save() self.importer.run() @@ -834,7 +847,7 @@ class GroupAlbumsImportTest(_common.TestCase, ImportHelper): self.assertEqual(albums, set(['Album B', 'Tag Album'])) def test_add_album_for_same_album_and_different_artist(self): - self.import_media[0].artist = "Artist B" + self.import_media[0].artist = "Artist B" self.import_media[0].save() self.importer.run() @@ -843,7 +856,7 @@ class GroupAlbumsImportTest(_common.TestCase, ImportHelper): def test_incremental(self): config['import']['incremental'] = True - self.import_media[0].album = "Album B" + self.import_media[0].album = "Album B" self.import_media[0].save() self.importer.run()