diff --git a/AUTHORS b/AUTHORS index 3c0cb7a7b5..9413a51884 100644 --- a/AUTHORS +++ b/AUTHORS @@ -608,6 +608,7 @@ answer newbie questions, and generally made Django that much better: Filip Wasilewski Dan Watson Joel Watts + Russ Webber Lakin Wecker Chris Wesseling Benjamin Wohlwend diff --git a/django/core/files/move.py b/django/core/files/move.py index 4519dedf97..4bd739b4c4 100644 --- a/django/core/files/move.py +++ b/django/core/files/move.py @@ -51,6 +51,10 @@ def file_move_safe(old_file_name, new_file_name, chunk_size = 1024*64, allow_ove return try: + # If the destination file exists and allow_overwrite is False then raise an IOError + if not allow_overwrite and os.access(new_file_name, os.F_OK): + raise IOError("Destination file %s exists and allow_overwrite is False" % new_file_name) + os.rename(old_file_name, new_file_name) return except OSError: diff --git a/tests/files/tests.py b/tests/files/tests.py index cd2d15acdb..f1e3d5b14b 100644 --- a/tests/files/tests.py +++ b/tests/files/tests.py @@ -1,11 +1,13 @@ from __future__ import absolute_import +import os import gzip import shutil import tempfile from django.core.cache import cache from django.core.files import File +from django.core.files.move import file_move_safe from django.core.files.base import ContentFile from django.core.files.uploadedfile import SimpleUploadedFile from django.test import TestCase @@ -146,3 +148,15 @@ class FileTests(unittest.TestCase): file = SimpleUploadedFile("mode_test.txt", b"content") self.assertFalse(hasattr(file, 'mode')) g = gzip.GzipFile(fileobj=file) + + +class FileMoveSafeTests(unittest.TestCase): + def test_file_move_overwrite(self): + handle_a, self.file_a = tempfile.mkstemp(dir=os.environ['DJANGO_TEST_TEMP_DIR']) + handle_b, self.file_b = tempfile.mkstemp(dir=os.environ['DJANGO_TEST_TEMP_DIR']) + + # file_move_safe should raise an IOError exception if destination file exists and allow_overwrite is False + self.assertRaises(IOError, lambda: file_move_safe(self.file_a, self.file_b, allow_overwrite=False)) + + # should allow it and continue on if allow_overwrite is True + self.assertIsNone(file_move_safe(self.file_a, self.file_b, allow_overwrite=True))