Skip to content

Commit 005e6a3

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 005e6a3

File tree

3 files changed

+61
-19
lines changed

3 files changed

+61
-19
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: 57 additions & 18 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 %r despite having all its auto install dependencies installed "
737+
"by the force install of %r, 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,8 +847,19 @@ 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 %r 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

834864
dep_match = "true"
835865
if column_exists(cr, "ir_module_module_dependency", "auto_install_required"):
@@ -863,27 +893,36 @@ def trigger_auto_install(cr, module):
863893
hidden = ref(cr, "base.module_category_hidden")
864894
cat_match = cr.mogrify("m.category_id = %s", [hidden]).decode()
865895

866-
query = """
867-
SELECT m.id
896+
name_match = "true"
897+
if module:
898+
name_match = cr.mogrify("m.name = %s", [module]).decode()
899+
900+
query = format_query(
901+
cr,
902+
"""
903+
SELECT m.name
868904
FROM ir_module_module_dependency d
869905
JOIN ir_module_module m ON m.id = d.module_id
870906
JOIN ir_module_module md ON md.name = d.name
871907
{}
872-
WHERE m.name = %s
908+
WHERE {}
873909
AND m.state = 'uninstalled'
874910
AND m.auto_install = true
875911
AND {}
876912
AND {}
877913
GROUP BY m.id
878914
HAVING bool_and(md.state IN %s)
879915
{}
880-
""".format(country_join, dep_match, cat_match, country_match)
916+
""",
917+
SQLStr(country_join),
918+
SQLStr(name_match),
919+
SQLStr(dep_match),
920+
SQLStr(cat_match),
921+
SQLStr(country_match),
922+
)
881923

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
924+
cr.execute(query, [INSTALLED_MODULE_STATES])
925+
return {m[0] for m in cr.fetchall()}
887926

888927

889928
def _set_module_category(cr, module, category):

0 commit comments

Comments
 (0)