Fixed #21482 -- Uplifted restriction of collectstatic using symlink option in Windows NT 6.
Original patch by Vajrasky Kok. Reviewed by Florian Apolloner, Aymeric Augustin.
This commit is contained in:
parent
9c4ad454d1
commit
5cc0555603
|
@ -1,7 +1,6 @@
|
||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
import os
|
import os
|
||||||
import sys
|
|
||||||
from collections import OrderedDict
|
from collections import OrderedDict
|
||||||
from optparse import make_option
|
from optparse import make_option
|
||||||
|
|
||||||
|
@ -82,12 +81,8 @@ class Command(NoArgsCommand):
|
||||||
|
|
||||||
Split off from handle_noargs() to facilitate testing.
|
Split off from handle_noargs() to facilitate testing.
|
||||||
"""
|
"""
|
||||||
if self.symlink:
|
if self.symlink and not self.local:
|
||||||
if sys.platform == 'win32':
|
raise CommandError("Can't symlink to a remote destination.")
|
||||||
raise CommandError("Symlinking is not supported by this "
|
|
||||||
"platform (%s)." % sys.platform)
|
|
||||||
if not self.local:
|
|
||||||
raise CommandError("Can't symlink to a remote destination.")
|
|
||||||
|
|
||||||
if self.clear:
|
if self.clear:
|
||||||
self.clear_dir('')
|
self.clear_dir('')
|
||||||
|
@ -279,7 +274,18 @@ class Command(NoArgsCommand):
|
||||||
os.makedirs(os.path.dirname(full_path))
|
os.makedirs(os.path.dirname(full_path))
|
||||||
except OSError:
|
except OSError:
|
||||||
pass
|
pass
|
||||||
os.symlink(source_path, full_path)
|
try:
|
||||||
|
os.symlink(source_path, full_path)
|
||||||
|
except AttributeError:
|
||||||
|
import platform
|
||||||
|
raise CommandError("Symlinking is not supported by Python %s." %
|
||||||
|
platform.python_version())
|
||||||
|
except NotImplementedError:
|
||||||
|
import platform
|
||||||
|
raise CommandError("Symlinking is not supported in this "
|
||||||
|
"platform (%s)." % platform.platform())
|
||||||
|
except OSError as e:
|
||||||
|
raise CommandError(e)
|
||||||
if prefixed_path not in self.symlinked_files:
|
if prefixed_path not in self.symlinked_files:
|
||||||
self.symlinked_files.append(prefixed_path)
|
self.symlinked_files.append(prefixed_path)
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
import os
|
import os
|
||||||
import stat
|
import stat
|
||||||
import sys
|
import sys
|
||||||
|
import tempfile
|
||||||
from os.path import join, normcase, normpath, abspath, isabs, sep, dirname
|
from os.path import join, normcase, normpath, abspath, isabs, sep, dirname
|
||||||
|
|
||||||
from django.utils.encoding import force_text
|
from django.utils.encoding import force_text
|
||||||
|
@ -99,3 +100,24 @@ def rmtree_errorhandler(func, path, exc_info):
|
||||||
os.chmod(path, stat.S_IWRITE)
|
os.chmod(path, stat.S_IWRITE)
|
||||||
# use the original function to repeat the operation
|
# use the original function to repeat the operation
|
||||||
func(path)
|
func(path)
|
||||||
|
|
||||||
|
|
||||||
|
def symlinks_supported():
|
||||||
|
"""
|
||||||
|
A function to check if creating symlinks are supported in the
|
||||||
|
host platform and/or if they are allowed to be created (e.g.
|
||||||
|
on Windows it requires admin permissions).
|
||||||
|
"""
|
||||||
|
tmpdir = tempfile.mkdtemp()
|
||||||
|
original_path = os.path.join(tmpdir, 'original')
|
||||||
|
symlink_path = os.path.join(tmpdir, 'symlink')
|
||||||
|
os.makedirs(original_path)
|
||||||
|
try:
|
||||||
|
os.symlink(original_path, symlink_path)
|
||||||
|
supported = True
|
||||||
|
except (OSError, NotImplementedError, AttributeError):
|
||||||
|
supported = False
|
||||||
|
else:
|
||||||
|
os.remove(symlink_path)
|
||||||
|
finally:
|
||||||
|
return supported
|
||||||
|
|
|
@ -565,6 +565,9 @@ Management Commands
|
||||||
* Management commands can now produce syntax colored output under Windows if
|
* Management commands can now produce syntax colored output under Windows if
|
||||||
the ANSICON third-party tool is installed and active.
|
the ANSICON third-party tool is installed and active.
|
||||||
|
|
||||||
|
* :djadmin:`collectstatic` command with symlink option is now supported on
|
||||||
|
Windows NT 6 (Windows Vista and newer).
|
||||||
|
|
||||||
Models
|
Models
|
||||||
^^^^^^
|
^^^^^^
|
||||||
|
|
||||||
|
|
|
@ -17,7 +17,7 @@ from django.core.management import call_command
|
||||||
from django.test import TestCase, override_settings
|
from django.test import TestCase, override_settings
|
||||||
from django.utils.encoding import force_text
|
from django.utils.encoding import force_text
|
||||||
from django.utils.functional import empty
|
from django.utils.functional import empty
|
||||||
from django.utils._os import rmtree_errorhandler, upath
|
from django.utils._os import rmtree_errorhandler, upath, symlinks_supported
|
||||||
from django.utils import six
|
from django.utils import six
|
||||||
|
|
||||||
from django.contrib.staticfiles import finders, storage
|
from django.contrib.staticfiles import finders, storage
|
||||||
|
@ -645,24 +645,25 @@ class TestCollectionSimpleCachedStorage(BaseCollectionTestCase,
|
||||||
self.assertNotIn(b"cached/other.css", content)
|
self.assertNotIn(b"cached/other.css", content)
|
||||||
self.assertIn(b"other.deploy12345.css", content)
|
self.assertIn(b"other.deploy12345.css", content)
|
||||||
|
|
||||||
if sys.platform != 'win32':
|
|
||||||
|
|
||||||
class TestCollectionLinks(CollectionTestCase, TestDefaults):
|
@unittest.skipUnless(symlinks_supported(),
|
||||||
|
"Must be able to symlink to run this test.")
|
||||||
|
class TestCollectionLinks(CollectionTestCase, TestDefaults):
|
||||||
|
"""
|
||||||
|
Test ``--link`` option for ``collectstatic`` management command.
|
||||||
|
|
||||||
|
Note that by inheriting ``TestDefaults`` we repeat all
|
||||||
|
the standard file resolving tests here, to make sure using
|
||||||
|
``--link`` does not change the file-selection semantics.
|
||||||
|
"""
|
||||||
|
def run_collectstatic(self):
|
||||||
|
super(TestCollectionLinks, self).run_collectstatic(link=True)
|
||||||
|
|
||||||
|
def test_links_created(self):
|
||||||
"""
|
"""
|
||||||
Test ``--link`` option for ``collectstatic`` management command.
|
With ``--link``, symbolic links are created.
|
||||||
|
|
||||||
Note that by inheriting ``TestDefaults`` we repeat all
|
|
||||||
the standard file resolving tests here, to make sure using
|
|
||||||
``--link`` does not change the file-selection semantics.
|
|
||||||
"""
|
"""
|
||||||
def run_collectstatic(self):
|
self.assertTrue(os.path.islink(os.path.join(settings.STATIC_ROOT, 'test.txt')))
|
||||||
super(TestCollectionLinks, self).run_collectstatic(link=True)
|
|
||||||
|
|
||||||
def test_links_created(self):
|
|
||||||
"""
|
|
||||||
With ``--link``, symbolic links are created.
|
|
||||||
"""
|
|
||||||
self.assertTrue(os.path.islink(os.path.join(settings.STATIC_ROOT, 'test.txt')))
|
|
||||||
|
|
||||||
|
|
||||||
class TestServeStatic(StaticFilesTestCase):
|
class TestServeStatic(StaticFilesTestCase):
|
||||||
|
|
Loading…
Reference in New Issue