From 5304494585c58b0c9245ea9896a6d6122a8673a2 Mon Sep 17 00:00:00 2001 From: Markus Amalthea Magnuson Date: Wed, 3 Jun 2015 10:20:04 +0100 Subject: [PATCH] Fixed #24890 -- Added warning to collectstatic when static files have clashing names --- .../management/commands/collectstatic.py | 8 +++ tests/staticfiles_tests/tests.py | 59 +++++++++++++++++++ 2 files changed, 67 insertions(+) diff --git a/django/contrib/staticfiles/management/commands/collectstatic.py b/django/contrib/staticfiles/management/commands/collectstatic.py index 0c3f4e15fd..2d45648ba9 100644 --- a/django/contrib/staticfiles/management/commands/collectstatic.py +++ b/django/contrib/staticfiles/management/commands/collectstatic.py @@ -105,6 +105,14 @@ class Command(BaseCommand): if prefixed_path not in found_files: found_files[prefixed_path] = (storage, path) handler(path, prefixed_path, storage) + else: + self.log( + "Found another file with the destination path '%s'. It " + "will be ignored since only the first encountered file " + "is collected. If this is not what you want, make sure " + "every static file has a unique path." % prefixed_path, + level=1, + ) # Here we check if the storage backend has a post_process # method and pass it the list of modified files. diff --git a/tests/staticfiles_tests/tests.py b/tests/staticfiles_tests/tests.py index 52a45d2ccf..d40d033d78 100644 --- a/tests/staticfiles_tests/tests.py +++ b/tests/staticfiles_tests/tests.py @@ -399,6 +399,65 @@ class TestCollectionFilesOverride(CollectionTestCase): self.assertFileContains('file2.txt', 'duplicate of file2.txt') +# The collectstatic test suite already has conflicting files since both +# project/test/file.txt and apps/test/static/test/file.txt are collected. To +# properly test for the warning not happening unless we tell it to explicitly, +# we only include static files from the default finders. +@override_settings(STATICFILES_DIRS=[]) +class TestCollectionOverwriteWarning(CollectionTestCase): + """ + Test warning in ``collectstatic`` output when a file is skipped because a + previous file was already written to the same path. + """ + # If this string is in the collectstatic output, it means the warning we're + # looking for was emitted. + warning_string = 'Found another file' + + def _collectstatic_output(self, **kwargs): + """ + Run collectstatic, and capture and return the output. We want to run + the command at highest verbosity, which is why we can't + just call e.g. BaseCollectionTestCase.run_collectstatic() + """ + out = six.StringIO() + call_command('collectstatic', interactive=False, verbosity=3, stdout=out, **kwargs) + out.seek(0) + return out.read() + + def test_no_warning(self): + """ + There isn't a warning if there isn't a duplicate destination. + """ + output = self._collectstatic_output(clear=True) + self.assertNotIn(self.warning_string, force_text(output)) + + def test_warning(self): + """ + There is a warning when there are duplicate destinations. + """ + # Create new file in the no_label app that also exists in the test app. + test_dir = os.path.join(TEST_ROOT, 'apps', 'no_label', 'static', 'test') + if not os.path.exists(test_dir): + os.mkdir(test_dir) + + try: + duplicate_path = os.path.join(test_dir, 'file.txt') + with open(duplicate_path, 'w+') as f: + f.write('duplicate of file.txt') + output = self._collectstatic_output(clear=True) + self.assertIn(self.warning_string, force_text(output)) + finally: + if os.path.exists(duplicate_path): + os.unlink(duplicate_path) + + if os.path.exists(test_dir): + os.rmdir(test_dir) + + # Make sure the warning went away again. + output = self._collectstatic_output(clear=True) + self.assertNotIn(self.warning_string, force_text(output)) + + @override_settings( STATICFILES_STORAGE='staticfiles_tests.storage.DummyStorage', )