diff --git a/beetsplug/badfiles.py b/beetsplug/badfiles.py index e072d82a3..d27208724 100644 --- a/beetsplug/badfiles.py +++ b/beetsplug/badfiles.py @@ -20,7 +20,7 @@ from __future__ import (division, absolute_import, print_function, from beets.plugins import BeetsPlugin from beets.ui import Subcommand -from beets.util import displayable_path +from beets.util import displayable_path, confit from beets import ui from subprocess import check_output, CalledProcessError, list2cmdline, STDOUT import shlex @@ -35,22 +35,27 @@ class BadFiles(BeetsPlugin): displayable_path(list2cmdline(cmd))) try: output = check_output(cmd, stderr=STDOUT) - return 0, [line for line in output.split("\n") if line] + errors = 0 + status = 0 except CalledProcessError as e: - return 1, [line for line in e.output.split("\n") if line] + output = e.output + errors = 1 + status = e.returncode except OSError as e: if e.errno == errno.ENOENT: ui.print_("command not found: {}".format(cmd[0])) sys.exit(1) else: raise + output = output.decode(sys.getfilesystemencoding()) + return status, errors, [line for line in output.split("\n") if line] def check_mp3val(self, path): - errors, output = self.run_command(["mp3val", path]) - if errors == 0: + status, errors, output = self.run_command(["mp3val", path]) + if status == 0: output = [line for line in output if line.startswith("WARNING:")] - errors = sum(1 for line in output if line.startswith("WARNING:")) - return errors, output + errors = len(output) + return status, errors, output def check_flac(self, path): return self.run_command(["flac", "-wst", path]) @@ -64,7 +69,10 @@ class BadFiles(BeetsPlugin): def get_checker(self, ext): ext = ext.lower() - command = self.config['commands'].get().get(ext) + try: + command = self.config['commands'].get(dict).get(ext) + except confit.NotFoundError: + command = None if command: return self.check_custom(command) elif ext == "mp3": @@ -73,28 +81,37 @@ class BadFiles(BeetsPlugin): return self.check_flac def check_bad(self, lib, opts, args): - for item in lib.items(args): + for item in lib.items(ui.decargs(args)): # First, check whether the path exists. If not, the user # should probably run `beet update` to cleanup your library. dpath = displayable_path(item.path) self._log.debug("checking path: {}", dpath) if not os.path.exists(item.path): - ui.print_("{}: file does not exist".format(dpath)) + ui.print_("{}: file does not exist".format( + ui.colorize('text_error', dpath))) # Run the checker against the file if one is found ext = os.path.splitext(item.path)[1][1:] checker = self.get_checker(ext) if not checker: continue - errors, output = checker(item.path) - if errors == 0: - ui.print_("{}: ok".format(dpath)) - else: - ui.print_("{}: checker found {} errors or warnings" - .format(dpath, errors)) + path = item.path + if not isinstance(path, unicode): + path = item.path.decode(sys.getfilesystemencoding()) + status, errors, output = checker(path) + if status > 0: + ui.print_("{}: checker exited withs status {}" + .format(ui.colorize('text_error', dpath), status)) for line in output: ui.print_(" {}".format(displayable_path(line))) + elif errors > 0: + ui.print_("{}: checker found {} errors or warnings" + .format(ui.colorize('text_warning', dpath), errors)) + for line in output: + ui.print_(" {}".format(displayable_path(line))) + else: + ui.print_("{}: ok".format(ui.colorize('text_success', dpath))) def commands(self): bad_command = Subcommand('bad', diff --git a/docs/plugins/badfiles.rst b/docs/plugins/badfiles.rst index 6ff369ff5..80f543c54 100644 --- a/docs/plugins/badfiles.rst +++ b/docs/plugins/badfiles.rst @@ -7,14 +7,13 @@ corrupt files. Configuring ----------- -First, enable the ``badfiles`` plugin (see :ref:`using-plugins`). Then, add a -``badfiles:`` section to your configuration file, like so:: +First, enable the ``badfiles`` plugin (see :ref:`using-plugins`). The default +configuration defines the following default checkers, which you may need to +install yourself: - badfiles: - commands: {} +* `mp3val`_ for MP3 files +* `FLAC`_ command-line tools for FLAC files -This uses two default checkers: `mp3val`_ for MP3s and the ordinary `FLAC`_ -command-line tools for those files. (You will need to install these yourself.) You can also add custom commands for a specific extension, like this:: badfiles: @@ -22,6 +21,10 @@ You can also add custom commands for a specific extension, like this:: ogg: myoggchecker --opt1 --opt2 flac: flac --test --warnings-as-errors --silent +Custom commands will be run once for each file of the specified type, with the +path to the file as the last argument. Commands must return a status code +greater than zero for a file to be considered corrupt. + .. _mp3val: http://mp3val.sourceforge.net/ .. _flac: https://xiph.org/flac/