[FIX] module: fix dependency computation to work recursively
bzr revid: odo@openerp.com-20120326231839-q7x3zr1bgenom3pc
This commit is contained in:
parent
8bd0cf42f3
commit
c6f72008ed
|
@ -2,8 +2,7 @@
|
|||
##############################################################################
|
||||
#
|
||||
# OpenERP, Open Source Management Solution
|
||||
# Copyright (C) 2004-2009 Tiny SPRL (<http://tiny.be>).
|
||||
# Copyright (C) 2010 OpenERP s.a. (<http://openerp.com>).
|
||||
# Copyright (C) 2004-2012 OpenERP S.A. (<http://openerp.com>).
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Affero General Public License as
|
||||
|
@ -366,44 +365,48 @@ class module(osv.osv):
|
|||
return True
|
||||
|
||||
def module_uninstall(self, cr, uid, ids, context=None):
|
||||
|
||||
# you have to uninstall in the right order, not all modules at the same time
|
||||
|
||||
model_data = self.pool.get('ir.model.data')
|
||||
remove_modules = map(lambda x: x.name, self.browse(cr, uid, ids, context))
|
||||
|
||||
data_ids = model_data.search(cr, uid, [('module', 'in', remove_modules)])
|
||||
|
||||
model_data._pre_process_unlink(cr, uid, data_ids, context)
|
||||
model_data.unlink(cr, uid, data_ids, context)
|
||||
|
||||
# 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)]
|
||||
data_ids = ir_model_data.search(cr, uid, [('module', 'in', modules_to_remove)])
|
||||
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 istead of loading, or both ?
|
||||
# should we call process_end instead of loading, or both ?
|
||||
return True
|
||||
|
||||
def check_dependancy(self, cr, uid, ids, context):
|
||||
res = []
|
||||
for module in self.browse(cr, uid, ids):
|
||||
cr.execute('''select m.id
|
||||
from
|
||||
ir_module_module_dependency d
|
||||
join
|
||||
ir_module_module m on (d.module_id=m.id)
|
||||
where
|
||||
d.name=%s and
|
||||
m.state not in ('uninstalled','uninstallable','to remove')''', (module.name,))
|
||||
res = cr.fetchall()
|
||||
return res
|
||||
def downstream_dependencies(self, cr, uid, ids, known_dep_ids=None,
|
||||
exclude_states=['uninstalled','uninstallable','to remove'],
|
||||
context=None):
|
||||
"""Return the ids of all modules that directly or indirectly depend
|
||||
on the given module `ids`, and that satisfy the `exclude_states`
|
||||
filter"""
|
||||
if not ids: return []
|
||||
known_dep_ids = set(known_dep_ids or [])
|
||||
cr.execute('''SELECT DISTINCT m.id
|
||||
FROM
|
||||
ir_module_module_dependency d
|
||||
JOIN
|
||||
ir_module_module m ON (d.module_id=m.id)
|
||||
WHERE
|
||||
d.name IN (SELECT name from ir_module_module where id in %s) AND
|
||||
m.state NOT IN %s AND
|
||||
m.id NOT IN %s ''',
|
||||
(tuple(ids),tuple(exclude_states), tuple(known_dep_ids or ids)))
|
||||
new_dep_ids = set([m[0] for m in cr.fetchall()])
|
||||
missing_mod_ids = new_dep_ids - known_dep_ids
|
||||
known_dep_ids |= new_dep_ids
|
||||
if missing_mod_ids:
|
||||
known_dep_ids |= set(self.downstream_dependencies(cr, uid, list(missing_mod_ids),
|
||||
known_dep_ids, exclude_states,context))
|
||||
return list(known_dep_ids)
|
||||
|
||||
def button_uninstall(self, cr, uid, ids, context=None):
|
||||
res = self.check_dependancy(cr, uid, ids, context)
|
||||
for i in range(0,len(res)):
|
||||
res_depend = self.check_dependancy(cr, uid, [res[i][0]], context)
|
||||
for j in range(0,len(res_depend)):
|
||||
ids.append(res_depend[j][0])
|
||||
ids.append(res[i][0])
|
||||
self.write(cr, uid, ids, {'state': 'to remove'})
|
||||
if any(m.name == 'base' for m in self.browse(cr, uid, ids)):
|
||||
raise orm.except_orm(_('Error'), _("The `base` module cannot be uninstalled"))
|
||||
dep_ids = self.downstream_dependencies(cr, uid, ids, context=context)
|
||||
self.write(cr, uid, ids + dep_ids, {'state': 'to remove'})
|
||||
return dict(ACTION_DICT, name=_('Uninstall'))
|
||||
|
||||
def button_uninstall_cancel(self, cr, uid, ids, context=None):
|
||||
|
|
Loading…
Reference in New Issue