From 88a72ea14d0e3b90b5aa08675f9662b5fd24b62e Mon Sep 17 00:00:00 2001
From: Simon Arlott <sa.me.uk>
Date: Sun, 21 Jun 2020 10:13:55 +0100
Subject: [PATCH] Handle access errors scanning directories

Trying to read a directory that is visible but not accessible, or a
symlink to a file in a directory that is not accessible will raise a
PermissionError. Output these and then continue.

If os.scandir() raises an exception then the finally block accesses
"scanner" before it is assigned, raising an UnboundLocalError.
---
 .../music/management/commands/import_files.py | 28 +++++++++++++------
 changes/changelog.d/import-eaccess-fix.bugfix |  1 +
 2 files changed, 21 insertions(+), 8 deletions(-)
 create mode 100644 changes/changelog.d/import-eaccess-fix.bugfix

diff --git a/api/funkwhale_api/music/management/commands/import_files.py b/api/funkwhale_api/music/management/commands/import_files.py
index e03c9a720..5c9eecda6 100644
--- a/api/funkwhale_api/music/management/commands/import_files.py
+++ b/api/funkwhale_api/music/management/commands/import_files.py
@@ -3,6 +3,7 @@ import datetime
 import itertools
 import os
 import queue
+import sys
 import threading
 import time
 import urllib.parse
@@ -29,16 +30,27 @@ def crawl_dir(dir, extensions, recursive=True, ignored=[]):
         return
     try:
         scanner = os.scandir(dir)
+    except Exception as e:
+        m = "Error while reading {}: {} {}\n".format(dir, e.__class__.__name__, e)
+        sys.stderr.write(m)
+        return
+    try:
         for entry in scanner:
-            if entry.is_file():
-                for e in extensions:
-                    if entry.name.lower().endswith(".{}".format(e.lower())):
-                        if entry.path not in ignored:
-                            yield entry.path
-            elif recursive and entry.is_dir():
-                yield from crawl_dir(
-                    entry.path, extensions, recursive=recursive, ignored=ignored
+            try:
+                if entry.is_file():
+                    for e in extensions:
+                        if entry.name.lower().endswith(".{}".format(e.lower())):
+                            if entry.path not in ignored:
+                                yield entry.path
+                elif recursive and entry.is_dir():
+                    yield from crawl_dir(
+                        entry.path, extensions, recursive=recursive, ignored=ignored
+                    )
+            except Exception as e:
+                m = "Error while reading {}: {} {}\n".format(
+                    entry.name, e.__class__.__name__, e
                 )
+                sys.stderr.write(m)
     finally:
         if hasattr(scanner, "close"):
             scanner.close()
diff --git a/changes/changelog.d/import-eaccess-fix.bugfix b/changes/changelog.d/import-eaccess-fix.bugfix
new file mode 100644
index 000000000..841a820d9
--- /dev/null
+++ b/changes/changelog.d/import-eaccess-fix.bugfix
@@ -0,0 +1 @@
+Handle access errors scanning directories when importing files
-- 
GitLab