[IMP] Move uninstall behavior in modules.loading where it belongs
bzr revid: odo@openerp.com-20120330163422-jkatnkpw0cl8hd8t
This commit is contained in:
parent
fd14556b8c
commit
eb9b0021ff
|
@ -161,7 +161,11 @@ class ir_model(osv.osv):
|
|||
|
||||
self._drop_table(cr, user, ids, context)
|
||||
res = super(ir_model, self).unlink(cr, user, ids, context)
|
||||
pooler.restart_pool(cr.dbname)
|
||||
if not context.get(MODULE_UNINSTALL_FLAG):
|
||||
# only reload pool for normal unlink. For module uninstall the
|
||||
# reload is done independently in openerp.modules.loading
|
||||
pooler.restart_pool(cr.dbname)
|
||||
|
||||
return res
|
||||
|
||||
def write(self, cr, user, ids, vals, context=None):
|
||||
|
@ -832,6 +836,7 @@ class ir_model_data(osv.osv):
|
|||
context = dict(context or {})
|
||||
context[MODULE_UNINSTALL_FLAG] = True # enable model/field deletion
|
||||
|
||||
ids_set = set(ids)
|
||||
wkf_todo = []
|
||||
to_unlink = []
|
||||
to_drop_table = []
|
||||
|
@ -867,8 +872,11 @@ class ir_model_data(osv.osv):
|
|||
_logger.info('Drop CONSTRAINT %s@%s', name[11:], model)
|
||||
continue
|
||||
|
||||
to_unlink.append((model, res_id))
|
||||
if model=='workflow.activity':
|
||||
pair_to_unlink = (model, res_id)
|
||||
if pair_to_unlink not in to_unlink:
|
||||
to_unlink.append(pair_to_unlink)
|
||||
|
||||
if model == 'workflow.activity':
|
||||
cr.execute('select res_type,res_id from wkf_instance where id IN (select inst_id from wkf_workitem where act_id=%s)', (res_id,))
|
||||
wkf_todo.extend(cr.fetchall())
|
||||
cr.execute("update wkf_transition set condition='True', group_id=NULL, signal=NULL,act_to=act_from,act_from=%s where act_to=%s", (res_id,res_id))
|
||||
|
@ -888,13 +896,13 @@ class ir_model_data(osv.osv):
|
|||
for (model, res_id) in to_unlink:
|
||||
if model in ('ir.model','ir.model.fields', 'ir.model.data'):
|
||||
continue
|
||||
model_ids = self.search(cr, uid, [('model', '=', model),('res_id', '=', res_id)])
|
||||
if len(model_ids) > 1:
|
||||
external_ids = self.search(cr, uid, [('model', '=', model),('res_id', '=', res_id)])
|
||||
if (set(external_ids)-ids_set):
|
||||
# if other modules have defined this record, we do not delete it
|
||||
continue
|
||||
_logger.info('Deleting %s@%s', res_id, model)
|
||||
try:
|
||||
self.pool.get(model).unlink(cr, uid, res_id, context=context)
|
||||
self.pool.get(model).unlink(cr, uid, [res_id], context=context)
|
||||
except:
|
||||
_logger.info('Unable to delete %s@%s', res_id, model, exc_info=True)
|
||||
cr.commit()
|
||||
|
@ -902,18 +910,18 @@ class ir_model_data(osv.osv):
|
|||
for (model, res_id) in to_unlink:
|
||||
if model not in ('ir.model.fields',):
|
||||
continue
|
||||
model_ids = self.search(cr, uid, [('model', '=', model),('res_id', '=', res_id)])
|
||||
if len(model_ids) > 1:
|
||||
external_ids = self.search(cr, uid, [('model', '=', model),('res_id', '=', res_id)])
|
||||
if (set(external_ids)-ids_set):
|
||||
# if other modules have defined this record, we do not delete it
|
||||
continue
|
||||
_logger.info('Deleting %s@%s', res_id, model)
|
||||
self.pool.get(model).unlink(cr, uid, res_id, context=context)
|
||||
self.pool.get(model).unlink(cr, uid, [res_id], context=context)
|
||||
|
||||
for (model, res_id) in to_unlink:
|
||||
if model != 'ir.model':
|
||||
continue
|
||||
model_ids = self.search(cr, uid, [('model', '=', model),('res_id', '=', res_id)])
|
||||
if len(model_ids) > 1:
|
||||
external_ids = self.search(cr, uid, [('model', '=', model),('res_id', '=', res_id)])
|
||||
if (set(external_ids)-ids_set):
|
||||
# if other modules have defined this record, we do not delete it
|
||||
continue
|
||||
_logger.info('Deleting %s@%s', res_id, model)
|
||||
|
|
|
@ -365,6 +365,10 @@ class module(osv.osv):
|
|||
return True
|
||||
|
||||
def module_uninstall(self, cr, uid, ids, context=None):
|
||||
"""Perform the various steps required to uninstall a module completely
|
||||
including the deletion of all database structures created by the module:
|
||||
tables, columns, constraints, etc."""
|
||||
|
||||
# uninstall must be done respecting the reverse-dependency order
|
||||
ir_model_data = self.pool.get('ir.model.data')
|
||||
modules_to_remove = [m.name for m in self.browse(cr, uid, ids, context)]
|
||||
|
@ -372,8 +376,6 @@ class module(osv.osv):
|
|||
ir_model_data._pre_process_unlink(cr, uid, data_ids, context)
|
||||
ir_model_data.unlink(cr, uid, data_ids, context)
|
||||
self.write(cr, uid, ids, {'state': 'uninstalled'})
|
||||
|
||||
# should we call process_end instead of loading, or both ?
|
||||
return True
|
||||
|
||||
def downstream_dependencies(self, cr, uid, ids, known_dep_ids=None,
|
||||
|
|
|
@ -72,7 +72,7 @@ class base_module_upgrade(osv.osv_memory):
|
|||
def upgrade_module(self, cr, uid, ids, context=None):
|
||||
ir_module = self.pool.get('ir.module.module')
|
||||
|
||||
# install and upgrade modules
|
||||
# install/upgrade: double-check preconditions
|
||||
ids = ir_module.search(cr, uid, [('state', 'in', ['to upgrade', 'to install'])])
|
||||
unmet_packages = []
|
||||
mod_dep_obj = self.pool.get('ir.module.module.dependency')
|
||||
|
@ -86,16 +86,15 @@ class base_module_upgrade(osv.osv_memory):
|
|||
raise osv.except_osv(_('Unmet dependency !'), _('Following modules are not installed or unknown: %s') % ('\n\n' + '\n'.join(unmet_packages)))
|
||||
ir_module.download(cr, uid, ids, context=context)
|
||||
|
||||
# uninstall modules
|
||||
to_remove_ids = ir_module.search(cr, uid, [('state', 'in', ['to remove'])])
|
||||
ir_module.module_uninstall(cr, uid, to_remove_ids, context)
|
||||
# uninstall: double-check preconditions
|
||||
# TODO: check all dependent modules are uninstalled
|
||||
# XXX mod_ids_to_uninstall = ir_module.search(cr, uid, [('state', '=', 'to remove')])
|
||||
|
||||
cr.commit()
|
||||
cr.commit() # persist changes before reopening a cursor
|
||||
pooler.restart_pool(cr.dbname, update_module=True)
|
||||
|
||||
ir_model_data = self.pool.get('ir.model.data')
|
||||
_, res_id = ir_model_data.get_object_reference(cr, uid, 'base', 'view_base_module_upgrade_install')
|
||||
|
||||
return {
|
||||
'view_type': 'form',
|
||||
'view_mode': 'form',
|
||||
|
|
|
@ -40,6 +40,7 @@ import openerp.release as release
|
|||
import openerp.tools as tools
|
||||
import openerp.tools.assertion_report as assertion_report
|
||||
|
||||
from openerp import SUPERUSER_ID
|
||||
from openerp.tools.translate import _
|
||||
from openerp.modules.module import initialize_sys_path, \
|
||||
load_openerp_module, init_module_models
|
||||
|
@ -161,7 +162,7 @@ def load_module_graph(cr, graph, status=None, perform_checks=True, skip_modules=
|
|||
modobj = pool.get('ir.module.module')
|
||||
|
||||
if perform_checks:
|
||||
modobj.check(cr, 1, [module_id])
|
||||
modobj.check(cr, SUPERUSER_ID, [module_id])
|
||||
|
||||
idref = {}
|
||||
|
||||
|
@ -172,7 +173,7 @@ def load_module_graph(cr, graph, status=None, perform_checks=True, skip_modules=
|
|||
if hasattr(package, 'init') or hasattr(package, 'update') or package.state in ('to install', 'to upgrade'):
|
||||
if package.state=='to upgrade':
|
||||
# upgrading the module information
|
||||
modobj.write(cr, 1, [module_id], modobj.get_values_from_terp(package.data))
|
||||
modobj.write(cr, SUPERUSER_ID, [module_id], modobj.get_values_from_terp(package.data))
|
||||
load_init_xml(module_name, idref, mode)
|
||||
load_update_xml(module_name, idref, mode)
|
||||
load_data(module_name, idref, mode)
|
||||
|
@ -201,9 +202,9 @@ def load_module_graph(cr, graph, status=None, perform_checks=True, skip_modules=
|
|||
|
||||
ver = release.major_version + '.' + package.data['version']
|
||||
# Set new modules and dependencies
|
||||
modobj.write(cr, 1, [module_id], {'state': 'installed', 'latest_version': ver})
|
||||
modobj.write(cr, SUPERUSER_ID, [module_id], {'state': 'installed', 'latest_version': ver})
|
||||
# Update translations for all installed languages
|
||||
modobj.update_translations(cr, 1, [module_id], None)
|
||||
modobj.update_translations(cr, SUPERUSER_ID, [module_id], None)
|
||||
|
||||
package.state = 'installed'
|
||||
for kind in ('init', 'demo', 'update'):
|
||||
|
@ -304,15 +305,15 @@ def load_modules(db, force_demo=False, status=None, update_module=False):
|
|||
|
||||
mods = [k for k in tools.config['init'] if tools.config['init'][k]]
|
||||
if mods:
|
||||
ids = modobj.search(cr, 1, ['&', ('state', '=', 'uninstalled'), ('name', 'in', mods)])
|
||||
ids = modobj.search(cr, SUPERUSER_ID, ['&', ('state', '=', 'uninstalled'), ('name', 'in', mods)])
|
||||
if ids:
|
||||
modobj.button_install(cr, 1, ids)
|
||||
modobj.button_install(cr, SUPERUSER_ID, ids)
|
||||
|
||||
mods = [k for k in tools.config['update'] if tools.config['update'][k]]
|
||||
if mods:
|
||||
ids = modobj.search(cr, 1, ['&', ('state', '=', 'installed'), ('name', 'in', mods)])
|
||||
ids = modobj.search(cr, SUPERUSER_ID, ['&', ('state', '=', 'installed'), ('name', 'in', mods)])
|
||||
if ids:
|
||||
modobj.button_upgrade(cr, 1, ids)
|
||||
modobj.button_upgrade(cr, SUPERUSER_ID, ids)
|
||||
|
||||
cr.execute("update ir_module_module set state=%s where name=%s", ('installed', 'base'))
|
||||
|
||||
|
@ -322,7 +323,11 @@ def load_modules(db, force_demo=False, status=None, update_module=False):
|
|||
# partially installed modules (i.e. installed/to upgrade), to
|
||||
# offer a consistent system to the second part: installing
|
||||
# newly selected modules.
|
||||
states_to_load = ['installed', 'to upgrade']
|
||||
# We include the modules 'to remove' in the first step, because
|
||||
# they are part of the "currently installed" modules. They will
|
||||
# be dropped in STEP 6 later, before restarting the loading
|
||||
# process.
|
||||
states_to_load = ['installed', 'to upgrade', 'to remove']
|
||||
processed = load_marked_modules(cr, graph, states_to_load, force, status, report, loaded_modules)
|
||||
processed_modules.extend(processed)
|
||||
if update_module:
|
||||
|
@ -333,9 +338,9 @@ def load_modules(db, force_demo=False, status=None, update_module=False):
|
|||
# load custom models
|
||||
cr.execute('select model from ir_model where state=%s', ('manual',))
|
||||
for model in cr.dictfetchall():
|
||||
pool.get('ir.model').instanciate(cr, 1, model['model'], {})
|
||||
pool.get('ir.model').instanciate(cr, SUPERUSER_ID, model['model'], {})
|
||||
|
||||
# STEP 4: Finish and cleanup
|
||||
# STEP 4: Finish and cleanup installations
|
||||
if processed_modules:
|
||||
cr.execute("""select model,name from ir_model where id NOT IN (select distinct model_id from ir_model_access)""")
|
||||
for (model, name) in cr.fetchall():
|
||||
|
@ -360,53 +365,46 @@ def load_modules(db, force_demo=False, status=None, update_module=False):
|
|||
_logger.warning("Model %s is declared but cannot be loaded! (Perhaps a module was partially removed or renamed)", model)
|
||||
|
||||
# Cleanup orphan records
|
||||
pool.get('ir.model.data')._process_end(cr, 1, processed_modules)
|
||||
pool.get('ir.model.data')._process_end(cr, SUPERUSER_ID, processed_modules)
|
||||
|
||||
for kind in ('init', 'demo', 'update'):
|
||||
tools.config[kind] = {}
|
||||
|
||||
cr.commit()
|
||||
# if update_module:
|
||||
|
||||
# STEP 5: Cleanup menus
|
||||
# Remove menu items that are not referenced by any of other
|
||||
# (child) menu item, ir_values, or ir_model_data.
|
||||
# TODO: This code could be a method of ir_ui_menu. Remove menu without actions of children
|
||||
if update_module:
|
||||
while True:
|
||||
cr.execute('''delete from
|
||||
ir_ui_menu
|
||||
where
|
||||
(id not IN (select parent_id from ir_ui_menu where parent_id is not null))
|
||||
and
|
||||
(id not IN (select res_id from ir_values where model='ir.ui.menu'))
|
||||
and
|
||||
(id not IN (select res_id from ir_model_data where model='ir.ui.menu'))''')
|
||||
cr.commit()
|
||||
if not cr.rowcount:
|
||||
break
|
||||
else:
|
||||
_logger.info('removed %d unused menus', cr.rowcount)
|
||||
|
||||
# STEP 6: Uninstall modules to remove
|
||||
if update_module:
|
||||
# Remove records referenced from ir_model_data for modules to be
|
||||
# removed (and removed the references from ir_model_data).
|
||||
#cr.execute("select id,name from ir_module_module where state=%s", ('to remove',))
|
||||
#remove_modules = map(lambda x: x['name'], cr.dictfetchall())
|
||||
# Cleanup orphan records
|
||||
#pool.get('ir.model.data')._process_end(cr, 1, remove_modules, noupdate=None)
|
||||
# for mod_id, mod_name in cr.fetchall():
|
||||
# cr.execute('select model,res_id from ir_model_data where noupdate=%s and module=%s order by id desc', (False, mod_name,))
|
||||
# for rmod, rid in cr.fetchall():
|
||||
# uid = 1
|
||||
# rmod_module= pool.get(rmod)
|
||||
# if rmod_module:
|
||||
# rmod_module.unlink(cr, uid, [rid])
|
||||
# else:
|
||||
# _logger.error('Could not locate %s to remove res=%d' % (rmod,rid))
|
||||
# cr.execute('delete from ir_model_data where module=%s', (mod_name,))
|
||||
# cr.commit()
|
||||
|
||||
# Remove menu items that are not referenced by any of other
|
||||
# (child) menu item, ir_values, or ir_model_data.
|
||||
# This code could be a method of ir_ui_menu.
|
||||
# TODO: remove menu without actions of children
|
||||
# while True:
|
||||
# cr.execute('''delete from
|
||||
# ir_ui_menu
|
||||
# where
|
||||
# (id not IN (select parent_id from ir_ui_menu where parent_id is not null))
|
||||
# and
|
||||
# (id not IN (select res_id from ir_values where model='ir.ui.menu'))
|
||||
# and
|
||||
# (id not IN (select res_id from ir_model_data where model='ir.ui.menu'))''')
|
||||
# cr.commit()
|
||||
# if not cr.rowcount:
|
||||
# break
|
||||
# else:
|
||||
# _logger.info('removed %d unused menus', cr.rowcount)
|
||||
|
||||
# Pretend that modules to be removed are actually uninstalled.
|
||||
#cr.execute("update ir_module_module set state=%s where state=%s", ('uninstalled', 'to remove',))
|
||||
#cr.commit()
|
||||
cr.execute("SELECT id FROM ir_module_module WHERE state=%s", ('to remove',))
|
||||
mod_ids_to_remove = [x[0] for x in cr.fetchall()]
|
||||
if mod_ids_to_remove:
|
||||
pool.get('ir.module.module').module_uninstall(cr, SUPERUSER_ID, mod_ids_to_remove)
|
||||
# Recursive reload, should only happen once, because there should be no
|
||||
# modules to remove next time
|
||||
cr.commit()
|
||||
_logger.info('Reloading registry once more after uninstalling modules')
|
||||
return pooler.restart_pool(cr.dbname, force_demo, status, update_module)
|
||||
|
||||
if report.failures:
|
||||
_logger.error('At least one test failed when loading the modules.')
|
||||
|
|
Loading…
Reference in New Issue