From 1af4f86c17f90920da9ffe48cc346c5f69dcfd78 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Domen=20Ko=C5=BEar?= Date: Thu, 5 Apr 2012 01:14:17 +0200 Subject: [PATCH] support move action when importing --- beets/importer.py | 10 +++++++--- beets/ui/commands.py | 11 +++++++++-- docs/reference/config.rst | 4 ++++ test/_common.py | 1 + test/test_importer.py | 30 ++++++++++++++++++++++++++---- test/test_ui.py | 2 +- 6 files changed, 48 insertions(+), 10 deletions(-) diff --git a/beets/importer.py b/beets/importer.py index 4d623e5ca..ccf2c354d 100644 --- a/beets/importer.py +++ b/beets/importer.py @@ -259,7 +259,7 @@ class ImportConfig(object): then never touched again. """ _fields = ['lib', 'paths', 'resume', 'logfile', 'color', 'quiet', - 'quiet_fallback', 'copy', 'write', 'art', 'delete', + 'quiet_fallback', 'copy', 'move', 'write', 'art', 'delete', 'choose_match_func', 'should_resume_func', 'threaded', 'autot', 'singletons', 'timid', 'choose_item_func', 'query', 'incremental', 'ignore', @@ -697,16 +697,20 @@ def apply_choices(config): # Move/copy files. task.old_paths = [item.path for item in items] for item in items: - if config.copy: + if config.copy or config.move: # If we're replacing an item, then move rather than # copying. old_path = item.path do_copy = not bool(replaced_items[item]) - lib.move(item, do_copy, task.is_album) + if config.move: + lib.move(item, False, task.is_album) + else: + lib.move(item, do_copy, task.is_album) if not do_copy: # If we moved the item, remove the now-nonexistent # file from old_paths. task.old_paths.remove(old_path) + if config.write and task.should_write_tags(): item.write() diff --git a/beets/ui/commands.py b/beets/ui/commands.py index 993869307..434f93632 100644 --- a/beets/ui/commands.py +++ b/beets/ui/commands.py @@ -87,6 +87,7 @@ def _showdiff(field, oldval, newval, color): # import: Autotagger and importer. DEFAULT_IMPORT_COPY = True +DEFAULT_IMPORT_MOVE = False DEFAULT_IMPORT_WRITE = True DEFAULT_IMPORT_DELETE = False DEFAULT_IMPORT_AUTOT = True @@ -598,7 +599,7 @@ def resolve_duplicate(task, config): # The import command. -def import_files(lib, paths, copy, write, autot, logpath, art, threaded, +def import_files(lib, paths, copy, move, write, autot, logpath, art, threaded, color, delete, quiet, resume, quiet_fallback, singletons, timid, query, incremental, ignore): """Import the files in the given list of paths, tagging each leaf @@ -655,6 +656,7 @@ def import_files(lib, paths, copy, write, autot, logpath, art, threaded, quiet = quiet, quiet_fallback = quiet_fallback, copy = copy, + move = move, write = write, art = art, delete = delete, @@ -686,6 +688,8 @@ import_cmd.parser.add_option('-c', '--copy', action='store_true', default=None, help="copy tracks into library directory (default)") import_cmd.parser.add_option('-C', '--nocopy', action='store_false', dest='copy', help="don't copy tracks (opposite of -c)") +import_cmd.parser.add_option('-m', '--move', action='store_true', + default=None, help="move tracks into library directory") import_cmd.parser.add_option('-w', '--write', action='store_true', default=None, help="write new metadata to files' tags (default)") import_cmd.parser.add_option('-W', '--nowrite', action='store_false', @@ -719,6 +723,9 @@ def import_func(lib, config, opts, args): copy = opts.copy if opts.copy is not None else \ ui.config_val(config, 'beets', 'import_copy', DEFAULT_IMPORT_COPY, bool) + move = opts.move if opts.move is not None else \ + ui.config_val(config, 'beets', 'import_move', + DEFAULT_IMPORT_MOVE, bool) write = opts.write if opts.write is not None else \ ui.config_val(config, 'beets', 'import_write', DEFAULT_IMPORT_WRITE, bool) @@ -768,7 +775,7 @@ def import_func(lib, config, opts, args): query = None paths = args - import_files(lib, paths, copy, write, autot, logpath, art, threaded, + import_files(lib, paths, copy, move, write, autot, logpath, art, threaded, color, delete, quiet, resume, quiet_fallback, singletons, timid, query, incremental, ignore) import_cmd.func = import_func diff --git a/docs/reference/config.rst b/docs/reference/config.rst index 3450f3ea3..b8d07395b 100644 --- a/docs/reference/config.rst +++ b/docs/reference/config.rst @@ -24,6 +24,10 @@ section header: directory when using ``beet import``. Defaults to ``yes``. Can be overridden with the ``-c`` and ``-C`` command-line options. +``import_move`` + Either ``yes`` or ``no``, indicating whether to move files into the library + directory when using ``beet import``. Defaults to ``no``. + ``import_write`` Either ``yes`` or ``no``, controlling whether metadata (e.g., ID3) tags are written to files when using ``beet import``. Defaults to ``yes``. The ``-w`` diff --git a/test/_common.py b/test/_common.py index d632df041..846f0de2b 100644 --- a/test/_common.py +++ b/test/_common.py @@ -82,6 +82,7 @@ def iconfig(lib, **kwargs): quiet = True, quiet_fallback = importer.action.SKIP, copy = True, + move = False, write = False, art = False, delete = False, diff --git a/test/test_importer.py b/test/test_importer.py index 935ba65df..57c6f20e3 100644 --- a/test/test_importer.py +++ b/test/test_importer.py @@ -69,7 +69,7 @@ class NonAutotaggedImportTest(unittest.TestCase): return realpath def _run_import(self, titles=TEST_TITLES, delete=False, threaded=False, - singletons=False): + singletons=False, move=False): # Make a bunch of tracks to import. paths = [] for i, title in enumerate(titles): @@ -86,7 +86,8 @@ class NonAutotaggedImportTest(unittest.TestCase): importer.run_import( lib=self.lib, paths=[os.path.dirname(paths[0])], - copy=True, + copy=not move, + move=move, write=True, autot=False, logfile=None, @@ -125,12 +126,33 @@ class NonAutotaggedImportTest(unittest.TestCase): filenames = set(os.listdir(album_folder)) destinations = set('%s.mp3' % title for title in TEST_TITLES) self.assertEqual(filenames, destinations) + def test_import_copy_arrives(self): - self._run_import() + paths = self._run_import() self._copy_arrives() + + for path in paths: + self.assertTrue(os.path.exists(path)) + def test_threaded_import_copy_arrives(self): - self._run_import(threaded=True) + paths = self._run_import(threaded=True) self._copy_arrives() + for path in paths: + self.assertTrue(os.path.exists(path)) + + def test_import_move(self): + paths = self._run_import(move=True) + self._copy_arrives() + + for path in paths: + self.assertFalse(os.path.exists(path)) + + def test_threaded_import_move(self): + paths = self._run_import(threaded=True, move=True) + self._copy_arrives() + + for path in paths: + self.assertFalse(os.path.exists(path)) def test_import_no_delete(self): paths = self._run_import(['sometrack'], delete=False) diff --git a/test/test_ui.py b/test/test_ui.py index 22b32d06f..13d82c030 100644 --- a/test/test_ui.py +++ b/test/test_ui.py @@ -470,7 +470,7 @@ class AutotagTest(unittest.TestCase): class ImportTest(unittest.TestCase): def test_quiet_timid_disallowed(self): self.assertRaises(ui.UserError, commands.import_files, - None, [], False, False, False, None, False, False, + None, [], False, False, False, False, None, False, False, False, False, True, False, None, False, True, None, False, [])