mirror of
https://github.com/django/django.git
synced 2025-01-03 15:06:09 +00:00
Fixed #4282 -- Made startapp/startproject management commands honor umask.
Co-authored-by: Christian Schmitt <c.schmitt@briefdomain.de>
This commit is contained in:
parent
1555e5850d
commit
59f4796918
@ -181,7 +181,7 @@ class TemplateCommand(BaseCommand):
|
||||
if self.verbosity >= 2:
|
||||
self.stdout.write('Creating %s' % new_path)
|
||||
try:
|
||||
shutil.copymode(old_path, new_path)
|
||||
self.apply_umask(old_path, new_path)
|
||||
self.make_writeable(new_path)
|
||||
except OSError:
|
||||
self.stderr.write(
|
||||
@ -345,6 +345,12 @@ class TemplateCommand(BaseCommand):
|
||||
scheme = template.split(':', 1)[0].lower()
|
||||
return scheme in self.url_schemes
|
||||
|
||||
def apply_umask(self, old_path, new_path):
|
||||
current_umask = os.umask(0)
|
||||
os.umask(current_umask)
|
||||
current_mode = stat.S_IMODE(os.stat(old_path).st_mode)
|
||||
os.chmod(new_path, current_mode & ~current_umask)
|
||||
|
||||
def make_writeable(self, filename):
|
||||
"""
|
||||
Make sure that the file is writeable.
|
||||
|
@ -7,6 +7,7 @@ import os
|
||||
import re
|
||||
import shutil
|
||||
import socket
|
||||
import stat
|
||||
import subprocess
|
||||
import sys
|
||||
import tempfile
|
||||
@ -32,6 +33,7 @@ from django.test import (
|
||||
LiveServerTestCase, SimpleTestCase, TestCase, override_settings,
|
||||
)
|
||||
from django.test.utils import captured_stderr, captured_stdout
|
||||
from django.utils.version import PY39
|
||||
|
||||
custom_templates_dir = os.path.join(os.path.dirname(__file__), 'custom_templates')
|
||||
|
||||
@ -95,7 +97,7 @@ class AdminScriptTestCase(SimpleTestCase):
|
||||
paths.append(os.path.dirname(backend_dir))
|
||||
return paths
|
||||
|
||||
def run_test(self, args, settings_file=None, apps=None):
|
||||
def run_test(self, args, settings_file=None, apps=None, umask=None):
|
||||
base_dir = os.path.dirname(self.test_dir)
|
||||
# The base dir for Django's tests is one level up.
|
||||
tests_dir = os.path.dirname(os.path.dirname(__file__))
|
||||
@ -124,11 +126,13 @@ class AdminScriptTestCase(SimpleTestCase):
|
||||
cwd=self.test_dir,
|
||||
env=test_environ,
|
||||
text=True,
|
||||
# subprocess.run()'s umask was added in Python 3.9.
|
||||
**({'umask': umask} if umask and PY39 else {}),
|
||||
)
|
||||
return p.stdout, p.stderr
|
||||
|
||||
def run_django_admin(self, args, settings_file=None):
|
||||
return self.run_test(['-m', 'django', *args], settings_file)
|
||||
def run_django_admin(self, args, settings_file=None, umask=None):
|
||||
return self.run_test(['-m', 'django', *args], settings_file, umask=umask)
|
||||
|
||||
def run_manage(self, args, settings_file=None, manage_py=None):
|
||||
template_manage_py = (
|
||||
@ -2297,6 +2301,29 @@ class StartProject(LiveServerTestCase, AdminScriptTestCase):
|
||||
not_excluded = os.path.join(testproject_dir, project_name)
|
||||
self.assertIs(os.path.exists(not_excluded), True)
|
||||
|
||||
@unittest.skipIf(
|
||||
sys.platform == 'win32',
|
||||
'Windows only partially supports umasks and chmod.',
|
||||
)
|
||||
@unittest.skipUnless(PY39, "subprocess.run()'s umask was added in Python 3.9.")
|
||||
def test_honor_umask(self):
|
||||
_, err = self.run_django_admin(['startproject', 'testproject'], umask=0o077)
|
||||
self.assertNoOutput(err)
|
||||
testproject_dir = os.path.join(self.test_dir, 'testproject')
|
||||
self.assertIs(os.path.isdir(testproject_dir), True)
|
||||
tests = [
|
||||
(['manage.py'], 0o700),
|
||||
(['testproject'], 0o700),
|
||||
(['testproject', 'settings.py'], 0o600),
|
||||
]
|
||||
for paths, expected_mode in tests:
|
||||
file_path = os.path.join(testproject_dir, *paths)
|
||||
with self.subTest(paths[-1]):
|
||||
self.assertEqual(
|
||||
stat.S_IMODE(os.stat(file_path).st_mode),
|
||||
expected_mode,
|
||||
)
|
||||
|
||||
|
||||
class StartApp(AdminScriptTestCase):
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user