Commit d79be259 by Christian Hammond

Fix a regression in determining when to collect static files.

A commit made in 1.6.10 (ae6b3f8e)
changed a storage lookup to use the prefixed_path variable instead of
the path variable when looking up modification times in order to
determine if an existing collected file should be deleted and
re-collected. By using the wrong path variable, the storage lookups
always failed, resulting in every single file being re-collected every
single time.

This reduces performance considerably, particularly with large codebases.
Since every file ends up copied, they appear as new and are recompiled.
This can result in very long page reloads on a development server,
especially if working on an older machine, in a VM, on a shared
filesystem, or on the Linux subsystem for Windows.

This is a simple change that fixes the lookup to use the correct
variable. Unit tests were added to ensure this continues to work as
expected and does not regress.
parent dbf66e6e
......@@ -78,7 +78,7 @@ class Collector(object):
else:
try:
# When was the source file modified last time?
source_last_modified = self._get_modified_time(source_storage, prefixed_path)
source_last_modified = self._get_modified_time(source_storage, path)
except (OSError, NotImplementedError, AttributeError):
pass
else:
......
......@@ -3,12 +3,17 @@ from __future__ import unicode_literals
import os
from django.contrib.staticfiles import finders
from django.core.files.storage import FileSystemStorage
from django.test import TestCase
from pipeline.collector import default_collector
from pipeline.finders import PipelineFinder
def local_path(path):
return os.path.abspath(os.path.join(os.path.dirname(__file__), '..', path))
class CollectorTest(TestCase):
def tearDown(self):
super(CollectorTest, self).tearDown()
......@@ -31,6 +36,24 @@ class CollectorTest(TestCase):
'pipeline/js/second.js',
]))
def test_delete_file_with_modified(self):
list(default_collector.collect())
storage = FileSystemStorage(local_path('assets'))
new_mtime = os.path.getmtime(storage.path('js/first.js')) - 1000
os.utime(default_collector.storage.path('pipeline/js/first.js'),
(new_mtime, new_mtime))
self.assertTrue(default_collector.delete_file(
'js/first.js', 'pipeline/js/first.js', storage))
def test_delete_file_with_unmodified(self):
list(default_collector.collect(files=['pipeline/js/first.js']))
self.assertFalse(default_collector.delete_file(
'js/first.js', 'pipeline/js/first.js',
FileSystemStorage(local_path('assets'))))
def _get_collectable_files(self):
for finder in finders.get_finders():
if not isinstance(finder, PipelineFinder):
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment