Kaydet (Commit) 5cc05556 authored tarafından Jannis Leidel's avatar Jannis Leidel

Fixed #21482 -- Uplifted restriction of collectstatic using symlink option in Windows NT 6.

Original patch by Vajrasky Kok. Reviewed by Florian Apolloner, Aymeric Augustin.
üst 9c4ad454
from __future__ import unicode_literals
import os
import sys
from collections import OrderedDict
from optparse import make_option
......@@ -82,12 +81,8 @@ class Command(NoArgsCommand):
Split off from handle_noargs() to facilitate testing.
"""
if self.symlink:
if sys.platform == 'win32':
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.symlink and not self.local:
raise CommandError("Can't symlink to a remote destination.")
if self.clear:
self.clear_dir('')
......@@ -279,7 +274,18 @@ class Command(NoArgsCommand):
os.makedirs(os.path.dirname(full_path))
except OSError:
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:
self.symlinked_files.append(prefixed_path)
......
import os
import stat
import sys
import tempfile
from os.path import join, normcase, normpath, abspath, isabs, sep, dirname
from django.utils.encoding import force_text
......@@ -99,3 +100,24 @@ def rmtree_errorhandler(func, path, exc_info):
os.chmod(path, stat.S_IWRITE)
# use the original function to repeat the operation
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
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
^^^^^^
......
......@@ -17,7 +17,7 @@ from django.core.management import call_command
from django.test import TestCase, override_settings
from django.utils.encoding import force_text
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.contrib.staticfiles import finders, storage
......@@ -645,24 +645,25 @@ class TestCollectionSimpleCachedStorage(BaseCollectionTestCase,
self.assertNotIn(b"cached/other.css", content)
self.assertIn(b"other.deploy12345.css", content)
if sys.platform != 'win32':
class TestCollectionLinks(CollectionTestCase, TestDefaults):
"""
Test ``--link`` option for ``collectstatic`` management command.
@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)
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):
"""
With ``--link``, symbolic links are created.
"""
self.assertTrue(os.path.islink(os.path.join(settings.STATIC_ROOT, 'test.txt')))
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):
......
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