diff --git a/beets/ui/commands.py b/beets/ui/commands.py index d35922c65..75cae066c 100644 --- a/beets/ui/commands.py +++ b/beets/ui/commands.py @@ -1194,31 +1194,33 @@ default_commands.append(update_cmd) # remove: Remove items from library, delete files. -def remove_items(lib, query, album, delete): +def remove_items(lib, query, album, delete, force): """Remove items matching query from lib. If album, then match and remove whole albums. If delete, also remove files from disk. """ # Get the matching items. items, albums = _do_query(lib, query, album) - # Prepare confirmation with user. - print_() - if delete: - fmt = u'$path - $title' - prompt = u'Really DELETE %i file%s (y/n)?' % \ - (len(items), 's' if len(items) > 1 else '') - else: - fmt = '' - prompt = u'Really remove %i item%s from the library (y/n)?' % \ - (len(items), 's' if len(items) > 1 else '') + # Confirm file removal if not forcing removal. + if not force: + # Prepare confirmation with user. + print_() + if delete: + fmt = u'$path - $title' + prompt = u'Really DELETE %i file%s (y/n)?' % \ + (len(items), 's' if len(items) > 1 else '') + else: + fmt = '' + prompt = u'Really remove %i item%s from the library (y/n)?' % \ + (len(items), 's' if len(items) > 1 else '') - # Show all the items. - for item in items: - ui.print_(format(item, fmt)) + # Show all the items. + for item in items: + ui.print_(format(item, fmt)) - # Confirm with user. - if not ui.input_yn(prompt, True): - return + # Confirm with user. + if not ui.input_yn(prompt, True): + return # Remove (and possibly delete) items. with lib.transaction(): @@ -1227,7 +1229,7 @@ def remove_items(lib, query, album, delete): def remove_func(lib, opts, args): - remove_items(lib, decargs(args), opts.album, opts.delete) + remove_items(lib, decargs(args), opts.album, opts.delete, opts.force) remove_cmd = ui.Subcommand( @@ -1237,6 +1239,10 @@ remove_cmd.parser.add_option( u"-d", u"--delete", action="store_true", help=u"also remove files from disk" ) +remove_cmd.parser.add_option( + u"-f", u"--force", action="store_true", + help=u"do not ask when removing items" +) remove_cmd.parser.add_album_option() remove_cmd.func = remove_func default_commands.append(remove_cmd) diff --git a/docs/changelog.rst b/docs/changelog.rst index 1069552c0..64b582450 100644 --- a/docs/changelog.rst +++ b/docs/changelog.rst @@ -4,7 +4,10 @@ Changelog 1.3.19 (in development) ----------------------- -Changelog goes here! +New features: + +* A new ``--force`` option for :ref:`remove-cmd` allows removal of items + without prompting beforehand. :bug:`2042` Some fixes for Windows: diff --git a/docs/reference/cli.rst b/docs/reference/cli.rst index faae67ee6..93b9b6253 100644 --- a/docs/reference/cli.rst +++ b/docs/reference/cli.rst @@ -211,7 +211,7 @@ remove `````` :: - beet remove [-ad] QUERY + beet remove [-adf] QUERY Remove music from your library. @@ -219,6 +219,7 @@ This command uses the same :doc:`query ` syntax as the ``list`` command. You'll be shown a list of the files that will be removed and asked to confirm. By default, this just removes entries from the library database; it doesn't touch the files on disk. To actually delete the files, use ``beet remove -d``. +If you do not want to be prompted to remove the files, use ``beet remove -f``. .. _modify-cmd: diff --git a/test/test_ui.py b/test/test_ui.py index 4476720e2..d40bfe3b7 100644 --- a/test/test_ui.py +++ b/test/test_ui.py @@ -134,14 +134,26 @@ class RemoveTest(_common.TestCase): def test_remove_items_no_delete(self): self.io.addinput('y') - commands.remove_items(self.lib, u'', False, False) + commands.remove_items(self.lib, u'', False, False, False) items = self.lib.items() self.assertEqual(len(list(items)), 0) self.assertTrue(os.path.exists(self.i.path)) def test_remove_items_with_delete(self): self.io.addinput('y') - commands.remove_items(self.lib, u'', False, True) + commands.remove_items(self.lib, u'', False, True, False) + items = self.lib.items() + self.assertEqual(len(list(items)), 0) + self.assertFalse(os.path.exists(self.i.path)) + + def test_remove_items_with_force_no_delete(self): + commands.remove_items(self.lib, u'', False, False, True) + items = self.lib.items() + self.assertEqual(len(list(items)), 0) + self.assertTrue(os.path.exists(self.i.path)) + + def test_remove_items_with_force_delete(self): + commands.remove_items(self.lib, u'', False, True, True) items = self.lib.items() self.assertEqual(len(list(items)), 0) self.assertFalse(os.path.exists(self.i.path))