Skip to content

Commit aec1a38

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 aec1a38

File tree

3 files changed

+52
-22
lines changed

3 files changed

+52
-22
lines changed

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

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

44
def migrate(cr, version):
55
cr.execute(
@@ -13,3 +13,4 @@ def migrate(cr, version):
1313
WHERE EXCLUDED.value::timestamp - ir_config_parameter.value::timestamp > interval '72 hours'
1414
"""
1515
)
16+
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: 48 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -342,6 +342,8 @@ 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)
346+
345347

346348

347349
def remove_theme(cr, theme, base_theme=None):
@@ -362,6 +364,7 @@ def remove_theme(cr, theme, base_theme=None):
362364

363365
ENVIRON["__modules_auto_discovery_force_installs"].pop(theme, None)
364366
ENVIRON["__modules_auto_discovery_force_upgrades"].pop(theme, None)
367+
ENVIRON["__modules_to_skip_autoinstall"].discard(theme)
365368

366369

367370
def _update_view_key(cr, old, new):
@@ -415,6 +418,10 @@ def rename_module(cr, old, new):
415418
fu = ENVIRON["__modules_auto_discovery_force_upgrades"]
416419
if old in fu:
417420
fu[new] = fu.pop(old)
421+
si = ENVIRON["__modules_to_skip_autoinstall"]
422+
if old in si:
423+
si.discard(old)
424+
si.add(new)
418425

419426

420427
@_warn_usage_outside_base
@@ -450,6 +457,10 @@ def merge_module(cr, old, into, update_dependers=True):
450457
version = fu[old][1] if parse_version(fu[old][1]) < parse_version(fu[into][1]) else fu[into][1]
451458
del fu[old]
452459
fu[into] = (init, version)
460+
si = ENVIRON["__modules_to_skip_autoinstall"]
461+
if old in si and into in si:
462+
si.discard(old)
463+
453464

454465
if old not in mod_ids:
455466
# this can happen in case of temp modules added after a release if the database does not
@@ -721,14 +732,20 @@ def _force_install_module(cr, module, if_installed=None, reason="it has been exp
721732
[toinstall, list(INSTALLED_MODULE_STATES)],
722733
)
723734
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-
)
735+
if mod in ENVIRON["__modules_to_skip_autoinstall"]:
736+
_logger.info((
737+
"Skipping the auto installation of module {} after all its auto install dependencies were installed by "
738+
"the force install of {}, because it was previously uninstalled."
739+
).format(mod, module))
740+
else:
741+
_force_install_module(
742+
cr,
743+
mod,
744+
reason=(
745+
"it is an auto install module that got all its auto install dependencies installed "
746+
"by the force install of {!r}"
747+
).format(module),
748+
)
732749

733750
# TODO handle module exclusions
734751

@@ -828,10 +845,20 @@ def module_auto_install(cr, module, auto_install):
828845
@_warn_usage_outside_base
829846
def trigger_auto_install(cr, module):
830847
_assert_modules_exists(cr, module)
848+
to_autoinstall = _get_autoinstallable_modules(cr, module)
849+
if to_autoinstall:
850+
if module in ENVIRON["__modules_to_skip_autoinstall"]:
851+
_logger.info("Skipping the auto installation of module {} because it was previously uninstalled.".format(module))
852+
return False
853+
force_install_module(cr, module, reason="it's an auto install module and all its dependencies are installed")
854+
return True
855+
return False
856+
857+
def _get_autoinstallable_modules(cr, module=None):
831858
if AUTO_INSTALL == "none":
832-
return False
859+
return set()
833860

834-
dep_match = "true"
861+
dep_match = "TRUE"
835862
if column_exists(cr, "ir_module_module_dependency", "auto_install_required"):
836863
dep_match = "d.auto_install_required = true"
837864

@@ -856,34 +883,35 @@ def trigger_auto_install(cr, module):
856883
)
857884
"""
858885

859-
cat_match = "true"
886+
cat_match = "TRUE"
860887
if AUTO_INSTALL == "only_link_modules":
861888
# even if we skip auto installs, we still need to auto install the real link-modules.
862889
# those are in the "Hidden" category
863890
hidden = ref(cr, "base.module_category_hidden")
864891
cat_match = cr.mogrify("m.category_id = %s", [hidden]).decode()
865892

893+
name_match = "TRUE"
894+
if module:
895+
name_match = cr.mogrify("m.name = %s", [module]).decode()
896+
866897
query = """
867-
SELECT m.id
898+
SELECT m.name
868899
FROM ir_module_module_dependency d
869900
JOIN ir_module_module m ON m.id = d.module_id
870901
JOIN ir_module_module md ON md.name = d.name
871902
{}
872-
WHERE m.name = %s
903+
WHERE {}
873904
AND m.state = 'uninstalled'
874905
AND m.auto_install = true
875906
AND {}
876907
AND {}
877-
GROUP BY m.id
908+
GROUP BY m.name
878909
HAVING bool_and(md.state IN %s)
879910
{}
880-
""".format(country_join, dep_match, cat_match, country_match)
911+
""".format(country_join, name_match, dep_match, cat_match, country_match)
881912

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
913+
cr.execute(query, [INSTALLED_MODULE_STATES])
914+
return set(m[0] for m in cr.fetchall())
887915

888916

889917
def _set_module_category(cr, module, category):

0 commit comments

Comments
 (0)