Author: gwilson
Date: 2009-05-08 00:50:31 -0500 (Fri, 08 May 2009)
New Revision: 10701

Modified:
   django/trunk/django/core/files/storage.py
   django/trunk/tests/regressiontests/file_storage/tests.py
Log:
Fixed #9610 -- Fixed duplicate uploaded file name mangling when directory 
contained a dot and file didn't.  Based on patches from fadlytabrani and 
adurdin.


Modified: django/trunk/django/core/files/storage.py
===================================================================
--- django/trunk/django/core/files/storage.py   2009-05-08 04:46:30 UTC (rev 
10700)
+++ django/trunk/django/core/files/storage.py   2009-05-08 05:50:31 UTC (rev 
10701)
@@ -63,15 +63,15 @@
         Returns a filename that's free on the target storage system, and
         available for new content to be written to.
         """
-        # If the filename already exists, keep adding an underscore to the name
-        # of the file until the filename doesn't exist.
+        dir_name, file_name = os.path.split(name)
+        file_root, file_ext = os.path.splitext(file_name)
+        # If the filename already exists, keep adding an underscore (before the
+        # file extension, if one exists) to the filename until the generated
+        # filename doesn't exist.
         while self.exists(name):
-            try:
-                dot_index = name.rindex('.')
-            except ValueError: # filename has no dot
-                name += '_'
-            else:
-                name = name[:dot_index] + '_' + name[dot_index:]
+            file_root += '_'
+            # file_ext includes the dot.
+            name = os.path.join(dir_name, file_root + file_ext)
         return name
 
     def path(self, name):

Modified: django/trunk/tests/regressiontests/file_storage/tests.py
===================================================================
--- django/trunk/tests/regressiontests/file_storage/tests.py    2009-05-08 
04:46:30 UTC (rev 10700)
+++ django/trunk/tests/regressiontests/file_storage/tests.py    2009-05-08 
05:50:31 UTC (rev 10701)
@@ -84,11 +84,12 @@
 """
 
 # Tests for a race condition on file saving (#4948).
-# This is written in such a way that it'll always pass on platforms 
+# This is written in such a way that it'll always pass on platforms
 # without threading.
 import os
 import time
 import shutil
+import sys
 import tempfile
 from unittest import TestCase
 from django.conf import settings
@@ -109,13 +110,13 @@
         self.storage_dir = tempfile.mkdtemp()
         self.storage = FileSystemStorage(self.storage_dir)
         self.thread = threading.Thread(target=self.save_file, 
args=['conflict'])
-    
+
     def tearDown(self):
         shutil.rmtree(self.storage_dir)
-    
+
     def save_file(self, name):
         name = self.storage.save(name, SlowFile("Data"))
-    
+
     def test_race_condition(self):
         self.thread.start()
         name = self.save_file('conflict')
@@ -141,3 +142,41 @@
         actual_mode = os.stat(self.storage.path(name))[0] & 0777
         self.assertEqual(actual_mode, 0666)
 
+
+class FileStoragePathParsing(TestCase):
+    def setUp(self):
+        self.storage_dir = tempfile.mkdtemp()
+        self.storage = FileSystemStorage(self.storage_dir)
+
+    def tearDown(self):
+        shutil.rmtree(self.storage_dir)
+
+    def test_directory_with_dot(self):
+        """Regression test for #9610.
+
+        If the directory name contains a dot and the file name doesn't, make
+        sure we still mangle the file name instead of the directory name.
+        """
+
+        self.storage.save('dotted.path/test', ContentFile("1"))
+        self.storage.save('dotted.path/test', ContentFile("2"))
+
+        self.assertFalse(os.path.exists(os.path.join(self.storage_dir, 
'dotted_.path')))
+        self.assertTrue(os.path.exists(os.path.join(self.storage_dir, 
'dotted.path/test')))
+        self.assertTrue(os.path.exists(os.path.join(self.storage_dir, 
'dotted.path/test_')))
+
+    def test_first_character_dot(self):
+        """
+        File names with a dot as their first character don't have an extension,
+        and the underscore should get added to the end.
+        """
+        self.storage.save('dotted.path/.test', ContentFile("1"))
+        self.storage.save('dotted.path/.test', ContentFile("2"))
+
+        self.assertTrue(os.path.exists(os.path.join(self.storage_dir, 
'dotted.path/.test')))
+        # Before 2.6, a leading dot was treated as an extension, and so
+        # underscore gets added to beginning instead of end.
+        if sys.version_info < (2, 6):
+            self.assertTrue(os.path.exists(os.path.join(self.storage_dir, 
'dotted.path/_.test')))
+        else:
+            self.assertTrue(os.path.exists(os.path.join(self.storage_dir, 
'dotted.path/.test_')))


--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups 
"Django updates" group.
To post to this group, send email to django-updates@googlegroups.com
To unsubscribe from this group, send email to 
django-updates+unsubscr...@googlegroups.com
For more options, visit this group at 
http://groups.google.com/group/django-updates?hl=en
-~----------~----~----~----~------~----~------~--~---

Reply via email to