Skip to content

Commit 4c2b786

Browse files
committed
[IMP] modules: skip autoinstall of unintalled modules
In the case where an autoninstall module is uninstalled by users prior to the upgrade start, this module could be reinstalled during the upgrade if there were dependency changes and those dependencies get force installed. This improvement keeps track of any module that was elligible for autoinstall before the upgrade starts and skips its force installation when dependencies change.
1 parent 3fcc237 commit 4c2b786

File tree

3 files changed

+55
-21
lines changed

3 files changed

+55
-21
lines changed

src/base/0.0.0/pre-00-upgrade-start.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
# -*- coding: utf-8 -*-
1+
from odoo.addons.base.maintenance.migrations import util
2+
from odoo.addons.base.maintenance.migrations.util.modules import _get_autoinstallable_modules
23

34

45
def migrate(cr, version):
@@ -13,3 +14,4 @@ def migrate(cr, version):
1314
WHERE EXCLUDED.value::timestamp - ir_config_parameter.value::timestamp > interval '72 hours'
1415
"""
1516
)
17+
util.ENVIRON["__modules_to_skip_autoinstall"] = _get_autoinstallable_modules(cr)

src/util/const.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
"__renamed_fields": collections.defaultdict(dict),
1414
"__modules_auto_discovery_force_installs": {},
1515
"__modules_auto_discovery_force_upgrades": {},
16+
"__modules_to_skip_autoinstall": set(),
1617
"__fix_fk_allowed_cascade": [],
1718
"__no_model_data_delete": {},
1819
}

src/util/modules.py

Lines changed: 51 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -342,6 +342,7 @@ def remove_module(cr, module):
342342

343343
ENVIRON["__modules_auto_discovery_force_installs"].pop(module, None)
344344
ENVIRON["__modules_auto_discovery_force_upgrades"].pop(module, None)
345+
ENVIRON["__modules_to_skip_autoinstall"].discard(module)
345346

346347

347348
def remove_theme(cr, theme, base_theme=None):
@@ -362,6 +363,7 @@ def remove_theme(cr, theme, base_theme=None):
362363

363364
ENVIRON["__modules_auto_discovery_force_installs"].pop(theme, None)
364365
ENVIRON["__modules_auto_discovery_force_upgrades"].pop(theme, None)
366+
ENVIRON["__modules_to_skip_autoinstall"].discard(theme)
365367

366368

367369
def _update_view_key(cr, old, new):
@@ -415,6 +417,10 @@ def rename_module(cr, old, new):
415417
fu = ENVIRON["__modules_auto_discovery_force_upgrades"]
416418
if old in fu:
417419
fu[new] = fu.pop(old)
420+
si = ENVIRON["__modules_to_skip_autoinstall"]
421+
if old in si:
422+
si.discard(old)
423+
si.add(new)
418424

419425

420426
@_warn_usage_outside_base
@@ -450,6 +456,9 @@ def merge_module(cr, old, into, update_dependers=True):
450456
version = fu[old][1] if parse_version(fu[old][1]) < parse_version(fu[into][1]) else fu[into][1]
451457
del fu[old]
452458
fu[into] = (init, version)
459+
si = ENVIRON["__modules_to_skip_autoinstall"]
460+
if old in si and into in si:
461+
si.discard(old)
453462

454463
if old not in mod_ids:
455464
# this can happen in case of temp modules added after a release if the database does not
@@ -721,14 +730,24 @@ def _force_install_module(cr, module, if_installed=None, reason="it has been exp
721730
[toinstall, list(INSTALLED_MODULE_STATES)],
722731
)
723732
for (mod,) in cr.fetchall():
724-
_force_install_module(
725-
cr,
726-
mod,
727-
reason=(
728-
"it is an auto install module that got all its auto install dependencies installed "
729-
"by the force install of {!r}"
730-
).format(module),
731-
)
733+
if mod in ENVIRON["__modules_to_skip_autoinstall"]:
734+
_logger.info(
735+
(
736+
"Skipping the auto installation of module %s after all its auto install dependencies were installed by "
737+
"the force install of %s, because it was previously uninstalled."
738+
),
739+
mod,
740+
module,
741+
)
742+
else:
743+
_force_install_module(
744+
cr,
745+
mod,
746+
reason=(
747+
"it is an auto install module that got all its auto install dependencies installed "
748+
"by the force install of {!r}"
749+
).format(module),
750+
)
732751

733752
# TODO handle module exclusions
734753

@@ -828,10 +847,21 @@ def module_auto_install(cr, module, auto_install):
828847
@_warn_usage_outside_base
829848
def trigger_auto_install(cr, module):
830849
_assert_modules_exists(cr, module)
850+
to_autoinstall = _get_autoinstallable_modules(cr, module)
851+
if to_autoinstall:
852+
if module in ENVIRON["__modules_to_skip_autoinstall"]:
853+
_logger.info("Skipping the auto installation of module %s because it was previously uninstalled.", module)
854+
return False
855+
force_install_module(cr, module, reason="it's an auto install module and all its dependencies are installed")
856+
return True
857+
return False
858+
859+
860+
def _get_autoinstallable_modules(cr, module=None):
831861
if AUTO_INSTALL == "none":
832-
return False
862+
return set()
833863

834-
dep_match = "true"
864+
dep_match = "TRUE"
835865
if column_exists(cr, "ir_module_module_dependency", "auto_install_required"):
836866
dep_match = "d.auto_install_required = true"
837867

@@ -856,34 +886,35 @@ def trigger_auto_install(cr, module):
856886
)
857887
"""
858888

859-
cat_match = "true"
889+
cat_match = "TRUE"
860890
if AUTO_INSTALL == "only_link_modules":
861891
# even if we skip auto installs, we still need to auto install the real link-modules.
862892
# those are in the "Hidden" category
863893
hidden = ref(cr, "base.module_category_hidden")
864894
cat_match = cr.mogrify("m.category_id = %s", [hidden]).decode()
865895

896+
name_match = "TRUE"
897+
if module:
898+
name_match = cr.mogrify("m.name = %s", [module]).decode()
899+
866900
query = """
867-
SELECT m.id
901+
SELECT m.name
868902
FROM ir_module_module_dependency d
869903
JOIN ir_module_module m ON m.id = d.module_id
870904
JOIN ir_module_module md ON md.name = d.name
871905
{}
872-
WHERE m.name = %s
906+
WHERE {}
873907
AND m.state = 'uninstalled'
874908
AND m.auto_install = true
875909
AND {}
876910
AND {}
877-
GROUP BY m.id
911+
GROUP BY m.name
878912
HAVING bool_and(md.state IN %s)
879913
{}
880-
""".format(country_join, dep_match, cat_match, country_match)
914+
""".format(country_join, name_match, dep_match, cat_match, country_match)
881915

882-
cr.execute(query, [module, INSTALLED_MODULE_STATES])
883-
if cr.rowcount:
884-
force_install_module(cr, module, reason="it's an auto install module and all its dependencies are installed")
885-
return True
886-
return False
916+
cr.execute(query, [INSTALLED_MODULE_STATES])
917+
return {m[0] for m in cr.fetchall()}
887918

888919

889920
def _set_module_category(cr, module, category):

0 commit comments

Comments
 (0)