# HG changeset patch # User Sylvain Thénault # Date 1277294042 -7200 # Node ID 1a24c62aefc5e57f61be3d04affd415288e81904 # Parent a021295083788a04d245c3eaa126e04be26358de [bfss] fix file update to ensure file's content is available on the fs asap... and not only at commit time. So it's consistent with entity creation behaviour. The new file is created at assignement time and removed if the commit is rollbacked. diff -r a02129508378 -r 1a24c62aefc5 server/sources/storages.py --- a/server/sources/storages.py Fri Jul 02 09:09:59 2010 +0200 +++ b/server/sources/storages.py Wed Jun 23 13:54:02 2010 +0200 @@ -106,7 +106,7 @@ """ fpath = source.binary_to_str(value) try: - return Binary(file(fpath).read()) + return Binary(file(fpath, 'rb').read()) except OSError, ex: source.critical("can't open %s: %s", value, ex) return None @@ -114,28 +114,50 @@ def entity_added(self, entity, attr): """an entity using this storage for attr has been added""" if entity._cw.transaction_data.get('fs_importing'): - binary = Binary(file(entity[attr].getvalue()).read()) + binary = Binary(file(entity[attr].getvalue(), 'rb').read()) else: binary = entity.pop(attr) fpath = self.new_fs_path(entity, attr) # bytes storage used to store file's path entity[attr] = Binary(fpath) - file(fpath, 'w').write(binary.getvalue()) + file(fpath, 'wb').write(binary.getvalue()) hook.set_operation(entity._cw, 'bfss_added', fpath, AddFileOp) return binary def entity_updated(self, entity, attr): """an entity using this storage for attr has been updatded""" + # get the name of the previous file containing the value oldpath = self.current_fs_path(entity, attr) if entity._cw.transaction_data.get('fs_importing'): + # If we are importing from the filesystem, the file already exists. + # We do not need to create it but we need to fetch the content of + # the file as the actual content of the attribute fpath = entity[attr].getvalue() - binary = Binary(file(fpath).read()) + binary = Binary(file(fpath, 'rb').read()) else: + # We must store the content of the attributes + # into a file to stay consistent with the behaviour of entity_add. + # Moreover, the BytesFileSystemStorage expects to be able to + # retrieve the current value of the attribute at anytime by reading + # the file on disk. To be able to rollback things, use a new file + # and keep the old one that will be removed on commit if everything + # went ok. + # + # fetch the current attribute value in memory binary = entity.pop(attr) + # Get filename for it fpath = self.new_fs_path(entity, attr) - UpdateFileOp(entity._cw, filepath=fpath, filedata=binary.getvalue()) + assert not osp.exists(fpath) + # write attribute value on disk + file(fpath, 'wb').write(binary.getvalue()) + # Mark the new file as added during the transaction. + # The file will be removed on rollback + hook.set_operation(entity._cw, 'bfss_added', fpath, AddFileOp) if oldpath != fpath: + # register the new location for the file. entity[attr] = Binary(fpath) + # Mark the old file as useless so the file will be removed at + # commit. hook.set_operation(entity._cw, 'bfss_deleted', oldpath, DeleteFileOp) return binary @@ -200,10 +222,3 @@ unlink(filepath) except Exception, ex: self.error('cant remove %s: %s' % (filepath, ex)) - -class UpdateFileOp(hook.Operation): - def precommit_event(self): - try: - file(self.filepath, 'w').write(self.filedata) - except Exception, ex: - self.exception(str(ex))