Commit 33d88ef7 authored by Julien Muchembled's avatar Julien Muchembled

Sort portal types to install according to their dependencies

git-svn-id: https://svn.erp5.org/repos/public/erp5/trunk@39708 20353a03-c40f-0410-a6d1-a30d3c3de9de
parent 30edcbd4
...@@ -56,7 +56,7 @@ from Products.ERP5Type.Utils import readLocalExtension, \ ...@@ -56,7 +56,7 @@ from Products.ERP5Type.Utils import readLocalExtension, \
from Products.ERP5Type.Utils import readLocalTest, \ from Products.ERP5Type.Utils import readLocalTest, \
writeLocalTest, \ writeLocalTest, \
removeLocalTest removeLocalTest
from Products.ERP5Type.Utils import convertToUpperCase from Products.ERP5Type.Utils import convertToUpperCase, PersistentMigrationMixin
from Products.ERP5Type import Permissions, PropertySheet, interfaces from Products.ERP5Type import Permissions, PropertySheet, interfaces
from Products.ERP5Type.XMLObject import XMLObject from Products.ERP5Type.XMLObject import XMLObject
from Products.ERP5Type.dynamic.portal_type_class import synchronizeDynamicModules from Products.ERP5Type.dynamic.portal_type_class import synchronizeDynamicModules
...@@ -954,6 +954,12 @@ class ObjectTemplateItem(BaseTemplateItem): ...@@ -954,6 +954,12 @@ class ObjectTemplateItem(BaseTemplateItem):
**original_reindex_parameters) **original_reindex_parameters)
return original_reindex_parameters return original_reindex_parameters
def _getObjectKeyList(self):
# sort to add objects before their subobjects
keys = self._objects.keys()
keys.sort()
return keys
def install(self, context, trashbin, **kw): def install(self, context, trashbin, **kw):
self.beforeInstall() self.beforeInstall()
update_dict = kw.get('object_to_update') update_dict = kw.get('object_to_update')
...@@ -981,12 +987,10 @@ class ObjectTemplateItem(BaseTemplateItem): ...@@ -981,12 +987,10 @@ class ObjectTemplateItem(BaseTemplateItem):
groups = {} groups = {}
old_groups = {} old_groups = {}
portal = context.getPortalObject() portal = context.getPortalObject()
# sort to add objects before their subobjects
keys = self._objects.keys()
keys.sort()
# set safe activities execution order # set safe activities execution order
original_reindex_parameters = self.setSafeReindexationMode(context) original_reindex_parameters = self.setSafeReindexationMode(context)
for path in keys: object_key_list = self._getObjectKeyList()
for path in object_key_list:
if update_dict.has_key(path) or force: if update_dict.has_key(path) or force:
# get action for the oject # get action for the oject
action = 'backup' action = 'backup'
...@@ -1225,7 +1229,7 @@ class ObjectTemplateItem(BaseTemplateItem): ...@@ -1225,7 +1229,7 @@ class ObjectTemplateItem(BaseTemplateItem):
if getattr(aq_base(container), 'objectIds', None) is not None: if getattr(aq_base(container), 'objectIds', None) is not None:
fillRecursivePathList(['%s/%s' % (from_path, sub_content_id) for\ fillRecursivePathList(['%s/%s' % (from_path, sub_content_id) for\
sub_content_id in container.objectIds()]) sub_content_id in container.objectIds()])
fillRecursivePathList(self._objects.keys()) fillRecursivePathList(object_key_list)
for recursive_path in recursive_path_list: for recursive_path in recursive_path_list:
if recursive_path in update_dict: if recursive_path in update_dict:
action = update_dict[recursive_path] action = update_dict[recursive_path]
...@@ -1899,6 +1903,31 @@ class PortalTypeTemplateItem(ObjectTemplateItem): ...@@ -1899,6 +1903,31 @@ class PortalTypeTemplateItem(ObjectTemplateItem):
self._objects[relative_url] = obj self._objects[relative_url] = obj
obj.wl_clearLocks() obj.wl_clearLocks()
def _getObjectKeyList(self):
# Sort portal types to install according to their dependencies
object_key_list = self._objects.keys()
path_dict = dict(x.split('/')[1:] + [x] for x in object_key_list)
cache = {}
def solveDependency(path):
score = cache.get(path)
if score is None:
obj = self._objects[path]
klass = obj.__class__
if klass.__module__.startswith('Products.ERP5Type.Document.'):
portal_type = obj.portal_type
obj._p_deactivate()
else:
portal_type = klass.__name__
depend = path_dict.get(portal_type)
cache[path] = score = depend and 1 + solveDependency(depend)[0] or 0
return score, path
PersistentMigrationMixin._no_migration += 1
try:
object_key_list.sort(key=solveDependency)
finally:
PersistentMigrationMixin._no_migration -= 1
return object_key_list
# XXX : this method is kept temporarily, but can be removed once all bt5 are # XXX : this method is kept temporarily, but can be removed once all bt5 are
# re-exported with separated workflow-chain information # re-exported with separated workflow-chain information
def install(self, context, trashbin, **kw): def install(self, context, trashbin, **kw):
......
...@@ -6667,7 +6667,7 @@ class TestBusinessTemplate(ERP5TypeTestCase, LogInterceptor): ...@@ -6667,7 +6667,7 @@ class TestBusinessTemplate(ERP5TypeTestCase, LogInterceptor):
from Products.ERP5.Document.BusinessTemplate import BaseTemplateItem from Products.ERP5.Document.BusinessTemplate import BaseTemplateItem
portal = self.portal portal = self.portal
BaseTemplateItem_removeProperties = BaseTemplateItem.removeProperties BaseTemplateItem_removeProperties = BaseTemplateItem.removeProperties
object_id_list = 'old_file', 'some_file', 'some_foo' object_id_list = 'old_file', 'some_file'
marker_list = [] marker_list = []
def removeProperties(self, obj, export): def removeProperties(self, obj, export):
# Check it works if the object is modified during install. # Check it works if the object is modified during install.
......
...@@ -2,13 +2,21 @@ ...@@ -2,13 +2,21 @@
<ZopeData> <ZopeData>
<record id="1" aka="AAAAAAAAAAE="> <record id="1" aka="AAAAAAAAAAE=">
<pickle> <pickle>
<global name="Foo" module="erp5.portal_type"/> <global name="Base Type" module="erp5.portal_type"/>
</pickle> </pickle>
<pickle> <pickle>
<dictionary> <dictionary>
<item> <item>
<key> <string>id</string> </key> <key> <string>id</string> </key>
<value> <string>some_foo</string> </value> <value> <string>Foo Type</string> </value>
</item>
<item>
<key> <string>portal_type</string> </key>
<value> <string>Base Type</string> </value>
</item>
<item>
<key> <string>type_class</string> </key>
<value> <string>ERP5TypeInformation</string> </value>
</item> </item>
</dictionary> </dictionary>
</pickle> </pickle>
......
...@@ -2,58 +2,22 @@ ...@@ -2,58 +2,22 @@
<ZopeData> <ZopeData>
<record id="1" aka="AAAAAAAAAAE="> <record id="1" aka="AAAAAAAAAAE=">
<pickle> <pickle>
<global name="Base Type" module="erp5.portal_type"/> <global name="Foo Type" module="erp5.portal_type"/>
</pickle> </pickle>
<pickle> <pickle>
<dictionary> <dictionary>
<item>
<key> <string>content_icon</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>description</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>factory</string> </key>
<value>
<none/>
</value>
</item>
<item> <item>
<key> <string>id</string> </key> <key> <string>id</string> </key>
<value> <string>Foo</string> </value> <value> <string>Foo</string> </value>
</item> </item>
<item>
<key> <string>init_script</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>permission</string> </key>
<value>
<none/>
</value>
</item>
<item> <item>
<key> <string>portal_type</string> </key> <key> <string>portal_type</string> </key>
<value> <string>Base Type</string> </value> <value> <string>Foo Type</string> </value>
</item> </item>
<item> <item>
<key> <string>type_class</string> </key> <key> <string>type_class</string> </key>
<value> <string>XMLObject</string> </value> <value> <string>XMLObject</string> </value>
</item> </item>
<item>
<key> <string>type_mixin</string> </key>
<value>
<tuple/>
</value>
</item>
</dictionary> </dictionary>
</pickle> </pickle>
</record> </record>
......
old_file old_file
some_file some_file
some_foo \ No newline at end of file
\ No newline at end of file
...@@ -887,14 +887,14 @@ class PersistentMigrationMixin(object): ...@@ -887,14 +887,14 @@ class PersistentMigrationMixin(object):
It allows us to migrate ERP5Type.Document.XXX.YYY classes to It allows us to migrate ERP5Type.Document.XXX.YYY classes to
erp5.portal_type.ZZZ namespace erp5.portal_type.ZZZ namespace
Note that migration can be disabled by setting the migrate Note that migration can be disabled by setting the '_no_migration'
class attribute to 0/False, as all old objects in the system class attribute to a nonzero value, as all old objects in the system
should inherit from this mixin should inherit from this mixin
""" """
migrate = 1 _no_migration = 0
def __setstate__(self, value): def __setstate__(self, value):
if not PersistentMigrationMixin.migrate: if PersistentMigrationMixin._no_migration:
super(PersistentMigrationMixin, self).__setstate__(value) super(PersistentMigrationMixin, self).__setstate__(value)
return return
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment