[bfss] Rename filenames according to their metadata on entity update. stable
authorPierre-Yves David <pierre-yves.david@logilab.fr>
Fri, 28 May 2010 08:05:17 +0200
branchstable
changeset 5599 be94157bd754
parent 5598 0a68e7f5829c
child 5606 61b28589d33f
[bfss] Rename filenames according to their metadata on entity update.
server/sources/storages.py
server/test/unittest_storage.py
--- a/server/sources/storages.py	Wed May 26 18:32:27 2010 +0200
+++ b/server/sources/storages.py	Fri May 28 08:05:17 2010 +0200
@@ -125,17 +125,18 @@
 
     def entity_updated(self, entity, attr):
         """an entity using this storage for attr has been updatded"""
+        oldpath = self.current_fs_path(entity, attr)
         if entity._cw.transaction_data.get('fs_importing'):
-            oldpath = self.current_fs_path(entity, attr)
             fpath = entity[attr].getvalue()
-            if oldpath != fpath:
-                hook.set_operation(entity._cw, 'bfss_deleted', oldpath,
-                                   DeleteFileOp)
             binary = Binary(file(fpath).read())
         else:
             binary = entity.pop(attr)
-            fpath = self.current_fs_path(entity, attr)
+            fpath = self.new_fs_path(entity, attr)
             UpdateFileOp(entity._cw, filepath=fpath, filedata=binary.getvalue())
+        if oldpath != fpath:
+            entity[attr] = Binary(fpath)
+            hook.set_operation(entity._cw, 'bfss_deleted', oldpath,
+                               DeleteFileOp)
         return binary
 
     def entity_deleted(self, entity, attr):
--- a/server/test/unittest_storage.py	Wed May 26 18:32:27 2010 +0200
+++ b/server/test/unittest_storage.py	Fri May 28 08:05:17 2010 +0200
@@ -21,7 +21,7 @@
 
 from __future__ import with_statement
 
-from logilab.common.testlib import unittest_main
+from logilab.common.testlib import unittest_main, tag
 from cubicweb.devtools.testlib import CubicWebTC
 
 import os.path as osp
@@ -180,7 +180,7 @@
         self.assertEquals(f1.data.getvalue(), file(filepath).read(),
                           'files content differ')
 
-
+    @tag('Storage', 'BFSS', 'update')
     def test_bfss_update_with_existing_data(self):
         # use self.session to use server-side cache
         f1 = self.session.create_entity('File', data=Binary('some data'),
@@ -194,6 +194,52 @@
         f2 = self.execute('Any F WHERE F eid %(f)s, F is File', {'f': f1.eid}).get_entity(0, 0)
         self.assertEquals(f2.data.getvalue(), 'some other data')
 
+    @tag('Storage', 'BFSS', 'update', 'extension', 'commit')
+    def test_bfss_update_with_different_extension_commited(self):
+        # use self.session to use server-side cache
+        f1 = self.session.create_entity('File', data=Binary('some data'),
+                                        data_format=u'text/plain', data_name=u'foo.txt')
+        # NOTE: do not use set_attributes() which would automatically
+        #       update f1's local dict. We want the pure rql version to work
+        self.commit()
+        old_path = self.fspath(f1)
+        self.failUnless(osp.isfile(old_path))
+        self.assertEquals(osp.splitext(old_path)[1], '.txt')
+        self.execute('SET F data %(d)s, F data_name %(dn)s, F data_format %(df)s WHERE F eid %(f)s',
+                     {'d': Binary('some other data'), 'f': f1.eid, 'dn': u'bar.jpg', 'df': u'image/jpeg'})
+        self.commit()
+        # the new file exists with correct extension
+        # the old file is dead
+        f2 = self.execute('Any F WHERE F eid %(f)s, F is File', {'f': f1.eid}).get_entity(0, 0)
+        new_path = self.fspath(f2)
+        self.failIf(osp.isfile(old_path))
+        self.failUnless(osp.isfile(new_path))
+        self.assertEquals(osp.splitext(new_path)[1], '.jpg')
+
+    @tag('Storage', 'BFSS', 'update', 'extension', 'rollback')
+    def test_bfss_update_with_different_extension_rollbacked(self):
+        # use self.session to use server-side cache
+        f1 = self.session.create_entity('File', data=Binary('some data'),
+                                        data_format=u'text/plain', data_name=u'foo.txt')
+        # NOTE: do not use set_attributes() which would automatically
+        #       update f1's local dict. We want the pure rql version to work
+        self.commit()
+        old_path = self.fspath(f1)
+        old_data = f1.data.getvalue()
+        self.failUnless(osp.isfile(old_path))
+        self.assertEquals(osp.splitext(old_path)[1], '.txt')
+        self.execute('SET F data %(d)s, F data_name %(dn)s, F data_format %(df)s WHERE F eid %(f)s',
+                     {'d': Binary('some other data'), 'f': f1.eid, 'dn': u'bar.jpg', 'df': u'image/jpeg'})
+        self.rollback()
+        # the new file exists with correct extension
+        # the old file is dead
+        f2 = self.execute('Any F WHERE F eid %(f)s, F is File', {'f': f1.eid}).get_entity(0, 0)
+        new_path = self.fspath(f2)
+        new_data = f2.data.getvalue()
+        self.failUnless(osp.isfile(new_path))
+        self.assertEquals(osp.splitext(new_path)[1], '.txt')
+        self.assertEquals(old_path, new_path)
+        self.assertEquals(old_data, new_data)
 
     def test_bfss_update_with_fs_importing(self):
         # use self.session to use server-side cache