1
0
mirror of https://github.com/django/django.git synced 2025-07-04 01:39:20 +00:00

Fixed #35846 -- Ensured consistent path ordering in ManifestStaticFilesStorage manifest files.

This change reuses the existing sorting of `hashed_files` in
`ManifestStaticFilesStorage.save_manifest` to also store a sorted
`paths` mapping in the manifest file. This ensures stable manifest
output that does not change unnecessarily.
This commit is contained in:
Matthew Stell 2025-06-24 07:27:52 +01:00 committed by nessita
parent 58fc40427f
commit 7feafd79a4
3 changed files with 20 additions and 3 deletions

View File

@ -496,11 +496,12 @@ class ManifestFilesMixin(HashedFilesMixin):
self.save_manifest() self.save_manifest()
def save_manifest(self): def save_manifest(self):
sorted_hashed_files = sorted(self.hashed_files.items())
self.manifest_hash = self.file_hash( self.manifest_hash = self.file_hash(
None, ContentFile(json.dumps(sorted(self.hashed_files.items())).encode()) None, ContentFile(json.dumps(sorted_hashed_files).encode())
) )
payload = { payload = {
"paths": self.hashed_files, "paths": dict(sorted_hashed_files),
"version": self.manifest_version, "version": self.manifest_version,
"hash": self.manifest_hash, "hash": self.manifest_hash,
} }

View File

@ -154,7 +154,9 @@ Minor features
:mod:`django.contrib.staticfiles` :mod:`django.contrib.staticfiles`
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
* ... * :class:`~django.contrib.staticfiles.storage.ManifestStaticFilesStorage` now
ensures consistent path ordering in manifest files, making them more
reproducible and reducing unnecessary diffs.
:mod:`django.contrib.syndication` :mod:`django.contrib.syndication`
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

View File

@ -568,6 +568,20 @@ class TestCollectionManifestStorage(TestHashedFiles, CollectionTestCase):
self.assertEqual(manifest_hash, "") self.assertEqual(manifest_hash, "")
self.assertEqual(manifest_content, {"dummy.txt": "dummy.txt"}) self.assertEqual(manifest_content, {"dummy.txt": "dummy.txt"})
def test_manifest_file_consistent_content(self):
original_manifest_content = storage.staticfiles_storage.read_manifest()
hashed_files = storage.staticfiles_storage.hashed_files
# Force a change in the order of the hashed files.
with mock.patch.object(
storage.staticfiles_storage,
"hashed_files",
dict(reversed(hashed_files.items())),
):
storage.staticfiles_storage.save_manifest()
manifest_file_content = storage.staticfiles_storage.read_manifest()
# The manifest file content should not change.
self.assertEqual(original_manifest_content, manifest_file_content)
@override_settings( @override_settings(
STATIC_URL="/", STATIC_URL="/",