diff --git a/beets/autotag/__init__.py b/beets/autotag/__init__.py index 6915a7783..e054f6221 100644 --- a/beets/autotag/__init__.py +++ b/beets/autotag/__init__.py @@ -45,7 +45,8 @@ def albums_in_dir(path): collapse_pat = collapse_paths = collapse_items = None for root, dirs, files in sorted_walk(path, - ignore=config['ignore'].as_str_seq()): + ignore=config['ignore'].as_str_seq(), + logger=log): # Get a list of items in the directory. items = [] for filename in files: diff --git a/beets/util/__init__.py b/beets/util/__init__.py index b0a85f74d..2b56766f6 100644 --- a/beets/util/__init__.py +++ b/beets/util/__init__.py @@ -139,18 +139,28 @@ def ancestry(path, pathmod=None): out.insert(0, path) return out -def sorted_walk(path, ignore=()): - """Like ``os.walk``, but yields things in case-insensitive sorted, +def sorted_walk(path, ignore=(), logger=None): + """Like `os.walk`, but yields things in case-insensitive sorted, breadth-first order. Directory and file names matching any glob - pattern in ``ignore`` are skipped. + pattern in `ignore` are skipped. If `logger` is provided, then + warning messages are logged there when a directory cannot be listed. """ # Make sure the path isn't a Unicode string. path = bytestring_path(path) # Get all the directories and files at this level. + try: + contents = os.listdir(syspath(path)) + except OSError as exc: + print('foo', logger, bool(logger)) + if logger: + logger.warn(u'could not list directory {0}: {1}'.format( + displayable_path(path), exc.strerror + )) + return dirs = [] files = [] - for base in os.listdir(syspath(path)): + for base in contents: base = bytestring_path(base) # Skip ignored filenames. @@ -178,7 +188,7 @@ def sorted_walk(path, ignore=()): for base in dirs: cur = os.path.join(path, base) # yield from sorted_walk(...) - for res in sorted_walk(cur, ignore): + for res in sorted_walk(cur, ignore, logger): yield res def mkdirall(path): diff --git a/docs/changelog.rst b/docs/changelog.rst index 1d412023e..d839e09e9 100644 --- a/docs/changelog.rst +++ b/docs/changelog.rst @@ -7,6 +7,9 @@ Changelog * :doc:`/plugins/echonest_tempo`: API errors now issue a warning instead of exiting with an exception. We also avoid an error when track metadata contains newlines. +* When the importer encounters an error (insufficient permissions, for + example) when walking a directory tree, it now logs an error instead of + crashing. * Fix a crash when iTunes Sound Check tags contained invalid data. * Fix an error when the configuration file (``config.yaml``) is completely empty.