Commit 28bcff82 authored by Berker Peksag's avatar Berker Peksag Committed by Tim Graham
Browse files

Fixed #26297 -- Fixed `collectstatic --clear` crash if storage doesn't implement path().

parent ecb59cc6
Loading
Loading
Loading
Loading
+9 −5
Original line number Diff line number Diff line
@@ -221,7 +221,11 @@ class Command(BaseCommand):
                         smart_text(fpath), level=1)
            else:
                self.log("Deleting '%s'" % smart_text(fpath), level=1)
                try:
                    full_path = self.storage.path(fpath)
                except NotImplementedError:
                    self.storage.delete(fpath)
                else:
                    if not os.path.exists(full_path) and os.path.lexists(full_path):
                        # Delete broken symlinks
                        os.unlink(full_path)
+3 −0
Original line number Diff line number Diff line
@@ -27,3 +27,6 @@ Bugfixes
  earlier versions of Django.

* Fixed a memory leak in the cached template loader (:ticket:`26306`).

* Fixed a regression that caused ``collectstatic --clear`` to fail if the
  storage doesn't implement ``path()`` (:ticket:`26297`).
+37 −0
Original line number Diff line number Diff line
import errno
import os
from datetime import datetime

from django.conf import settings
from django.contrib.staticfiles.storage import CachedStaticFilesStorage
from django.core.files import storage
from django.utils import timezone
@@ -22,6 +25,40 @@ class DummyStorage(storage.Storage):
        return datetime.datetime(1970, 1, 1, tzinfo=timezone.utc)


class PathNotImplementedStorage(storage.Storage):

    def _save(self, name, content):
        return 'dummy'

    def _path(self, name):
        return os.path.join(settings.STATIC_ROOT, name)

    def exists(self, name):
        return os.path.exists(self._path(name))

    def listdir(self, path):
        path = self._path(path)
        directories, files = [], []
        for entry in os.listdir(path):
            if os.path.isdir(os.path.join(path, entry)):
                directories.append(entry)
            else:
                files.append(entry)
        return directories, files

    def delete(self, name):
        name = self._path(name)
        if os.path.exists(name):
            try:
                os.remove(name)
            except OSError as e:
                if e.errno != errno.ENOENT:
                    raise

    def path(self, name):
        raise NotImplementedError


class SimpleCachedStaticFilesStorage(CachedStaticFilesStorage):

    def file_hash(self, name, content=None):
+5 −0
Original line number Diff line number Diff line
@@ -170,6 +170,11 @@ class TestCollectionClear(CollectionTestCase):
        shutil.rmtree(six.text_type(settings.STATIC_ROOT))
        super(TestCollectionClear, self).run_collectstatic(clear=True)

    @override_settings(STATICFILES_STORAGE='staticfiles_tests.storage.PathNotImplementedStorage')
    def test_handle_path_notimplemented(self):
        self.run_collectstatic()
        self.assertFileNotFound('cleared.txt')


class TestCollectionExcludeNoDefaultIgnore(CollectionTestCase, TestDefaults):
    """